use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class GrpcUtils method validateResponseAndGetPayload.
static <Resp> Resp validateResponseAndGetPayload(final HttpResponse response, final CharSequence expectedContentType, final BufferAllocator allocator, final GrpcDeserializer<Resp> deserializer) {
// gRPC protocol requires 200, don't look further if this check fails.
validateStatusCode(response.status());
// In case of an empty response, gRPC-server may return only one HEADER frame with endStream=true. Our
// HTTP1-based implementation translates them into response headers so we need to look for a grpc-status in both
// headers and trailers.
final HttpHeaders headers = response.headers();
final HttpHeaders trailers = response.trailers();
validateContentType(headers, expectedContentType);
// We will try the trailers first as this is the most likely place to find the gRPC-related headers.
final GrpcStatusCode grpcStatusCode = extractGrpcStatusCodeFromHeaders(trailers);
if (grpcStatusCode != null) {
final GrpcStatusException grpcStatusException = convertToGrpcStatusException(grpcStatusCode, trailers);
if (grpcStatusException != null) {
throw grpcStatusException;
}
return deserializer.deserialize(response.payloadBody(), allocator);
}
// There was no grpc-status in the trailers, so it must be in headers.
ensureGrpcStatusReceived(headers);
return deserializer.deserialize(response.payloadBody(), allocator);
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class GrpcUtils method initRequest.
static void initRequest(final HttpRequestMetaData request, final CharSequence contentType, @Nullable final CharSequence encoding, @Nullable final CharSequence acceptedEncoding, @Nullable final Duration timeout) {
assert POST.equals(request.method());
final HttpHeaders headers = request.headers();
final CharSequence timeoutValue = makeTimeoutHeader(timeout);
if (null != timeoutValue) {
headers.set(GRPC_TIMEOUT_HEADER_KEY, timeoutValue);
}
headers.set(USER_AGENT, SERVICETALK_USER_AGENT);
headers.set(TE, TRAILERS);
headers.set(CONTENT_TYPE, contentType);
if (encoding != null) {
headers.set(GRPC_MESSAGE_ENCODING, encoding);
}
if (acceptedEncoding != null) {
headers.set(GRPC_MESSAGE_ACCEPT_ENCODING, acceptedEncoding);
}
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class HttpRequestEncoderTest method chunkedWithTrailers.
@Test
void chunkedWithTrailers() {
EmbeddedChannel channel = newEmbeddedChannel();
byte[] content = new byte[128];
ThreadLocalRandom.current().nextBytes(content);
Buffer buffer = allocator.wrap(content);
HttpHeaders trailers = INSTANCE.newTrailers();
trailers.add("TrailerStatus", "good");
HttpRequestMetaData request = newRequestMetaData(HTTP_1_1, GET, "/some/path?foo=bar&baz=yyy", INSTANCE.newHeaders());
request.headers().add(CONNECTION, KEEP_ALIVE).add(USER_AGENT, "unit-test").add(TRANSFER_ENCODING, CHUNKED);
channel.writeOutbound(request);
channel.writeOutbound(buffer.duplicate());
channel.writeOutbound(trailers);
verifyHttpRequest(channel, buffer, TransferEncoding.Chunked, true);
assertFalse(channel.finishAndReleaseAll());
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class HttpResponseDecoderTest method errorResponseToConnectRequestWithContent.
@Test
void errorResponseToConnectRequestWithContent() {
methodQueue.add(CONNECT);
int contentLength = 128;
writeMsg("HTTP/1.1 400 Bad Request" + "\r\n" + "Host: servicetalk.io" + "\r\n" + "Content-Length: " + contentLength + "\r\n" + "Connection: keep-alive" + "\r\n\r\n");
writeContent(contentLength);
assertResponseLine(HTTP_1_1, BAD_REQUEST);
HttpHeaders trailers = assertPayloadSize(contentLength);
assertThat("Trailers are not empty", trailers, nullValue());
assertFalse(channel.finishAndReleaseAll());
}
use of io.servicetalk.http.api.HttpHeaders in project servicetalk by apple.
the class HttpResponseEncoderTest method contentLengthWithTrailers.
@ParameterizedTest
@ValueSource(booleans = { true, false })
void contentLengthWithTrailers(boolean emptyTrailers) {
EmbeddedChannel channel = newEmbeddedChannel();
byte[] content = new byte[128];
ThreadLocalRandom.current().nextBytes(content);
Buffer buffer = DEFAULT_ALLOCATOR.wrap(content);
HttpHeaders trailers = DefaultHttpHeadersFactory.INSTANCE.newTrailers();
if (!emptyTrailers) {
trailers.add("TrailerStatus", "good");
}
HttpResponseMetaData response = newResponseMetaData(HTTP_1_1, OK, INSTANCE.newHeaders());
response.headers().add(CONNECTION, KEEP_ALIVE).add(SERVER, "unit-test").add(CONTENT_LENGTH, valueOf(content.length));
channel.writeOutbound(response);
channel.writeOutbound(buffer.duplicate());
if (!emptyTrailers) {
assertThrows(IOException.class, () -> channel.writeOutbound(trailers));
} else {
channel.writeOutbound(trailers);
verifyHttpResponse(channel, buffer, TransferEncoding.ContentLength, false);
consumeEmptyBufferFromTrailers(channel);
}
// The trailers will just not be encoded if the transfer encoding is not set correctly.
assertNotEquals(emptyTrailers, channel.finishAndReleaseAll());
}
Aggregations