private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { // Handle a bad request. if (!req.getDecoderResult().isSuccess()) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)); req.release(); return; } // Allow only GET methods. if (req.getMethod() != GET) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); req.release(); return; } // Handshake WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(req), null, false, Integer.MAX_VALUE); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); } else { handshaker.handshake(ctx.channel(), req); } req.release(); }
@Test public void clientRequestMultipleEmptyDataFrames() throws Exception { final String text = ""; final ByteBuf content = Unpooled.copiedBuffer(text.getBytes()); final FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, "/some/path/resource2", content, true); try { HttpHeaders httpHeaders = request.headers(); httpHeaders.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3); httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, text.length()); final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(as("/some/path/resource2")); runInChannel( clientChannel, new Http2Runnable() { @Override public void run() { frameWriter.writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); frameWriter.writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient()); frameWriter.writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient()); frameWriter.writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient()); ctxClient().flush(); } }); awaitRequests(); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); verify(serverListener).messageReceived(requestCaptor.capture()); capturedRequests = requestCaptor.getAllValues(); assertEquals(request, capturedRequests.get(0)); } finally { request.release(); } }
@Test public void clientRequestStreamDependencyInHttpMessageFlow() throws Exception { setServerLatch(2); final String text = "hello world big time data!"; final ByteBuf content = Unpooled.copiedBuffer(text.getBytes()); final String text2 = "hello world big time data...number 2!!"; final ByteBuf content2 = Unpooled.copiedBuffer(text2.getBytes()); final FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.PUT, "/some/path/resource", content, true); final FullHttpMessage request2 = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.PUT, "/some/path/resource2", content2, true); try { HttpHeaders httpHeaders = request.headers(); httpHeaders.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3); httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, text.length()); HttpHeaders httpHeaders2 = request2.headers(); httpHeaders2.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 5); httpHeaders2.set(HttpUtil.ExtensionHeaderNames.STREAM_DEPENDENCY_ID.text(), 3); httpHeaders2.set(HttpUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), 123); httpHeaders2.set(HttpHeaders.Names.CONTENT_LENGTH, text2.length()); final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("PUT")).path(as("/some/path/resource")); final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(as("PUT")).path(as("/some/path/resource2")); runInChannel( clientChannel, new Http2Runnable() { @Override public void run() { frameWriter.writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); frameWriter.writeHeaders(ctxClient(), 5, http2Headers2, 0, false, newPromiseClient()); frameWriter.writePriority(ctxClient(), 5, 3, (short) 123, true, newPromiseClient()); frameWriter.writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient()); frameWriter.writeData(ctxClient(), 5, content2.retain(), 0, true, newPromiseClient()); ctxClient().flush(); } }); awaitRequests(); ArgumentCaptor<FullHttpMessage> httpObjectCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); verify(serverListener, times(2)).messageReceived(httpObjectCaptor.capture()); capturedRequests = httpObjectCaptor.getAllValues(); assertEquals(request, capturedRequests.get(0)); assertEquals(request2, capturedRequests.get(1)); } finally { request.release(); request2.release(); } }
@Test public void clientRequestMultipleHeaders() throws Exception { // writeHeaders will implicitly add an END_HEADERS tag each time and so this test does not // follow the HTTP // message flow. We currently accept this message flow and just add the second headers to the // trailing headers. final String text = ""; final ByteBuf content = Unpooled.copiedBuffer(text.getBytes()); final FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, "/some/path/resource2", content, true); try { HttpHeaders httpHeaders = request.headers(); httpHeaders.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3); httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, text.length()); HttpHeaders trailingHeaders = request.trailingHeaders(); trailingHeaders.set("FoO", "goo"); trailingHeaders.set("foO2", "goo2"); trailingHeaders.add("fOo2", "goo3"); final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(as("/some/path/resource2")); final Http2Headers http2Headers2 = new DefaultHttp2Headers() .set(as("foo"), as("goo")) .set(as("foo2"), as("goo2")) .add(as("foo2"), as("goo3")); runInChannel( clientChannel, new Http2Runnable() { @Override public void run() { frameWriter.writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient()); frameWriter.writeHeaders(ctxClient(), 3, http2Headers2, 0, false, newPromiseClient()); frameWriter.writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient()); ctxClient().flush(); } }); awaitRequests(); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); verify(serverListener).messageReceived(requestCaptor.capture()); capturedRequests = requestCaptor.getAllValues(); assertEquals(request, capturedRequests.get(0)); } finally { request.release(); } }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { FullHttpRequest request = (FullHttpRequest) msg; logger.debug("messageReceived(): request.uri={}", request.uri()); Channel channel = ctx.channel(); currentChannel.set(channel); try { FullHttpResponse response = handleRequest(ctx, request); if (response != null) { sendFullResponse(ctx, request, response); } } catch (Exception f) { logger.error(f.getMessage(), f); FullHttpResponse response = newHttpResponseWithStackTrace(f, INTERNAL_SERVER_ERROR, null); sendFullResponse(ctx, request, response); } finally { currentChannel.remove(); request.release(); } }
@Test public void clientRequestSingleHeaderNoDataFrames() throws Exception { final FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, "/some/path/resource2", true); try { HttpHeaders httpHeaders = request.headers(); httpHeaders.set(HttpUtil.ExtensionHeaderNames.SCHEME.text(), "https"); httpHeaders.set(HttpUtil.ExtensionHeaderNames.AUTHORITY.text(), "example.org"); httpHeaders.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3); httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, 0); final Http2Headers http2Headers = new DefaultHttp2Headers() .method(as("GET")) .scheme(as("https")) .authority(as("example.org")) .path(as("/some/path/resource2")); runInChannel( clientChannel, new Http2Runnable() { @Override public void run() { frameWriter.writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient()); ctxClient().flush(); } }); awaitRequests(); ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class); verify(serverListener).messageReceived(requestCaptor.capture()); capturedRequests = requestCaptor.getAllValues(); assertEquals(request, capturedRequests.get(0)); } finally { request.release(); } }