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()));
}
}
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());
}
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);
}
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;
}
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();
}
}
});
}
Aggregations