use of com.linkedin.data.ByteString in project rest.li by linkedin.
the class AbstractR2Servlet method writeToServletResponse.
protected void writeToServletResponse(TransportResponse<RestResponse> response, HttpServletResponse resp) throws IOException {
Map<String, String> wireAttrs = response.getWireAttributes();
for (Map.Entry<String, String> e : WireAttributeHelper.toWireAttributes(wireAttrs).entrySet()) {
resp.setHeader(e.getKey(), e.getValue());
}
RestResponse restResponse = null;
if (response.hasError()) {
Throwable e = response.getError();
if (e instanceof RestException) {
restResponse = ((RestException) e).getResponse();
}
if (restResponse == null) {
restResponse = RestStatus.responseForError(RestStatus.INTERNAL_SERVER_ERROR, e);
}
} else {
restResponse = response.getResponse();
}
resp.setStatus(restResponse.getStatus());
Map<String, String> headers = restResponse.getHeaders();
for (Map.Entry<String, String> e : headers.entrySet()) {
// TODO multi-valued headers
resp.setHeader(e.getKey(), e.getValue());
}
for (String cookie : restResponse.getCookies()) {
resp.addHeader(HttpConstants.RESPONSE_COOKIE_HEADER_NAME, cookie);
}
final ByteString entity = restResponse.getEntity();
entity.write(resp.getOutputStream());
resp.getOutputStream().close();
}
use of com.linkedin.data.ByteString in project rest.li by linkedin.
the class HttpDispatcher method handleRequest.
/**
* handle a {@link com.linkedin.r2.message.stream.StreamRequest} using the given request context.
* @see com.linkedin.r2.transport.common.bridge.server.TransportDispatcher#handleStreamRequest
*
* @param req the request to be handled.
* @param context the request context.
* @param callback the callback to be invoked with the response or error.
*/
public void handleRequest(StreamRequest req, RequestContext context, final TransportCallback<StreamResponse> callback) {
markOnRequestTimings(context);
final Map<String, String> headers = new HashMap<>(req.getHeaders());
final Map<String, String> wireAttrs = WireAttributeHelper.removeWireAttributes(headers);
final BaseConnector connector = new BaseConnector();
try {
MessageType.Type msgType = MessageType.getMessageType(wireAttrs, MessageType.Type.REST);
switch(msgType) {
default:
case REST:
req.getEntityStream().setReader(connector);
StreamRequest newReq = req.builder().build(EntityStreams.newEntityStream(connector));
// decorate the call back so that if response is error or response finishes streaming,
// we cancel the request stream
TransportCallback<StreamResponse> decorateCallback = new TransportCallback<StreamResponse>() {
@Override
public void onResponse(TransportResponse<StreamResponse> response) {
// no need to check StreamException because that's handled by HttpBridge.httpToStreamCallback
if (response.hasError()) {
connector.cancel();
} else {
Observer observer = new Observer() {
@Override
public void onDataAvailable(ByteString data) {
// do nothing
}
@Override
public void onDone() {
connector.cancel();
}
@Override
public void onError(Throwable e) {
connector.cancel();
}
};
response.getResponse().getEntityStream().addObserver(observer);
}
callback.onResponse(response);
}
};
_dispatcher.handleStreamRequest(HttpBridge.toStreamRequest(newReq, headers), wireAttrs, context, HttpBridge.httpToStreamCallback(decorateCallback));
}
} catch (Exception e) {
connector.cancel();
callback.onResponse(TransportResponseImpl.<StreamResponse>error(e, Collections.<String, String>emptyMap()));
}
}
use of com.linkedin.data.ByteString in project rest.li by linkedin.
the class ServletHelper method writeToServletError.
static void writeToServletError(HttpServletResponse resp, int statusCode, String message) throws IOException {
RestResponse restResponse = RestStatus.responseForStatus(statusCode, message);
writeResponseHeadersToServletResponse(TransportResponseImpl.success(Messages.toStreamResponse(restResponse)), resp);
final ByteString entity = restResponse.getEntity();
entity.write(resp.getOutputStream());
resp.getOutputStream().close();
}
use of com.linkedin.data.ByteString in project rest.li by linkedin.
the class SyncIOHandler method eventLoop.
private void eventLoop() throws ServletException, IOException, InterruptedException, TimeoutException {
final long startTime = System.currentTimeMillis();
byte[] buf = new byte[DEFAULT_DATA_CHUNK_SIZE];
while (shouldContinue() && !_forceExit) {
long timeSpent = System.currentTimeMillis() - startTime;
long maxWaitTime = timeSpent < _timeout ? _timeout - timeSpent : 0;
Event event = _eventQueue.poll(maxWaitTime, TimeUnit.MILLISECONDS);
if (event == null) {
throw new TimeoutException("Timeout after " + _timeout + " milliseconds.");
}
switch(event.getEventType()) {
case ResponseDataAvailable:
{
ByteString data = (ByteString) event.getData();
data.write(_os);
_rh.request(1);
break;
}
case WriteRequestPossible:
{
while (_wh.remaining() > 0) {
final int actualLen = _is.read(buf);
if (actualLen < 0) {
_wh.done();
_requestReadFinished = true;
break;
}
_wh.write(ByteString.copy(buf, 0, actualLen));
}
break;
}
case FullResponseReceived:
{
_os.close();
_responseWriteFinished = true;
break;
}
case ResponseDataError:
{
_os.close();
_responseWriteFinished = true;
break;
}
case WriteRequestAborted:
{
if (event.getData() instanceof AbortedException) {
// reader cancels, we'll drain the stream on behalf of reader
// we don't directly drain it here because we'd like to give other events
// some opportunities to be executed; e.g. return an error response
_eventQueue.add(Event.DrainRequestEvent);
} else {
// TODO: do we want to be smarter and return server error response?
throw new ServletException((Throwable) event.getData());
}
break;
}
case DrainRequest:
{
for (int i = 0; i < 10; i++) {
final int actualLen = _is.read(buf);
if (actualLen < 0) {
_requestReadFinished = true;
break;
}
}
if (!_requestReadFinished) {
// add self back to event queue and give others a chance to run
_eventQueue.add(Event.DrainRequestEvent);
}
break;
}
case ForceExit:
{
_forceExit = true;
break;
}
default:
throw new IllegalStateException("Unknown event type:" + event.getEventType());
}
}
}
use of com.linkedin.data.ByteString in project rest.li by linkedin.
the class TestHttpClient method testClient.
@Test
public void testClient() throws Exception {
RestRequestBuilder rb = new RestRequestBuilder(getHttpUri(DISPATCHER_URI));
rb.setMethod("GET");
RestRequest request = rb.build();
Future<RestResponse> f = _client.restRequest(request);
// This will block
RestResponse response = f.get();
final ByteString entity = response.getEntity();
if (entity != null) {
System.out.println(entity.asString("UTF-8"));
} else {
System.out.println("NOTHING!");
}
assertEquals(response.getStatus(), 200);
}
Aggregations