use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.
the class GrpcHttp2HeadersUtilsTest method decode_responseHeaders.
@Test
public void decode_responseHeaders() throws Http2Exception {
Http2HeadersDecoder decoder = new GrpcHttp2ClientHeadersDecoder(DEFAULT_MAX_HEADER_LIST_SIZE);
Http2HeadersEncoder encoder = new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE);
Http2Headers headers = new DefaultHttp2Headers(false);
headers.add(of(":status"), of("200")).add(of("custom"), of("header"));
encodedHeaders = Unpooled.buffer();
encoder.encodeHeaders(1, /* randomly chosen */
headers, encodedHeaders);
Http2Headers decodedHeaders = decoder.decodeHeaders(3, /* randomly chosen */
encodedHeaders);
assertEquals(headers.get(of(":status")), decodedHeaders.get(of(":status")));
assertEquals(headers.get(of("custom")), decodedHeaders.get(of("custom")));
assertEquals(headers.size(), decodedHeaders.size());
String toString = decodedHeaders.toString();
assertContainsKeyAndValue(toString, ":status", decodedHeaders.get(of(":status")));
assertContainsKeyAndValue(toString, "custom", decodedHeaders.get(of("custom")));
}
use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.
the class NettyServerHandler method onHeadersRead.
private void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers) throws Http2Exception {
try {
// by Netty. RFC 7540 section 8.1.2.2
if (!DISABLE_CONNECTION_HEADER_CHECK && headers.contains(CONNECTION)) {
resetStream(ctx, streamId, Http2Error.PROTOCOL_ERROR.code(), ctx.newPromise());
return;
}
if (headers.authority() == null) {
List<CharSequence> hosts = headers.getAll(HOST);
if (hosts.size() > 1) {
// RFC 7230 section 5.4
respondWithHttpError(ctx, streamId, 400, Status.Code.INTERNAL, "Multiple host headers");
return;
}
if (!hosts.isEmpty()) {
headers.add(AUTHORITY.value(), hosts.get(0));
}
}
headers.remove(HOST);
// Remove the leading slash of the path and get the fully qualified method name
CharSequence path = headers.path();
if (path == null) {
respondWithHttpError(ctx, streamId, 404, Status.Code.UNIMPLEMENTED, "Expected path but is missing");
return;
}
if (path.charAt(0) != '/') {
respondWithHttpError(ctx, streamId, 404, Status.Code.UNIMPLEMENTED, String.format("Expected path to start with /: %s", path));
return;
}
String method = path.subSequence(1, path.length()).toString();
// Verify that the Content-Type is correct in the request.
CharSequence contentType = headers.get(CONTENT_TYPE_HEADER);
if (contentType == null) {
respondWithHttpError(ctx, streamId, 415, Status.Code.INTERNAL, "Content-Type is missing from the request");
return;
}
String contentTypeString = contentType.toString();
if (!GrpcUtil.isGrpcContentType(contentTypeString)) {
respondWithHttpError(ctx, streamId, 415, Status.Code.INTERNAL, String.format("Content-Type '%s' is not supported", contentTypeString));
return;
}
if (!HTTP_METHOD.contentEquals(headers.method())) {
respondWithHttpError(ctx, streamId, 405, Status.Code.INTERNAL, String.format("Method '%s' is not supported", headers.method()));
return;
}
if (!teWarningLogged && !TE_TRAILERS.contentEquals(headers.get(TE_HEADER))) {
logger.warning(String.format("Expected header TE: %s, but %s is received. This means " + "some intermediate proxy may not support trailers", TE_TRAILERS, headers.get(TE_HEADER)));
teWarningLogged = true;
}
// The Http2Stream object was put by AbstractHttp2ConnectionHandler before calling this
// method.
Http2Stream http2Stream = requireHttp2Stream(streamId);
Metadata metadata = Utils.convertHeaders(headers);
StatsTraceContext statsTraceCtx = StatsTraceContext.newServerContext(streamTracerFactories, method, metadata);
NettyServerStream.TransportState state = new NettyServerStream.TransportState(this, ctx.channel().eventLoop(), http2Stream, maxMessageSize, statsTraceCtx, transportTracer, method);
PerfMark.startTask("NettyServerHandler.onHeadersRead", state.tag());
try {
String authority = getOrUpdateAuthority((AsciiString) headers.authority());
NettyServerStream stream = new NettyServerStream(ctx.channel(), state, attributes, authority, statsTraceCtx, transportTracer);
transportListener.streamCreated(stream, method, metadata);
state.onStreamAllocated();
http2Stream.setProperty(streamKey, state);
} finally {
PerfMark.stopTask("NettyServerHandler.onHeadersRead", state.tag());
}
} catch (Exception e) {
logger.log(Level.WARNING, "Exception in onHeadersRead()", e);
// Throw an exception that will get handled by onStreamError.
throw newStreamException(streamId, e);
}
}
use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.
the class NettyServerHandler method sendResponseHeaders.
/**
* Sends the response headers to the client.
*/
private void sendResponseHeaders(ChannelHandlerContext ctx, SendResponseHeadersCommand cmd, ChannelPromise promise) throws Http2Exception {
PerfMark.startTask("NettyServerHandler.sendResponseHeaders", cmd.stream().tag());
PerfMark.linkIn(cmd.getLink());
try {
// TODO(carl-mastrangelo): remove this check once https://github.com/netty/netty/issues/6296
// is fixed.
int streamId = cmd.stream().id();
Http2Stream stream = connection().stream(streamId);
if (stream == null) {
resetStream(ctx, streamId, Http2Error.CANCEL.code(), promise);
return;
}
if (cmd.endOfStream()) {
closeStreamWhenDone(promise, streamId);
}
encoder().writeHeaders(ctx, streamId, cmd.headers(), 0, cmd.endOfStream(), promise);
} finally {
PerfMark.stopTask("NettyServerHandler.sendResponseHeaders", cmd.stream().tag());
}
}
use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.
the class NettyServerHandler method channelInactive.
/**
* Handler for the Channel shutting down.
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
try {
if (keepAliveManager != null) {
keepAliveManager.onTransportTermination();
}
if (maxConnectionIdleManager != null) {
maxConnectionIdleManager.onTransportTermination();
}
if (maxConnectionAgeMonitor != null) {
maxConnectionAgeMonitor.cancel(false);
}
final Status status = Status.UNAVAILABLE.withDescription("connection terminated for unknown reason");
// Any streams that are still active must be closed
connection().forEachActiveStream(new Http2StreamVisitor() {
@Override
public boolean visit(Http2Stream stream) throws Http2Exception {
NettyServerStream.TransportState serverStream = serverStream(stream);
if (serverStream != null) {
serverStream.transportReportStatus(status);
}
return true;
}
});
} finally {
super.channelInactive(ctx);
}
}
use of io.netty.handler.codec.http2.Http2Exception in project vert.x by eclipse.
the class Http2ServerTest method testResponseCompressionEnabled.
@Test
public void testResponseCompressionEnabled() throws Exception {
waitFor(2);
String expected = TestUtils.randomAlphaString(1000);
server.close();
server = vertx.createHttpServer(serverOptions.setCompressionSupported(true));
server.requestHandler(req -> {
req.response().end(expected);
});
startServer();
TestClient client = new TestClient();
ChannelFuture fut = client.connect(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, request -> {
request.decoder.frameListener(new Http2EventAdapter() {
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception {
vertx.runOnContext(v -> {
assertEquals("gzip", headers.get(HttpHeaderNames.CONTENT_ENCODING).toString());
complete();
});
}
@Override
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) throws Http2Exception {
byte[] bytes = new byte[data.readableBytes()];
data.readBytes(bytes);
vertx.runOnContext(v -> {
String decoded;
try {
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(bytes));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true) {
int i = in.read();
if (i == -1) {
break;
}
baos.write(i);
;
}
decoded = baos.toString();
} catch (IOException e) {
fail(e);
return;
}
assertEquals(expected, decoded);
complete();
});
return super.onDataRead(ctx, streamId, data, padding, endOfStream);
}
});
int id = request.nextStreamId();
request.encoder.writeHeaders(request.context, id, GET("/").add("accept-encoding", "gzip"), 0, true, request.context.newPromise());
request.context.flush();
});
fut.sync();
await();
}
Aggregations