use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method serverAllowDropTrailers.
private void serverAllowDropTrailers(boolean allowDrop, boolean clientAddTrailerHeader) throws Exception {
String trailerName = "t1";
String trailerValue = "v1";
SingleSource.Processor<HttpHeaders, HttpHeaders> trailersProcessor = Processors.newSingleProcessor();
h1ServerContext = HttpServers.forAddress(localAddress(0)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).allowDropRequestTrailers(allowDrop).listenStreamingAndAwait((ctx, request, responseFactory) -> succeeded(responseFactory.ok().payloadBody(// intermediate Buffer transform may drop trailers
request.transformPayloadBody(buf -> buf).transform(new StatelessTrailersTransformer<Buffer>() {
@Override
protected HttpHeaders payloadComplete(final HttpHeaders trailers) {
trailersProcessor.onSuccess(trailers);
return trailers;
}
}).payloadBody())));
InetSocketAddress serverAddress = (InetSocketAddress) h1ServerContext.listenAddress();
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).allowDropResponseTrailers(allowDrop).executionStrategy(clientExecutionStrategy).buildBlocking()) {
HttpRequest request = client.get("/");
if (clientAddTrailerHeader) {
request.headers().add(TRAILER, trailerName);
}
request.trailers().add(trailerName, trailerValue);
client.request(request);
HttpHeaders requestTrailers = fromSource(trailersProcessor).toFuture().get();
if (allowDrop && !clientAddTrailerHeader) {
assertFalse(requestTrailers.contains(trailerName));
} else {
assertHeaderValue(requestTrailers, trailerName, trailerValue);
}
}
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method clientAllowDropTrailers.
private void clientAllowDropTrailers(boolean allowDrop, boolean serverAddTrailerHeader) throws Exception {
String trailerName = "t1";
String trailerValue = "v1";
InetSocketAddress serverAddress = serverAddTrailerHeader ? bindHttpEchoServerWithTrailer(trailerName) : bindHttpEchoServer();
try (StreamingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).allowDropResponseTrailers(allowDrop).executionStrategy(clientExecutionStrategy).buildStreaming()) {
StreamingHttpResponse response = client.request(client.get("/").transform(new StatelessTrailersTransformer<Buffer>() {
@Override
protected HttpHeaders payloadComplete(final HttpHeaders trailers) {
trailers.add(trailerName, trailerValue);
return trailers;
}
})).toFuture().get();
SingleSource.Processor<HttpHeaders, HttpHeaders> trailersProcessor = Processors.newSingleProcessor();
// intermediate Buffer transform may drop trailers
response.transformPayloadBody(buf -> buf).transform(new StatelessTrailersTransformer<Buffer>() {
@Override
protected HttpHeaders payloadComplete(final HttpHeaders trailers) {
trailersProcessor.onSuccess(trailers);
return trailers;
}
}).messageBody().ignoreElements().toFuture().get();
HttpHeaders responseTrailers = fromSource(trailersProcessor).toFuture().get();
if (allowDrop && !serverAddTrailerHeader) {
assertFalse(responseTrailers.contains(trailerName));
} else {
assertHeaderValue(responseTrailers, trailerName, trailerValue);
}
}
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class DefaultContainerResponseWriter method sendResponse.
private void sendResponse(final long contentLength, @Nullable final Publisher<Buffer> content, final ContainerResponse containerResponse) {
final HttpResponseStatus status = getStatus(containerResponse);
final StreamingHttpResponse response;
if (content != null && !isHeadRequest()) {
final HttpExecutionStrategy executionStrategy = getResponseExecutionStrategy(request);
// TODO(scott): use request factory methods that accept a payload body to avoid overhead of payloadBody.
final Publisher<Buffer> payloadBody = (executionStrategy != null && executionStrategy.isSendOffloaded() ? content.subscribeOn(serviceCtx.executionContext().executor(), IoThreadFactory.IoThread::currentThreadIsIoThread) : content).beforeCancel(// Cleanup internal state if server cancels response body
this::cancelResponse);
response = responseFactory.newResponse(status).version(protocolVersion).payloadBody(payloadBody);
} else {
response = responseFactory.newResponse(status).version(protocolVersion);
}
final HttpHeaders headers = response.headers();
// If we use HTTP/2 protocol all headers MUST be in lower case
final boolean isH2 = response.version().major() == 2;
containerResponse.getHeaders().forEach((k, vs) -> vs.forEach(v -> {
headers.add(isH2 ? k.toLowerCase() : k, v == null ? emptyAsciiString() : asCharSequence(v));
}));
if (!headers.contains(CONTENT_LENGTH)) {
if (contentLength == UNKNOWN_RESPONSE_LENGTH) {
// We can omit Transfer-Encoding for HEAD per https://tools.ietf.org/html/rfc7231#section-4.3.2
if (!isHeadRequest() && !HTTP_1_0.equals(protocolVersion)) {
headers.set(TRANSFER_ENCODING, CHUNKED);
}
} else {
headers.set(CONTENT_LENGTH, contentLength == 0 ? ZERO : Long.toString(contentLength));
headers.removeIgnoreCase(TRANSFER_ENCODING, CHUNKED);
}
}
responseSubscriber.onSuccess(response);
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class HttpResponseDecoderBenchmark method initialLine.
@Benchmark
public int initialLine() {
channel.writeInbound(responseByteBuf.duplicate());
final HttpResponseMetaData response = channel.readInbound();
final HttpHeaders trailers = channel.readInbound();
if (response.status().code() != statusCode) {
throw new IllegalStateException("Unexpected statusCode: " + response.status().code());
}
return response.headers().size() + trailers.size();
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class AbstractH2DuplexHandler method writeTrailers.
final void writeTrailers(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
closeHandler.protocolPayloadEndOutbound(ctx, promise);
HttpHeaders trailers = (HttpHeaders) msg;
if (trailers.isEmpty()) {
writeEmptyEndStream(ctx, promise);
} else {
Http2Headers h2Headers = h1HeadersToH2Headers(trailers);
if (h2Headers.isEmpty()) {
writeEmptyEndStream(ctx, promise);
} else {
ctx.write(new DefaultHttp2HeadersFrame(h2Headers, true), promise);
}
}
}
Aggregations