use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class NettyServerHandlerTest method headersWithInvalidMethodShouldFail.
@Test
public void headersWithInvalidMethodShouldFail() throws Exception {
manualSetUp();
Http2Headers headers = new DefaultHttp2Headers().method(HTTP_FAKE_METHOD).set(CONTENT_TYPE_HEADER, CONTENT_TYPE_GRPC).path(new AsciiString("/foo/bar"));
ByteBuf headersFrame = headersFrame(STREAM_ID, headers);
channelRead(headersFrame);
Http2Headers responseHeaders = new DefaultHttp2Headers().set(InternalStatus.CODE_KEY.name(), String.valueOf(Code.INTERNAL.value())).set(InternalStatus.MESSAGE_KEY.name(), "Method 'FAKE' is not supported").status("" + 405).set(CONTENT_TYPE_HEADER, "text/plain; charset=utf-8");
verifyWrite().writeHeaders(eq(ctx()), eq(STREAM_ID), eq(responseHeaders), eq(0), eq(false), any(ChannelPromise.class));
}
use of io.netty.handler.codec.http2.Http2Headers in project grpc-java by grpc.
the class NettyHandlerTestBase method headersFrame.
protected final ByteBuf headersFrame(int streamId, Http2Headers headers) {
ChannelHandlerContext ctx = newMockContext();
new DefaultHttp2FrameWriter().writeHeaders(ctx, streamId, headers, 0, false, newPromise());
return captureWrite(ctx);
}
use of io.netty.handler.codec.http2.Http2Headers 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.Http2Headers in project grpc-java by grpc.
the class NettyServerHandler method respondWithHttpError.
private void respondWithHttpError(ChannelHandlerContext ctx, int streamId, int code, Status.Code statusCode, String msg) {
Metadata metadata = new Metadata();
metadata.put(InternalStatus.CODE_KEY, statusCode.toStatus());
metadata.put(InternalStatus.MESSAGE_KEY, msg);
byte[][] serialized = InternalMetadata.serialize(metadata);
Http2Headers headers = new DefaultHttp2Headers(true, serialized.length / 2).status("" + code).set(CONTENT_TYPE_HEADER, "text/plain; charset=utf-8");
for (int i = 0; i < serialized.length; i += 2) {
headers.add(new AsciiString(serialized[i], false), new AsciiString(serialized[i + 1], false));
}
encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise());
ByteBuf msgBuf = ByteBufUtil.writeUtf8(ctx.alloc(), msg);
encoder().writeData(ctx, streamId, msgBuf, 0, true, ctx.newPromise());
}
use of io.netty.handler.codec.http2.Http2Headers 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