use of io.servicetalk.http.api.HttpServiceContext in project servicetalk by apple.
the class GrpcRouter method bind.
Single<GrpcServerContext> bind(final ServerBinder binder, final GrpcExecutionContext executionContext) {
final CompositeCloseable closeable = AsyncCloseables.newCompositeCloseable();
final Map<String, StreamingHttpService> allRoutes = new HashMap<>();
populateRoutes(executionContext, allRoutes, routes, closeable, executionStrategies);
populateRoutes(executionContext, allRoutes, streamingRoutes, closeable, executionStrategies);
populateRoutes(executionContext, allRoutes, blockingRoutes, closeable, executionStrategies);
populateRoutes(executionContext, allRoutes, blockingStreamingRoutes, closeable, executionStrategies);
// TODO: Optimize to bind a specific programming model service based on routes
return binder.bindStreaming(new StreamingHttpService() {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
final StreamingHttpService service;
if (!POST.equals(request.method()) || (service = allRoutes.get(request.path())) == null) {
return NOT_FOUND_SERVICE.handle(ctx, request, responseFactory);
} else {
return service.handle(ctx, request, responseFactory);
}
}
@Override
public Completable closeAsync() {
return closeable.closeAsync();
}
@Override
public Completable closeAsyncGracefully() {
return closeable.closeAsyncGracefully();
}
}).map(httpServerContext -> new DefaultGrpcServerContext(httpServerContext, executionContext));
}
use of io.servicetalk.http.api.HttpServiceContext in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method serverThrowsFromHandler.
@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void serverThrowsFromHandler(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
setUp(strategy, h2PriorKnowledge);
InetSocketAddress serverAddress = bindHttpEchoServer(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
throw DELIBERATE_EXCEPTION;
}
}, null);
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).buildBlocking()) {
HttpResponse response = client.request(client.get("/"));
assertThat(response.status(), is(INTERNAL_SERVER_ERROR));
assertThat(response.payloadBody(), equalTo(EMPTY_BUFFER));
}
}
use of io.servicetalk.http.api.HttpServiceContext in project servicetalk by apple.
the class HttpLifecycleObserverTest method testClientCancelsRequestAfterResponse.
@ParameterizedTest(name = "{displayName} [{index}] protocol={0}")
@EnumSource(HttpProtocol.class)
void testClientCancelsRequestAfterResponse(HttpProtocol protocol) throws Exception {
TestPublisher<Buffer> serverResponsePayload = new TestPublisher<>();
serviceFilterFactory(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(HttpServiceContext ctx, StreamingHttpRequest request, StreamingHttpResponseFactory responseFactory) {
return request.payloadBody().ignoreElements().concat(succeeded(responseFactory.ok().payloadBody(serverResponsePayload)));
}
});
setUp(protocol);
StreamingHttpConnection connection = streamingHttpConnection();
StreamingHttpRequest request = connection.post("/").payloadBody(Publisher.from(CONTENT.duplicate())).transform(// adds empty trailers
new StatelessTrailersTransformer<>());
StreamingHttpResponse response = connection.request(request).toFuture().get();
assertResponse(response, protocol.version, OK);
Future<Collection<Buffer>> payload = response.payloadBody().toFuture();
payload.cancel(true);
if (protocol == HttpProtocol.HTTP_1) {
// wait for cancellation to close the connection:
connection.onClose().toFuture().get();
}
// try to write server content to trigger write failure and close the server-side connection:
serverResponsePayload.onNext(CONTENT.duplicate());
bothTerminate.await();
clientInOrder.verify(clientLifecycleObserver).onNewExchange();
clientInOrder.verify(clientExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
clientInOrder.verify(clientExchangeObserver).onRequest(any(StreamingHttpRequest.class));
clientInOrder.verify(clientExchangeObserver).onResponse(any(StreamingHttpResponse.class));
clientInOrder.verify(clientResponseObserver).onResponseCancel();
clientRequestInOrder.verify(clientRequestObserver).onRequestData(any(Buffer.class));
clientRequestInOrder.verify(clientRequestObserver).onRequestTrailers(any(HttpHeaders.class));
clientRequestInOrder.verify(clientRequestObserver).onRequestComplete();
clientInOrder.verify(clientExchangeObserver).onExchangeFinally();
verifyNoMoreInteractions(clientLifecycleObserver, clientExchangeObserver, clientRequestObserver, clientResponseObserver);
serverInOrder.verify(serverLifecycleObserver).onNewExchange();
serverInOrder.verify(serverExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
serverInOrder.verify(serverExchangeObserver).onRequest(any(StreamingHttpRequest.class));
serverInOrder.verify(serverExchangeObserver).onResponse(any(StreamingHttpResponse.class));
verify(serverResponseObserver, atMostOnce()).onResponseData(any(Buffer.class));
serverInOrder.verify(serverResponseObserver).onResponseCancel();
serverRequestInOrder.verify(serverRequestObserver).onRequestData(any(Buffer.class));
serverRequestInOrder.verify(serverRequestObserver).onRequestComplete();
serverInOrder.verify(serverExchangeObserver).onExchangeFinally();
verifyNoMoreInteractions(serverLifecycleObserver, serverExchangeObserver, serverRequestObserver, serverResponseObserver);
}
use of io.servicetalk.http.api.HttpServiceContext in project servicetalk by apple.
the class HttpTransportObserverTest method setUp.
private void setUp(HttpProtocol protocol) {
this.protocol = protocol;
protocol(protocol.config);
connectionAcceptor(ctx -> {
ctx.onClose().whenFinally(serverConnectionClosed::countDown).subscribe();
return completed();
});
serviceFilterFactory(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(HttpServiceContext ctx, StreamingHttpRequest request, StreamingHttpResponseFactory responseFactory) {
requestReceived.countDown();
try {
processRequest.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throwException(e);
}
return delegate().handle(ctx, request, responseFactory);
}
});
clientTransportObserver = mock(TransportObserver.class, "clientTransportObserver");
clientConnectionObserver = mock(ConnectionObserver.class, "clientConnectionObserver");
clientDataObserver = mock(DataObserver.class, "clientDataObserver");
clientMultiplexedObserver = mock(MultiplexedObserver.class, "clientMultiplexedObserver");
clientStreamObserver = mock(StreamObserver.class, "clientStreamObserver");
clientReadObserver = mock(ReadObserver.class, "clientReadObserver");
clientWriteObserver = mock(WriteObserver.class, "clientWriteObserver");
when(clientTransportObserver.onNewConnection(any(), any())).thenReturn(clientConnectionObserver);
lenient().when(clientConnectionObserver.connectionEstablished(any(ConnectionInfo.class))).thenReturn(clientDataObserver);
lenient().when(clientConnectionObserver.multiplexedConnectionEstablished(any(ConnectionInfo.class))).thenReturn(clientMultiplexedObserver);
lenient().when(clientMultiplexedObserver.onNewStream()).thenReturn(clientStreamObserver);
lenient().when(clientStreamObserver.streamEstablished()).thenReturn(clientDataObserver);
lenient().when(clientDataObserver.onNewRead()).thenReturn(clientReadObserver);
lenient().when(clientDataObserver.onNewWrite()).thenReturn(clientWriteObserver);
serverTransportObserver = mock(TransportObserver.class, "serverTransportObserver");
serverConnectionObserver = mock(ConnectionObserver.class, "serverConnectionObserver");
serverDataObserver = mock(DataObserver.class, "serverDataObserver");
serverMultiplexedObserver = mock(MultiplexedObserver.class, "serverMultiplexedObserver");
serverStreamObserver = mock(StreamObserver.class, "serverStreamObserver");
serverReadObserver = mock(ReadObserver.class, "serverReadObserver");
serverWriteObserver = mock(WriteObserver.class, "serverWriteObserver");
when(serverTransportObserver.onNewConnection(any(), any())).thenReturn(serverConnectionObserver);
lenient().when(serverConnectionObserver.connectionEstablished(any(ConnectionInfo.class))).thenReturn(serverDataObserver);
lenient().when(serverConnectionObserver.multiplexedConnectionEstablished(any(ConnectionInfo.class))).thenReturn(serverMultiplexedObserver);
lenient().when(serverMultiplexedObserver.onNewStream()).thenReturn(serverStreamObserver);
lenient().when(serverStreamObserver.streamEstablished()).thenReturn(serverDataObserver);
lenient().when(serverDataObserver.onNewRead()).thenReturn(serverReadObserver);
lenient().when(serverDataObserver.onNewWrite()).thenReturn(serverWriteObserver);
transportObserver(clientTransportObserver, serverTransportObserver);
setUp(CACHED, CACHED_SERVER);
}
use of io.servicetalk.http.api.HttpServiceContext in project servicetalk by apple.
the class AbstractHttpServiceAsyncContextTest method filterFactory.
private StreamingHttpServiceFilterFactory filterFactory(final boolean useImmediate, final boolean asyncFilter, final Queue<Throwable> errorQueue) {
return service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory factory) {
return asyncFilter ? defer(() -> doHandle(ctx, request, factory).shareContextOnSubscribe()) : doHandle(ctx, request, factory);
}
private Single<StreamingHttpResponse> doHandle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory factory) {
if (useImmediate && !currentThread().getName().startsWith(IO_THREAD_PREFIX)) {
// verify that if we expect to be offloaded, that we actually are
return succeeded(factory.internalServerError());
}
CharSequence requestId = request.headers().getAndRemove(REQUEST_ID_HEADER);
if (requestId != null) {
AsyncContext.put(K1, requestId);
}
final StreamingHttpRequest filteredRequest = request.transformMessageBody(pub -> pub.afterSubscriber(assertAsyncContextSubscriber(requestId, errorQueue)));
return delegate().handle(ctx, filteredRequest, factory).map(resp -> {
assertAsyncContext(requestId, errorQueue);
return resp.transformMessageBody(pub -> pub.afterSubscriber(assertAsyncContextSubscriber(requestId, errorQueue)));
});
}
};
}
Aggregations