use of io.servicetalk.http.api.StreamingHttpResponseFactory in project servicetalk by apple.
the class TestServiceStreaming method newEchoResponse.
private static StreamingHttpResponse newEchoResponse(final StreamingHttpRequest req, final StreamingHttpResponseFactory factory) {
final StreamingHttpResponse response = factory.ok().version(req.version()).transformMessageBody(pub -> pub.ignoreElements().merge(req.messageBody())).transform(new StatelessTrailersTransformer<>());
final CharSequence contentLength = req.headers().get(CONTENT_LENGTH);
if (contentLength != null) {
response.addHeader(CONTENT_LENGTH, contentLength);
}
final CharSequence contentType = req.headers().get(CONTENT_TYPE);
if (contentType != null) {
response.addHeader(CONTENT_TYPE, contentType);
}
final CharSequence transferEncoding = req.headers().get(TRANSFER_ENCODING);
if (transferEncoding != null) {
response.addHeader(TRANSFER_ENCODING, transferEncoding);
}
return response;
}
use of io.servicetalk.http.api.StreamingHttpResponseFactory in project servicetalk by apple.
the class TestServiceStreaming method handle.
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext context, final StreamingHttpRequest req, final StreamingHttpResponseFactory factory) {
LOGGER.debug("({}) Handling {}", counter, req.toString((a, b) -> b));
final StreamingHttpResponse response;
switch(req.path()) {
case SVC_ECHO:
response = newEchoResponse(req, factory);
break;
case SVC_COUNTER_NO_LAST_CHUNK:
response = newTestCounterResponse(context, req, factory);
break;
case SVC_COUNTER:
response = newTestCounterResponseWithLastPayloadChunk(context, req, factory);
break;
case SVC_LARGE_LAST:
response = newLargeLastChunkResponse(context, req, factory);
break;
case SVC_TEST_PUBLISHER:
response = newTestPublisherResponse(req, factory);
break;
case SVC_NO_CONTENT:
response = newNoContentResponse(req, factory);
break;
case SVC_NO_CONTENT_AFTER_READ:
return req.payloadBody().ignoreElements().concat(succeeded(newNoContentResponse(req, factory)));
case SVC_ROT13:
response = newRot13Response(req, factory);
break;
case SVC_NEVER:
return req.payloadBody().ignoreElements().concat(never());
case SVC_THROW_ERROR:
response = throwErrorSynchronously();
break;
case SVC_SINGLE_ERROR:
return Single.failed(DELIBERATE_EXCEPTION);
case SVC_ERROR_BEFORE_READ:
response = throwErrorBeforeRead(req, factory);
break;
case SVC_ERROR_DURING_READ:
response = throwErrorDuringRead(req, factory);
break;
default:
response = newNotFoundResponse(req, factory);
}
return succeeded(response);
}
use of io.servicetalk.http.api.StreamingHttpResponseFactory in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method queryParams.
private void queryParams(final HttpRequestMethod method) throws Exception {
final String qpName = "foo";
InetSocketAddress serverAddress = bindHttpEchoServer(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
return request.queryParameter(qpName) == null ? succeeded(responseFactory.badRequest()) : super.handle(ctx, request, responseFactory);
}
}, null);
String responseBody = "hello world";
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildBlocking()) {
HttpResponse response = client.request(client.newRequest(method, "/p").addQueryParameters(qpName, "bar")).payloadBody(responseBody, textSerializerUtf8());
assertThat("Unexpected response status.", response.status(), equalTo(OK));
}
}
use of io.servicetalk.http.api.StreamingHttpResponseFactory in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method serverGracefulClose.
@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void serverGracefulClose(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
setUp(strategy, h2PriorKnowledge);
CountDownLatch serverReceivedRequestLatch = new CountDownLatch(1);
CountDownLatch connectionOnClosingLatch = new CountDownLatch(1);
InetSocketAddress serverAddress = bindHttpEchoServer(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
serverReceivedRequestLatch.countDown();
return delegate().handle(ctx, request, responseFactory);
}
}, connectionOnClosingLatch);
StreamingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildStreaming();
Processor<Buffer, Buffer> requestBody = newProcessor();
// We want to make a request, and intentionally not complete it. While the request is in process we invoke
// closeAsyncGracefully and verify that we wait until the request has completed before the underlying
// transport is closed.
StreamingHttpRequest request = client.post("/").payloadBody(fromSource(requestBody));
StreamingHttpResponse response = client.request(request).toFuture().get();
// Wait for the server the process the request.
serverReceivedRequestLatch.await();
// Initiate graceful close on the server
assertNotNull(h1ServerContext);
CountDownLatch onServerCloseLatch = new CountDownLatch(1);
h1ServerContext.onClose().subscribe(onServerCloseLatch::countDown);
h1ServerContext.closeAsyncGracefully().subscribe();
assertTrue(connectionOnClosingLatch.await(300, MILLISECONDS));
try (BlockingHttpClient client2 = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildBlocking()) {
assertThrows(Throwable.class, () -> client2.request(client2.get("/")), "server has initiated graceful close, subsequent connections/requests are expected to fail.");
}
// We expect this to timeout, because we have not completed the outstanding request.
assertFalse(onServerCloseLatch.await(30, MILLISECONDS));
requestBody.onComplete();
HttpResponse fullResponse = response.toResponse().toFuture().get();
assertEquals(0, fullResponse.payloadBody().readableBytes());
onServerCloseLatch.await();
}
use of io.servicetalk.http.api.StreamingHttpResponseFactory in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method serverSendsInvalidContentLength.
private void serverSendsInvalidContentLength(boolean addTrailers, BiConsumer<HttpHeaders, Integer> headersModifier) throws Exception {
assumeFalse(!h2PriorKnowledge && addTrailers, "HTTP/1.1 does not support Content-Length with trailers");
InetSocketAddress serverAddress = bindHttpEchoServer(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
return delegate().handle(ctx, request, responseFactory).flatMap(resp -> resp.transformMessageBody(// honored during "streaming -> aggregated -> streaming" conversion.
pub -> addTrailers ? pub : pub.filter(i -> i instanceof Buffer)).toResponse().map(aggResp -> {
aggResp.headers().remove(TRANSFER_ENCODING);
headersModifier.accept(aggResp.headers(), aggResp.payloadBody().readableBytes());
return aggResp.toStreamingResponse();
}));
}
}, null);
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildBlocking()) {
HttpRequest request = client.get("/").payloadBody("a", textSerializerUtf8());
if (addTrailers) {
request.trailers().set("mytrailer", "myvalue");
}
if (h2PriorKnowledge) {
assertThrows(Http2Exception.class, () -> client.request(request));
} else {
try (ReservedBlockingHttpConnection reservedConn = client.reserveConnection(request)) {
assertThrows(IOException.class, () -> {
// Either the current request or the next one should fail
reservedConn.request(request);
reservedConn.request(client.get("/"));
});
}
}
}
}
Aggregations