use of io.servicetalk.http.api.HttpPayloadWriter in project servicetalk by apple.
the class GracefulConnectionClosureHandlingTest method setUp.
void setUp(HttpProtocol protocol, boolean initiateClosureFromClient, boolean useUds, boolean viaProxy) throws Exception {
this.protocol = protocol;
this.initiateClosureFromClient = initiateClosureFromClient;
if (useUds) {
Assumptions.assumeTrue(SERVER_CTX.ioExecutor().isUnixDomainSocketSupported(), "Server's IoExecutor does not support UnixDomainSocket");
Assumptions.assumeTrue(CLIENT_CTX.ioExecutor().isUnixDomainSocketSupported(), "Client's IoExecutor does not support UnixDomainSocket");
assumeFalse(viaProxy, "UDS cannot be used via proxy");
}
assumeFalse(protocol == HTTP_2 && viaProxy, "Proxy is not supported with HTTP/2");
HttpServerBuilder serverBuilder = (useUds ? forAddress(newSocketAddress()) : forAddress(localAddress(0))).protocols(protocol.config).ioExecutor(SERVER_CTX.ioExecutor()).executor(SERVER_CTX.executor()).executionStrategy(defaultStrategy()).enableWireLogging("servicetalk-tests-wire-logger", TRACE, () -> true).appendConnectionAcceptorFilter(original -> new DelegatingConnectionAcceptor(original) {
@Override
public Completable accept(final ConnectionContext context) {
if (!initiateClosureFromClient) {
((NettyConnectionContext) context).onClosing().whenFinally(onClosing::countDown).subscribe();
}
context.onClose().whenFinally(serverConnectionClosed::countDown).subscribe();
connectionAccepted.countDown();
return completed();
}
});
HostAndPort proxyAddress = null;
if (viaProxy) {
// Dummy proxy helps to emulate old intermediate systems that do not support half-closed TCP connections
proxyTunnel = new ProxyTunnel();
proxyAddress = proxyTunnel.startProxy();
serverBuilder.sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, DefaultTestCerts::loadServerKey).build());
} else {
proxyTunnel = null;
}
serverContext = serverBuilder.listenBlockingStreamingAndAwait((ctx, request, response) -> {
serverReceivedRequest.countDown();
response.addHeader(CONTENT_LENGTH, valueOf(RESPONSE_CONTENT.length()));
serverSendResponse.await();
try (HttpPayloadWriter<String> writer = response.sendMetaData(RAW_STRING_SERIALIZER)) {
// Subscribe to the request payload body before response writer closes
BlockingIterator<Buffer> iterator = request.payloadBody().iterator();
// Consume request payload body asynchronously:
ctx.executionContext().executor().submit(() -> {
int receivedSize = 0;
while (iterator.hasNext()) {
Buffer chunk = iterator.next();
assert chunk != null;
receivedSize += chunk.readableBytes();
}
serverReceivedRequestPayload.add(receivedSize);
}).beforeOnError(cause -> {
LOGGER.error("failure while reading request", cause);
serverReceivedRequestPayload.add(-1);
}).toFuture();
serverSendResponsePayload.await();
writer.write(RESPONSE_CONTENT);
}
});
serverContext.onClose().whenFinally(serverContextClosed::countDown).subscribe();
client = (viaProxy ? forSingleAddress(serverHostAndPort(serverContext)).proxyAddress(proxyAddress).sslConfig(new ClientSslConfigBuilder(DefaultTestCerts::loadServerCAPem).peerHost(serverPemHostname()).build()) : forResolvedAddress(serverContext.listenAddress())).protocols(protocol.config).executor(CLIENT_CTX.executor()).ioExecutor(CLIENT_CTX.ioExecutor()).executionStrategy(defaultStrategy()).enableWireLogging("servicetalk-tests-wire-logger", TRACE, Boolean.TRUE::booleanValue).appendConnectionFactoryFilter(ConnectionFactoryFilter.withStrategy(cf -> initiateClosureFromClient ? new OnClosingConnectionFactoryFilter<>(cf, onClosing) : cf, ExecutionStrategy.offloadNone())).buildStreaming();
connection = client.reserveConnection(client.get("/")).toFuture().get();
connection.onClose().whenFinally(clientConnectionClosed::countDown).subscribe();
// wait until server accepts connection
connectionAccepted.await();
toClose = initiateClosureFromClient ? connection : serverContext;
}
use of io.servicetalk.http.api.HttpPayloadWriter in project servicetalk by apple.
the class RequestResponseContextTest method service.
@Override
void service(final StreamingHttpService service) {
final StreamingHttpService newService;
assert api != null;
switch(api) {
case AsyncAggregated:
newService = toStreamingHttpService((HttpService) (ctx, request, responseFactory) -> {
HttpResponse response = responseFactory.ok().payloadBody(request.payloadBody());
transferContext(request, response);
return succeeded(response);
}, offloadNone()).adaptor();
break;
case AsyncStreaming:
newService = (ctx, request, responseFactory) -> {
StreamingHttpResponse response = responseFactory.ok().payloadBody(request.payloadBody());
transferContext(request, response);
return succeeded(response);
};
break;
case BlockingAggregated:
newService = toStreamingHttpService((BlockingHttpService) (ctx, request, responseFactory) -> {
HttpResponse response = responseFactory.ok().payloadBody(request.payloadBody());
transferContext(request, response);
return response;
}, offloadNone()).adaptor();
break;
case BlockingStreaming:
newService = toStreamingHttpService((ctx, request, response) -> {
transferContext(request, response);
try (HttpPayloadWriter<Buffer> writer = response.sendMetaData()) {
for (Buffer chunk : request.payloadBody()) {
writer.write(chunk);
}
}
}, offloadNone()).adaptor();
break;
default:
throw new IllegalStateException("Unknown api: " + api);
}
super.service(newService);
}
use of io.servicetalk.http.api.HttpPayloadWriter in project servicetalk by apple.
the class BlockingStreamingHttpServiceTest method setRequestMessageBody.
@Test
void setRequestMessageBody() throws Exception {
BlockingStreamingHttpClient client = context((ctx, request, response) -> {
response.status(OK);
try {
HttpMessageBodyIterator<Buffer> reqItr = request.messageBody().iterator();
StringBuilder sb = new StringBuilder();
while (reqItr.hasNext()) {
sb.append(requireNonNull(reqItr.next()).toString(UTF_8));
}
assertThat(sb.toString(), is(HELLO_WORLD));
HttpHeaders trailers = reqItr.trailers();
assertThat(trailers, notNullValue());
assertThat(trailers.get(X_TOTAL_LENGTH).toString(), is(HELLO_WORLD_LENGTH));
} catch (Throwable cause) {
HttpPayloadWriter<String> payloadWriter = response.sendMetaData(appSerializerUtf8FixLen());
payloadWriter.write(cause.toString());
payloadWriter.close();
return;
}
response.sendMetaData(appSerializerUtf8FixLen()).close();
});
BufferAllocator alloc = client.executionContext().bufferAllocator();
BlockingStreamingHttpRequest req = client.get("/");
req.setHeader(TRAILER, X_TOTAL_LENGTH);
int split = HELLO_WORLD.length() / 2;
final BlockingIterable<Buffer> reqIterable = BlockingIterables.from(asList(alloc.fromAscii(HELLO_WORLD.substring(0, split)), alloc.fromAscii(HELLO_WORLD.substring(split))));
req.messageBody(() -> new HttpMessageBodyIterator<Buffer>() {
private final BlockingIterator<Buffer> iterator = reqIterable.iterator();
@Nullable
private HttpHeaders trailers;
private int totalLength;
@Nullable
@Override
public HttpHeaders trailers() {
if (trailers == null) {
trailers = DefaultHttpHeadersFactory.INSTANCE.newTrailers();
trailers.set(X_TOTAL_LENGTH, String.valueOf(totalLength));
}
return trailers;
}
@Override
public boolean hasNext(final long timeout, final TimeUnit unit) throws TimeoutException {
return iterator.hasNext(timeout, unit);
}
@Nullable
@Override
public Buffer next(final long timeout, final TimeUnit unit) throws TimeoutException {
return addTotalLength(iterator.next(timeout, unit));
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Nullable
@Override
public Buffer next() {
return addTotalLength(iterator.next());
}
@Override
public void close() throws Exception {
iterator.close();
}
@Nullable
private Buffer addTotalLength(@Nullable Buffer buffer) {
if (buffer != null) {
totalLength += buffer.readableBytes();
}
return buffer;
}
});
BlockingStreamingHttpResponse response = client.request(req);
assertThat(response.status(), is(OK));
assertThat(stream(response.payloadBody(appSerializerUtf8FixLen()).spliterator(), false).collect(Collectors.toList()), emptyIterable());
}
use of io.servicetalk.http.api.HttpPayloadWriter in project servicetalk by apple.
the class BlockingProtobufStreamingServer method main.
public static void main(String[] args) throws Exception {
HttpServers.forPort(8080).listenBlockingStreamingAndAwait((ctx, request, response) -> {
if (!"/protobuf".equals(request.requestTarget())) {
response.status(NOT_FOUND).sendMetaData().close();
} else if (!POST.equals(request.method())) {
response.status(METHOD_NOT_ALLOWED).addHeader(ALLOW, POST.name()).sendMetaData().close();
} else {
BlockingIterable<RequestMessage> values = request.payloadBody(REQ_STREAMING_SERIALIZER);
response.status(CREATED);
try (HttpPayloadWriter<ResponseMessage> writer = response.sendMetaData(RESP_STREAMING_SERIALIZER)) {
for (RequestMessage req : values) {
writer.write(ResponseMessage.newBuilder().setLength(req.getMessage().length()).build());
}
}
}
}).awaitShutdown();
}
use of io.servicetalk.http.api.HttpPayloadWriter in project servicetalk by apple.
the class BlockingPojoStreamingServer method main.
public static void main(String[] args) throws Exception {
HttpServers.forPort(8080).listenBlockingStreamingAndAwait((ctx, request, response) -> {
if (!"/pojos".equals(request.requestTarget())) {
response.status(NOT_FOUND).sendMetaData().close();
} else if (!POST.equals(request.method())) {
response.status(METHOD_NOT_ALLOWED).addHeader(ALLOW, POST.name()).sendMetaData().close();
} else {
BlockingIterable<CreatePojoRequest> values = request.payloadBody(REQ_STREAMING_SERIALIZER);
response.status(CREATED);
try (HttpPayloadWriter<PojoResponse> writer = response.sendMetaData(RESP_STREAMING_SERIALIZER)) {
for (CreatePojoRequest req : values) {
writer.write(new PojoResponse(ID_GENERATOR.getAndIncrement(), req.getValue()));
}
}
}
}).awaitShutdown();
}
Aggregations