Search in sources :

Example 11 with TransportResponse

use of com.linkedin.r2.transport.common.bridge.common.TransportResponse in project rest.li by linkedin.

the class PipelineStreamHandler method channelRead0.

@Override
protected void channelRead0(ChannelHandlerContext ctx, RestRequest request) throws Exception {
    final Channel ch = ctx.channel();
    TransportCallback<StreamResponse> writeResponseCallback = new TransportCallback<StreamResponse>() {

        @Override
        public void onResponse(final TransportResponse<StreamResponse> response) {
            if (response.hasError()) {
                // This onError is only getting called in cases where:
                // (1) the exception was thrown by the handleRequest() method, and the upper layer
                // dispatcher did not catch the exception or caught it and passed it here without
                // turning it into a Response, or
                // (2) the HttpBridge-installed callback's onError declined to convert the exception to a
                // response and passed it along to here.
                writeError(ch, response, response.getError());
            } else {
                Messages.toRestResponse(response.getResponse(), new Callback<RestResponse>() {

                    @Override
                    public void onError(Throwable e) {
                        writeError(ch, response, e);
                    }

                    @Override
                    public void onSuccess(RestResponse result) {
                        writeResponse(ch, response, result);
                    }
                });
            }
        }
    };
    try {
        _dispatcher.handleRequest(Messages.toStreamRequest(request), writeResponseCallback);
    } catch (Exception ex) {
        writeResponseCallback.onResponse(TransportResponseImpl.<StreamResponse>error(ex, Collections.<String, String>emptyMap()));
    }
}
Also used : TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) RestResponse(com.linkedin.r2.message.rest.RestResponse) Channel(io.netty.channel.Channel) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse)

Example 12 with TransportResponse

use of com.linkedin.r2.transport.common.bridge.common.TransportResponse in project rest.li by linkedin.

the class PipelineStreamHandler method writeError.

private void writeError(Channel ch, TransportResponse<StreamResponse> response, Throwable ex) {
    RestResponseBuilder responseBuilder = new RestResponseBuilder(RestStatus.responseForError(RestStatus.INTERNAL_SERVER_ERROR, ex)).unsafeOverwriteHeaders(WireAttributeHelper.toWireAttributes(response.getWireAttributes()));
    ch.writeAndFlush(responseBuilder.build());
}
Also used : RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder)

Example 13 with TransportResponse

use of com.linkedin.r2.transport.common.bridge.common.TransportResponse in project rest.li by linkedin.

the class RetryTrackerClient method restRequest.

@Override
public void restRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, TransportCallback<RestResponse> callback) {
    TransportResponse<RestResponse> response;
    if (_uri.toString().startsWith("http://test.linkedin.com/retry")) {
        RetriableRequestException ex = new RetriableRequestException("Data not available");
        response = TransportResponseImpl.error(ex);
    } else if (_uri.toString().equals("http://test.linkedin.com/bad")) {
        response = TransportResponseImpl.error(RestException.forError(404, "exception happens"), wireAttrs);
    } else {
        response = TransportResponseImpl.success(new RestResponseBuilder().build(), wireAttrs);
    }
    callback.onResponse(response);
}
Also used : RetriableRequestException(com.linkedin.r2.RetriableRequestException) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder)

Example 14 with TransportResponse

use of com.linkedin.r2.transport.common.bridge.common.TransportResponse in project rest.li by linkedin.

the class ServletHelper method writeResponseHeadersToServletResponse.

static StreamResponse writeResponseHeadersToServletResponse(TransportResponse<StreamResponse> response, HttpServletResponse resp) {
    Map<String, String> wireAttrs = response.getWireAttributes();
    for (Map.Entry<String, String> e : WireAttributeHelper.toWireAttributes(wireAttrs).entrySet()) {
        resp.setHeader(e.getKey(), e.getValue());
    }
    StreamResponse streamResponse;
    if (response.hasError()) {
        Throwable e = response.getError();
        if (e instanceof StreamException) {
            streamResponse = ((StreamException) e).getResponse();
        } else {
            streamResponse = Messages.toStreamResponse(RestStatus.responseForError(RestStatus.INTERNAL_SERVER_ERROR, e));
        }
    } else {
        streamResponse = response.getResponse();
    }
    resp.setStatus(streamResponse.getStatus());
    Map<String, String> headers = streamResponse.getHeaders();
    for (Map.Entry<String, String> e : headers.entrySet()) {
        // TODO multi-valued headers
        resp.setHeader(e.getKey(), e.getValue());
    }
    for (String cookie : streamResponse.getCookies()) {
        resp.addHeader(HttpConstants.RESPONSE_COOKIE_HEADER_NAME, cookie);
    }
    return streamResponse;
}
Also used : StreamResponse(com.linkedin.r2.message.stream.StreamResponse) ByteString(com.linkedin.data.ByteString) Map(java.util.Map) StreamException(com.linkedin.r2.message.stream.StreamException)

