use of com.linkedin.r2.message.stream.entitystream.ByteStringWriter in project rest.li by linkedin.
the class TestNettyRequestAdapter method testStreamToHttp2HeadersPseudoHeaders.
@Test
public void testStreamToHttp2HeadersPseudoHeaders() throws Exception {
StreamRequestBuilder streamRequestBuilder = new StreamRequestBuilder(new URI(ANY_URI));
StreamRequest request = streamRequestBuilder.build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(ANY_ENTITY.getBytes()))));
Http2Headers headers = NettyRequestAdapter.toHttp2Headers(request);
Assert.assertNotNull(headers);
Assert.assertEquals(headers.authority(), "localhost:8080");
Assert.assertEquals(headers.method(), "GET");
Assert.assertEquals(headers.path(), "/foo/bar?q=baz");
Assert.assertEquals(headers.scheme(), "http");
}
use of com.linkedin.r2.message.stream.entitystream.ByteStringWriter in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testChannelReusedAfterStreamingTimeout.
/**
* When a request fails due to {@link TimeoutException}, connection should not be destroyed.
* @throws Exception
*/
@Test(timeOut = TEST_TIMEOUT, retryAnalyzer = SingleRetry.class)
public void testChannelReusedAfterStreamingTimeout() throws Exception {
final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
final TransportResponse<StreamResponse> response1;
final TransportResponse<StreamResponse> response2;
try {
server.start();
final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
response1 = callback1.get();
Assert.assertNotNull(response1);
Assert.assertFalse(response1.hasError());
response1.getResponse().getEntityStream().setReader(new TimeoutReader());
final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
response2 = callback2.get();
} finally {
server.stop();
}
// The 2nd request should succeed
Assert.assertNotNull(response2);
Assert.assertFalse(response2.hasError());
response2.getResponse().getEntityStream().setReader(new DrainReader());
// The server should have seen 3 requests but establishes only 1 connection with the client
Assert.assertEquals(statsProvider.requestCount(), 3);
Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
use of com.linkedin.r2.message.stream.entitystream.ByteStringWriter in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testMaxConcurrentStreamExhaustion.
/**
* When the maximum number of concurrent streams is exhausted, the client is expected to throw
* an {@link StreamException} immediately.
*/
@Test(timeOut = TEST_TIMEOUT)
public void testMaxConcurrentStreamExhaustion() throws Exception {
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.maxConcurrentStreams(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.buildHttp2StreamClient();
final FutureTransportCallback<StreamResponse> callback = new FutureTransportCallback<>();
final TransportResponse<StreamResponse> response;
try {
server.start();
// Sends the stream request
final StreamRequestBuilder builder = new StreamRequestBuilder(new URI(URL));
final StreamRequest request = builder.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
client.streamRequest(request, new RequestContext(), new HashMap<>(), callback);
response = callback.get();
} finally {
server.stop();
}
Assert.assertNotNull(response);
Assert.assertTrue(response.hasError());
Assert.assertNotNull(response.getError());
ExceptionTestUtil.verifyCauseChain(response.getError(), Http2Exception.StreamException.class);
}
use of com.linkedin.r2.message.stream.entitystream.ByteStringWriter in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testChannelReusedAfterRequestTimeout.
/**
* When a request fails due to {@link TimeoutException}, connection should not be destroyed.
* @throws Exception
*/
@Test(timeOut = TEST_TIMEOUT)
public void testChannelReusedAfterRequestTimeout() throws Exception {
final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
final TransportResponse<StreamResponse> response1;
final TransportResponse<StreamResponse> response2;
try {
server.start();
final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new TimeoutWriter()));
final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
response1 = callback1.get();
final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
response2 = callback2.get();
} finally {
server.stop();
}
// The 1st request should be failed with timeout
Assert.assertNotNull(response1);
Assert.assertTrue(response1.hasError());
Assert.assertNotNull(response1.getError());
ExceptionTestUtil.verifyCauseChain(response1.getError(), TimeoutException.class);
// The 2nd request should succeed
Assert.assertNotNull(response2);
Assert.assertFalse(response2.hasError());
response2.getResponse().getEntityStream().setReader(new DrainReader());
// The server should have seen 2 requests but establishes only 1 connection with the client
Assert.assertEquals(statsProvider.requestCount(), 3);
Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
use of com.linkedin.r2.message.stream.entitystream.ByteStringWriter in project rest.li by linkedin.
the class RestClient method buildStreamRequest.
private StreamRequest buildStreamRequest(URI uri, ResourceMethod method, DataMap dataMap, Map<String, String> headers, List<String> cookies, ProtocolVersion protocolVersion, ContentType contentType, List<ContentType> acceptTypes, boolean acceptResponseAttachments, List<Object> streamingAttachments) throws Exception {
StreamRequestBuilder requestBuilder = new StreamRequestBuilder(uri).setMethod(method.getHttpMethod().toString());
requestBuilder.setHeaders(headers);
requestBuilder.setCookies(cookies);
addAcceptHeaders(requestBuilder, acceptTypes, acceptResponseAttachments);
addProtocolVersionHeader(requestBuilder, protocolVersion);
if (method.getHttpMethod() == HttpMethod.POST) {
requestBuilder.setHeader(RestConstants.HEADER_RESTLI_REQUEST_METHOD, method.toString());
}
final ContentType type = resolveContentType(requestBuilder, dataMap, contentType, uri);
// This request builders enforce this invariant.
if (streamingAttachments != null) {
final ByteStringWriter firstPartWriter;
// with empty action parameters will have an empty JSON ({}) as the body.
assert (type != null);
firstPartWriter = new ByteStringWriter(type.getCodec().mapToByteString(dataMap));
// Our protocol does not use an epilogue or a preamble.
final MultiPartMIMEWriter.Builder attachmentsBuilder = new MultiPartMIMEWriter.Builder();
for (final Object dataSource : streamingAttachments) {
assert (dataSource instanceof RestLiAttachmentDataSourceWriter || dataSource instanceof RestLiDataSourceIterator);
if (dataSource instanceof RestLiAttachmentDataSourceWriter) {
AttachmentUtils.appendSingleAttachmentToBuilder(attachmentsBuilder, (RestLiAttachmentDataSourceWriter) dataSource);
} else {
AttachmentUtils.appendMultipleAttachmentsToBuilder(attachmentsBuilder, (RestLiDataSourceIterator) dataSource);
}
}
final MultiPartMIMEWriter multiPartMIMEWriter = AttachmentUtils.createMultiPartMIMEWriter(firstPartWriter, type.getHeaderKey(), attachmentsBuilder);
final String contentTypeHeader = MultiPartMIMEUtils.buildMIMEContentTypeHeader(AttachmentUtils.RESTLI_MULTIPART_SUBTYPE, multiPartMIMEWriter.getBoundary(), Collections.emptyMap());
requestBuilder.setHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER, contentTypeHeader);
return requestBuilder.build(multiPartMIMEWriter.getEntityStream());
} else {
if (dataMap != null && type != null && type.supportsStreaming()) {
requestBuilder.setHeader(RestConstants.HEADER_CONTENT_TYPE, type.getHeaderKey());
return requestBuilder.build(EntityStreamAdapters.fromGenericEntityStream(type.getStreamCodec().encodeMap(dataMap)));
} else {
return Messages.toStreamRequest(buildRestRequest(uri, method, dataMap, headers, cookies, protocolVersion, contentType, acceptTypes, acceptResponseAttachments));
}
}
}
Aggregations