@Override void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endOfStream, Http2Headers headers) { String[] splitPath = headers.path().toString().split("\\?"); if (splitPath.length <= 1) { sendResponseString(ctx, streamId, "Header name not found."); return; } String headerName = splitPath[1].toLowerCase(Locale.US); if (headers.get(headerName) == null) { sendResponseString(ctx, streamId, "Header not found:" + headerName); return; } sendResponseString(ctx, streamId, headers.get(headerName).toString()); }
@Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) throws Http2Exception { String path = headers.path().toString(); RequestResponder responder; if (path.startsWith(ECHO_STREAM_PATH)) { responder = new EchoStreamResponder(); } else if (path.startsWith(ECHO_TRAILERS_PATH)) { responder = new EchoTrailersResponder(); } else if (path.startsWith(ECHO_ALL_HEADERS_PATH)) { responder = new EchoAllHeadersResponder(); } else if (path.startsWith(ECHO_HEADER_PATH)) { responder = new EchoHeaderResponder(); } else if (path.startsWith(ECHO_METHOD_PATH)) { responder = new EchoMethodResponder(); } else { responder = new RequestResponder(); } responder.onHeadersRead(ctx, streamId, endOfStream, headers); if (!endOfStream) { mResponderMap.put(streamId, responder); } }
/** * Converts the specified Netty HTTP/2 into Armeria HTTP/2 headers. */ public static HttpHeaders toArmeria(Http2Headers headers) { final HttpHeaders converted = new DefaultHttpHeaders(false, headers.size()); StringJoiner cookieJoiner = null; for (Entry<CharSequence, CharSequence> e : headers) { final AsciiString name = AsciiString.of(e.getKey()); final CharSequence value = e.getValue(); // Cookies must be concatenated into a single octet string. // https://tools.ietf.org/html/rfc7540#section-8.1.2.5 if (name.equals(HttpHeaderNames.COOKIE)) { if (cookieJoiner == null) { cookieJoiner = new StringJoiner(COOKIE_SEPARATOR); } COOKIE_SPLITTER.split(value).forEach(cookieJoiner::add); } else { converted.add(name, value.toString()); } } if (cookieJoiner != null && cookieJoiner.length() != 0) { converted.add(HttpHeaderNames.COOKIE, cookieJoiner.toString()); } return converted; }
/** * Converts the specified Armeria HTTP/2 headers into Netty HTTP/2 headers. */ public static Http2Headers toNettyHttp2(HttpHeaders in) { final Http2Headers out = new DefaultHttp2Headers(false, in.size()); out.set(in); out.remove(HttpHeaderNames.CONNECTION); out.remove(HttpHeaderNames.TRANSFER_ENCODING); out.remove(HttpHeaderNames.TRAILER); if (!out.contains(HttpHeaderNames.COOKIE)) { return out; } // Split up cookies to allow for better compression. // https://tools.ietf.org/html/rfc7540#section-8.1.2.5 final List<CharSequence> cookies = out.getAllAndRemove(HttpHeaderNames.COOKIE); for (CharSequence c : cookies) { out.add(HttpHeaderNames.COOKIE, COOKIE_SPLITTER.split(c)); } return out; }
@Override public void onHeadersRead( ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception { if (isServer) { ctx.fireChannelRead(Http2Request.build(streamId, headers, endStream)); } else { ctx.fireChannelRead(Http2Response.build(streamId, headers, endStream)); } }
void writeContent(ChannelHandlerContext ctx, StreamingData data, ChannelPromise promise) { Request request = getChannelRequest(ctx); int streamId = request.streamId(); if (data.endOfStream()) { setChannelRequest(ctx, null); } boolean dataEos = data.endOfStream() && data.trailingHeaders().size() == 0; Http2Response response = Http2Response.build(streamId, new DefaultHttp2DataFrame(data.content(), dataEos), dataEos); if (data.trailingHeaders().size() != 0) { Http2Headers headers = data.trailingHeaders().http2Headers(); Http2Response last = Http2Response.build(streamId, headers, true); PromiseCombiner combiner = new PromiseCombiner(); combiner.add(ctx.write(response, ctx.newPromise())); combiner.add(ctx.write(last, ctx.newPromise())); combiner.finish(promise); } else { ctx.write(response, promise); } }
@Test public void keepAliveEnforcer_sendingDataResetsCounters() throws Exception { permitKeepAliveWithoutCalls = false; permitKeepAliveTimeInNanos = TimeUnit.HOURS.toNanos(1); manualSetUp(); createStream(); Http2Headers headers = Utils.convertServerHeaders(new Metadata()); ChannelFuture future = enqueue( SendResponseHeadersCommand.createHeaders(stream.transportState(), headers)); future.get(); ByteBuf payload = handler().ctx().alloc().buffer(8); payload.writeLong(1); for (int i = 0; i < 10; i++) { future = enqueue( new SendGrpcFrameCommand(stream.transportState(), content().retainedSlice(), false)); future.get(); channel().releaseOutbound(); channelRead(pingFrame(false /* isAck */, payload.slice())); } payload.release(); verifyWrite(never()).writeGoAway(eq(ctx()), eq(STREAM_ID), eq(Http2Error.ENHANCE_YOUR_CALM.code()), any(ByteBuf.class), any(ChannelPromise.class)); }
@Test public void testFullRequest() throws Exception { outputReceived = new CountDownLatch(1); Http2Headers headers = new DefaultHttp2Headers().method("GET").path("/"); Http2Request requestIn = Http2Request.build(1, headers, true); channel.writeInbound(requestIn); channel.runPendingTasks(); // blocks Uninterruptibles.awaitUninterruptibly(outputReceived); Request requestOut = requests.remove(0); assertTrue(requestOut != null); assertTrue(requestOut instanceof FullRequest); assertEquals("h2", requestOut.version()); assertEquals(HttpMethod.GET, requestOut.method()); assertEquals("/", requestOut.path()); assertFalse(requestOut.hasBody()); assertFalse(requestOut.body() == null); assertEquals(0, requestOut.body().readableBytes()); assertEquals(1, requestOut.streamId()); }
@Test public void testFullResponse() throws Exception { outputReceived = new CountDownLatch(2); Http2Headers headersIn = new DefaultHttp2Headers().method("GET").path("/"); Http2Request requestIn = Http2Request.build(1, headersIn, true); FullResponse responseIn = ResponseBuilders.newOk().body(Unpooled.EMPTY_BUFFER).build(); channel.writeInbound(requestIn); channel.runPendingTasks(); // blocks channel.writeOutbound(responseIn); channel.runPendingTasks(); // blocks Uninterruptibles.awaitUninterruptibly(outputReceived); Http2Response responseOut = (Http2Response) responses.remove(0); assertTrue(responseOut != null); assertTrue(responseOut.payload instanceof Http2Headers); assertEquals("200", ((Http2Headers) responseOut.payload).status().toString()); assertTrue(responseOut.eos); assertEquals(1, responseOut.streamId); }
@Test public void testFullResponse() throws Exception { outputReceived = new CountDownLatch(1); Http2Headers headers = new DefaultHttp2Headers().status("200"); Http2Response responseIn = Http2Response.build(1, headers, true); channel.writeInbound(responseIn); channel.runPendingTasks(); // blocks Uninterruptibles.awaitUninterruptibly(outputReceived); Response responseOut = responses.remove(0); assertTrue(responseOut != null); assertTrue(responseOut instanceof FullResponse); assertEquals("h2", responseOut.version()); assertEquals(OK, responseOut.status()); assertFalse(responseOut.hasBody()); assertEquals(1, responseOut.streamId()); }
@Override public void push(final String method, final String path, final Map<String, Object> headers) { ctx.channel().eventLoop().execute(() -> { AsciiString streamIdHeader = HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(); Http2Connection connection = encoder.connection(); int nextStreamId = connection.local().incrementAndGetNextStreamId(); Http2Headers h2headers = new DefaultHttp2Headers() .path(path) .method(method) .authority(authority) .scheme(scheme); headers.forEach((n, v) -> h2headers.add(n, v.toString())); encoder.writePushPromise(ctx, streamId, nextStreamId, h2headers, 0, ctx.newPromise()); // TODO: Is there another way of handling a push promise? DefaultFullHttpRequest pushRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method.toUpperCase()), path, Unpooled.EMPTY_BUFFER, new DefaultHttpHeaders(false).set(streamIdHeader, nextStreamId), EmptyHttpHeaders.INSTANCE); ctx.pipeline().fireChannelRead(pushRequest); ctx.pipeline().fireChannelReadComplete(); }); }
@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; encoding=utf-8"); verifyWrite().writeHeaders(eq(ctx()), eq(STREAM_ID), eq(responseHeaders), eq(0), eq(DEFAULT_PRIORITY_WEIGHT), eq(false), eq(0), eq(false), any(ChannelPromise.class)); }
public static Http2Headers convertClientHeaders(Metadata headers, AsciiString scheme, AsciiString defaultPath, AsciiString authority, AsciiString method, AsciiString userAgent) { Preconditions.checkNotNull(defaultPath, "defaultPath"); Preconditions.checkNotNull(authority, "authority"); Preconditions.checkNotNull(method, "method"); // Discard any application supplied duplicates of the reserved headers headers.discardAll(CONTENT_TYPE_KEY); headers.discardAll(GrpcUtil.TE_HEADER); headers.discardAll(GrpcUtil.USER_AGENT_KEY); return GrpcHttp2OutboundHeaders.clientRequestHeaders( toHttp2Headers(headers), authority, defaultPath, method, scheme, userAgent); }
private void createStream() throws Exception { Http2Headers headers = new DefaultHttp2Headers() .method(HTTP_METHOD) .set(CONTENT_TYPE_HEADER, CONTENT_TYPE_GRPC) .set(TE_HEADER, TE_TRAILERS) .path(new AsciiString("/foo/bar")); ByteBuf headersFrame = headersFrame(STREAM_ID, headers); channelRead(headersFrame); ArgumentCaptor<NettyServerStream> streamCaptor = ArgumentCaptor.forClass(NettyServerStream.class); ArgumentCaptor<String> methodCaptor = ArgumentCaptor.forClass(String.class); verify(transportListener).streamCreated(streamCaptor.capture(), methodCaptor.capture(), any(Metadata.class)); stream = streamCaptor.getValue(); }
@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"))); }
@Test public void basicCorrectness() { Http2Headers headers = new GrpcHttp2RequestHeaders(1); headers.add(of(":method"), of("POST")); headers.add(of("content-type"), of("application/grpc+proto")); headers.add(of(":path"), of("/google.pubsub.v2.PublisherService/CreateTopic")); headers.add(of(":scheme"), of("https")); headers.add(of("te"), of("trailers")); headers.add(of(":authority"), of("pubsub.googleapis.com")); headers.add(of("foo"), of("bar")); assertEquals(7, headers.size()); // Number of headers without the pseudo headers and 'te' header. assertEquals(2, ((GrpcHttp2InboundHeaders)headers).numHeaders()); assertEquals(of("application/grpc+proto"), headers.get(of("content-type"))); assertEquals(of("/google.pubsub.v2.PublisherService/CreateTopic"), headers.path()); assertEquals(of("https"), headers.scheme()); assertEquals(of("POST"), headers.method()); assertEquals(of("pubsub.googleapis.com"), headers.authority()); assertEquals(of("trailers"), headers.get(of("te"))); assertEquals(of("bar"), headers.get(of("foo"))); }
@Test public void convertServerHeaders_sanitizes() { Metadata metaData = new Metadata(); // Intentionally being explicit here rather than relying on any pre-defined lists of headers, // since the goal of this test is to validate the correctness of such lists in the first place. metaData.put(GrpcUtil.CONTENT_TYPE_KEY, "to-be-removed"); metaData.put(GrpcUtil.TE_HEADER, "to-be-removed"); metaData.put(GrpcUtil.USER_AGENT_KEY, "to-be-removed"); metaData.put(userKey, userValue); Http2Headers output = Utils.convertServerHeaders(metaData); DefaultHttp2Headers headers = new DefaultHttp2Headers(); for (Map.Entry<CharSequence, CharSequence> entry : output) { headers.add(entry.getKey(), entry.getValue()); } // 2 reserved headers, 1 user header assertEquals(2 + 1, headers.size()); assertEquals(Utils.CONTENT_TYPE_GRPC, headers.get(GrpcUtil.CONTENT_TYPE_KEY.name())); }
@Test public void binaryHeadersShouldBeBase64Decoded() { Http2Headers headers = new GrpcHttp2RequestHeaders(1); byte[] data = new byte[100]; new Random().nextBytes(data); headers.add(of("foo-bin"), of(BaseEncoding.base64().encode(data))); assertEquals(1, headers.size()); byte[][] namesAndValues = ((GrpcHttp2InboundHeaders)headers).namesAndValues(); assertEquals(of("foo-bin"), new AsciiString(namesAndValues[0])); assertNotSame(data, namesAndValues[1]); assertArrayEquals(data, namesAndValues[1]); }
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; encoding=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()); }
public XrpcRequest( Http2Headers headers, Map<String, String> groups, Channel channel, int streamId) { this.h1Request = null; this.h2Headers = headers; this.groups = groups; this.upstreamChannel = channel; this.alloc = channel.alloc(); this.eventLoop = channel.eventLoop(); this.streamId = streamId; }
@Override void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endOfStream, Http2Headers headers) { // Send a frame for the response headers. encoder().writeHeaders(ctx, streamId, createResponseHeadersFromRequestHeaders(headers), 0, endOfStream, ctx.newPromise()); ctx.flush(); }
@Override void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endOfStream, Http2Headers headers) { StringBuilder response = new StringBuilder(); for (Map.Entry<CharSequence, CharSequence> header : headers) { response.append(header.getKey() + ": " + header.getValue() + "\r\n"); } sendResponseString(ctx, streamId, response.toString()); }
@Override void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endOfStream, Http2Headers headers) { encoder().writeHeaders( ctx, streamId, createDefaultResponseHeaders(), 0, false, ctx.newPromise()); encoder().writeData( ctx, streamId, RESPONSE_BYTES.duplicate(), 0, false, ctx.newPromise()); Http2Headers responseTrailers = createResponseHeadersFromRequestHeaders(headers).add( "trailer", "value1", "Value2"); encoder().writeHeaders(ctx, streamId, responseTrailers, 0, true, ctx.newPromise()); ctx.flush(); }
private static Http2Headers createResponseHeadersFromRequestHeaders( Http2Headers requestHeaders) { // Create response headers by echoing request headers. Http2Headers responseHeaders = new DefaultHttp2Headers().status(OK.codeAsText()); for (Map.Entry<CharSequence, CharSequence> header : requestHeaders) { if (!header.getKey().toString().startsWith(":")) { responseHeaders.add("echo-" + header.getKey(), header.getValue()); } } responseHeaders.add("echo-method", requestHeaders.get(":method").toString()); return responseHeaders; }
@Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception { encoder.writeHeaders(ctx, streamId, new DefaultHttp2Headers().status(HttpResponseStatus.OK.codeAsText()), 0, false, ctx.newPromise()); encoder.writeData( ctx, streamId, ctx.alloc().buffer() .writeBytes("HTTP/2 DTP".getBytes(StandardCharsets.UTF_8)), 0, true, ctx.newPromise()); }
/** * Sends a "Hello World" DATA frame to the client. */ private void sendResponse(ChannelHandlerContext ctx, ByteBuf payload) { // Send a frame for the response status Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()); ctx.write(new DefaultHttp2HeadersFrame(headers)); ctx.writeAndFlush(new DefaultHttp2DataFrame(payload, true)); }
/** * Handles the cleartext HTTP upgrade event. If an upgrade occurred, sends a simple response via HTTP/2 * on stream 1 (the stream specifically reserved for cleartext HTTP upgrade). */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof HttpServerUpgradeHandler.UpgradeEvent) { // Write an HTTP/2 response to the upgrade request Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()) .set(new AsciiString(UPGRADE_RESPONSE_HEADER), new AsciiString("true")); encoder().writeHeaders(ctx, 1, headers, 0, true, ctx.newPromise()); } super.userEventTriggered(ctx, evt); }
/** * Sends a "Hello World" DATA frame to the client. */ private void sendResponse(ChannelHandlerContext ctx, int streamId, ByteBuf payload) { // Send a frame for the response status Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()); encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise()); encoder().writeData(ctx, streamId, payload, 0, true, ctx.newPromise()); ctx.flush(); }
@Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) { if (endOfStream) { ByteBuf content = ctx.alloc().buffer(); content.writeBytes(RESPONSE_BYTES.duplicate()); ByteBufUtil.writeAscii(content, " - via HTTP/2"); sendResponse(ctx, streamId, content); } }
/** * If receive a frame with end-of-stream set, send a pre-canned response. */ @Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) throws Http2Exception { System.out.println("aaa"); if (endStream) { sendResponse(ctx, streamId, RESPONSE_BYTES.duplicate()); } }
/** * Sends a "Hello World" DATA frame to the client. */ private void sendResponse(ChannelHandlerContext ctx, int streamId, ByteBuf payload) { System.out.println("bbb"); // Send a frame for the response status Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()); encoder.writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise()); encoder.writeData(ctx, streamId, payload, 0, true, ctx.newPromise()); ctx.flush(); }
@Override public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) throws Http2Exception { HttpResponseWrapper res = getResponse(streamIdToId(streamId), endOfStream); if (res == null) { if (conn.streamMayHaveExisted(streamId)) { if (logger.isDebugEnabled()) { logger.debug("{} Received a late HEADERS frame for a closed stream: {}", ctx.channel(), streamId); } return; } throw connectionError(PROTOCOL_ERROR, "received a HEADERS frame for an unknown stream: %d", streamId); } final HttpHeaders converted = ArmeriaHttpUtil.toArmeria(headers); try { res.scheduleTimeout(ctx); res.write(converted); } catch (Throwable t) { res.close(t); throw connectionError(INTERNAL_ERROR, t, "failed to consume a HEADERS frame"); } if (endOfStream) { res.close(); } }
@Override public void onHeadersRead( ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endOfStream) throws Http2Exception { onHeadersRead(ctx, streamId, headers, padding, endOfStream); }
@Test public void outboundCookiesMustBeSplitForHttp2() { final HttpHeaders in = new DefaultHttpHeaders(); in.add(HttpHeaderNames.COOKIE, "a=b; c=d"); in.add(HttpHeaderNames.COOKIE, "e=f;g=h"); in.addObject(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8); in.add(HttpHeaderNames.COOKIE, "i=j"); in.add(HttpHeaderNames.COOKIE, "k=l;"); final Http2Headers out = toNettyHttp2(in); assertThat(out.getAll(HttpHeaderNames.COOKIE)) .containsExactly("a=b", "c=d", "e=f", "g=h", "i=j", "k=l"); }
@Test public void inboundCookiesMustBeMergedForHttp2() { final Http2Headers in = new DefaultHttp2Headers(); in.add(HttpHeaderNames.COOKIE, "a=b; c=d"); in.add(HttpHeaderNames.COOKIE, "e=f;g=h"); in.addObject(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8); in.add(HttpHeaderNames.COOKIE, "i=j"); in.add(HttpHeaderNames.COOKIE, "k=l;"); final HttpHeaders out = toArmeria(in); assertThat(out.getAll(HttpHeaderNames.COOKIE)) .containsExactly("a=b; c=d; e=f; g=h; i=j; k=l"); }
/** * This method handles the cleartext HTTP upgrade event. If an upgrade occurred, sends a simple response via HTTP/2 * on stream 1 (the stream specifically reserved for cleartext HTTP upgrade). * * @param ctx Channel context * @param evt Event * @throws Exception Throws when user event trigger has an error */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof HttpServerUpgradeHandler.UpgradeEvent) { // Write an HTTP/2 response to the upgrade request Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText()) .set(new AsciiString(Constants.UPGRADE_RESPONSE_HEADER), new AsciiString("true")); encoder().writeHeaders(ctx, 1, headers, 0, true, ctx.newPromise()); } super.userEventTriggered(ctx, evt); }
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) throws Http2Exception { HTTPCarbonMessage cMsg = publishToMessageProcessor(streamId, headers); if (endOfStream) { cMsg.setEndOfMsgAdded(true); // if (HTTPTransportContextHolder.getInstance().getHandlerExecutor() != null) { // HTTPTransportContextHolder.getInstance().getHandlerExecutor().executeAtSourceRequestSending(cMsg); // } } }
/** * Carbon Message is published to registered message processor and Message Processor should return transport. * thread immediately * * @param streamId Stream id of HTTP2 request received * @param headers HTTP2 Headers * @return HTTPCarbonMessage */ private HTTPCarbonMessage publishToMessageProcessor(int streamId, Http2Headers headers) { HTTPCarbonMessage cMsg = setupCarbonMessage(streamId, headers); // if (HTTPTransportContextHolder.getInstance().getHandlerExecutor() != null) { // HTTPTransportContextHolder.getInstance().getHandlerExecutor().executeAtSourceRequestReceiving(cMsg); // } boolean continueRequest = true; // if (HTTPTransportContextHolder.getInstance().getHandlerExecutor() != null) { // // continueRequest = HTTPTransportContextHolder.getInstance().getHandlerExecutor() // .executeRequestContinuationValidator(cMsg, carbonMessage -> { // CarbonCallback responseCallback = (CarbonCallback) cMsg // .getProperty(org.wso2.carbon.messaging.Constants.CALL_BACK); // responseCallback.done(carbonMessage); // }); // // } if (continueRequest) { CarbonMessageProcessor carbonMessageProcessor = HTTPTransportContextHolder.getInstance() .getMessageProcessor(listenerConfiguration.getMessageProcessorId()); if (carbonMessageProcessor != null) { try { // carbonMessageProcessor.receive(cMsg, new HTTP2ResponseCallback(ctx, streamId)); } catch (Exception e) { log.error("Error while submitting HTTPCarbonMessage to CarbonMessageProcessor", e); } } else { log.error("Cannot find registered MessageProcessor for forward the message"); } } return cMsg; }
Response wrapHeaders(Http2Headers headers, int streamId, boolean eos) { if (eos) { return new FullHttp2Response(headers, streamId); } else { return new StreamingHttp2Response(headers, streamId); } }