Example 15 with TransportResponse

use of com.linkedin.r2.transport.common.bridge.common.TransportResponse in project rest.li by linkedin.

the class AbstractAsyncR2StreamServlet method service.

@Override
public void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    final AsyncContext ctx = req.startAsync(req, resp);
    ctx.setTimeout(_timeout);
    final WrappedAsyncContext wrappedCtx = new WrappedAsyncContext(ctx);
    final AsyncEventIOHandler ioHandler = new AsyncEventIOHandler(req.getInputStream(), resp.getOutputStream(), req.getRemoteAddr(), wrappedCtx, MAX_BUFFERED_CHUNKS, _logServletExceptions);
    final RequestContext requestContext = ServletHelper.readRequestContext(req);
    final StreamRequest streamRequest;
    try {
        streamRequest = ServletHelper.readFromServletRequest(req, ioHandler);
    } catch (URISyntaxException e) {
        ServletHelper.writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
        wrappedCtx.complete();
        return;
    }
    final AtomicBoolean startedResponding = new AtomicBoolean(false);
    ctx.addListener(new AsyncListener() {

        @Override
        public void onTimeout(AsyncEvent event) throws IOException {
            LOG.error("Server timeout for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server timeout response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server timeout");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server timeout"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
        // Nothing to do here
        }

        @Override
        public void onError(AsyncEvent event) throws IOException {
            LOG.error("Server error for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server error response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server error");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server error"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onComplete(AsyncEvent event) throws IOException {
            Object exception = req.getAttribute(ASYNC_IOEXCEPTION);
            if (exception != null) {
                throw new IOException((Throwable) exception);
            }
        }
    });
    final TransportCallback<StreamResponse> callback = new TransportCallback<StreamResponse>() {

        @Override
        public void onResponse(final TransportResponse<StreamResponse> response) {
            if (startedResponding.compareAndSet(false, true)) {
                ctx.start(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            StreamResponse streamResponse = ServletHelper.writeResponseHeadersToServletResponse(response, resp);
                            streamResponse.getEntityStream().setReader(ioHandler);
                            ioHandler.loop();
                        } catch (Exception e) {
                            req.setAttribute(ASYNC_IOEXCEPTION, e);
                            wrappedCtx.complete();
                        }
                    }
                });
            } else {
                LOG.error("Dropped a response; this is mostly like because that AsyncContext timeout or error had already happened");
            }
        }
    };
    // we have to use a new thread and let this thread return to pool. otherwise the timeout won't start
    ctx.start(new Runnable() {

        @Override
        public void run() {
            try {
                getDispatcher().handleRequest(streamRequest, requestContext, callback);
                ioHandler.loop();
            } catch (Exception e) {
                req.setAttribute(ASYNC_IOEXCEPTION, e);
                wrappedCtx.complete();
            }
        }
    });
}
Also used : TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) AsyncContext(javax.servlet.AsyncContext) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) ServletException(javax.servlet.ServletException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AsyncListener(javax.servlet.AsyncListener) RequestContext(com.linkedin.r2.message.RequestContext)

Aggregations

StreamResponse (com.linkedin.r2.message.stream.StreamResponse)11 RequestContext (com.linkedin.r2.message.RequestContext)8 TransportResponse (com.linkedin.r2.transport.common.bridge.common.TransportResponse)8 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)7 TransportCallback (com.linkedin.r2.transport.common.bridge.common.TransportCallback)7 RestResponse (com.linkedin.r2.message.rest.RestResponse)6 ByteString (com.linkedin.data.ByteString)4 RestResponseBuilder (com.linkedin.r2.message.rest.RestResponseBuilder)4 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)4 HttpServerBuilder (com.linkedin.r2.testutils.server.HttpServerBuilder)4 URI (java.net.URI)4 URISyntaxException (java.net.URISyntaxException)4 Server (org.eclipse.jetty.server.Server)4 Test (org.testng.annotations.Test)4 ByteStringWriter (com.linkedin.r2.message.stream.entitystream.ByteStringWriter)3 FutureTransportCallback (com.linkedin.r2.transport.common.bridge.common.FutureTransportCallback)3 HttpClientBuilder (com.linkedin.r2.transport.http.client.HttpClientBuilder)3 RetriableRequestException (com.linkedin.r2.RetriableRequestException)2 RestRequest (com.linkedin.r2.message.rest.RestRequest)2 DrainReader (com.linkedin.r2.message.stream.entitystream.DrainReader)2