@Override public void messageReceived(ChannelInboundHandlerContext<Object> ctx, Object msg) throws Exception { Channel ch = ctx.channel(); if (!handshaker.isHandshakeComplete()) { handshaker.finishHandshake(ch, (HttpResponse) msg); System.out.println("WebSocket Client connected!"); return; } if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; throw new Exception( "Unexpected HttpResponse (status=" + response.getStatus() + ", content=" + response.getContent().toString(CharsetUtil.UTF_8) + ")"); } WebSocketFrame frame = (WebSocketFrame) msg; if (frame instanceof TextWebSocketFrame) { TextWebSocketFrame textFrame = (TextWebSocketFrame) frame; System.out.println("WebSocket Client received message: " + textFrame.getText()); } else if (frame instanceof PongWebSocketFrame) { System.out.println("WebSocket Client received pong"); } else if (frame instanceof CloseWebSocketFrame) { System.out.println("WebSocket Client received closing"); ch.close(); } }
@SuppressWarnings("deprecation") private SpdySynReplyFrame createSynReplyFrame(HttpResponse httpResponse) throws Exception { // Get the Stream-ID from the headers final HttpHeaders httpHeaders = httpResponse.headers(); int streamID = httpHeaders.getInt(Names.STREAM_ID); httpHeaders.remove(Names.STREAM_ID); // The Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding // headers are not valid and MUST not be sent. httpHeaders.remove(HttpHeaders.Names.CONNECTION); httpHeaders.remove(HttpHeaders.Names.KEEP_ALIVE); httpHeaders.remove(HttpHeaders.Names.PROXY_CONNECTION); httpHeaders.remove(HttpHeaders.Names.TRANSFER_ENCODING); SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID); SpdyHeaders frameHeaders = spdySynReplyFrame.headers(); // Unfold the first line of the response into name/value pairs frameHeaders.set(STATUS, httpResponse.status()); frameHeaders.set(VERSION, httpResponse.protocolVersion()); // Transfer the remaining HTTP headers for (Map.Entry<String, String> entry : httpHeaders) { spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue()); } currentStreamId = streamID; spdySynReplyFrame.setLast(isLast(httpResponse)); return spdySynReplyFrame; }
public static String extractCookie(HttpResponse response) { if (response.containsHeader(HttpHeaders.Names.SET_COOKIE)) { return response.getHeader(HttpHeaders.Names.SET_COOKIE); } return null; }
@Override public void sendError(int status, String message) throws IOException { if (committed) { throw new IllegalStateException(); } final HttpResponseStatus responseStatus; if (message != null) { responseStatus = new HttpResponseStatus(status, message); setStatus(status); } else { responseStatus = HttpResponseStatus.valueOf(status); setStatus(status); } io.netty.handler.codec.http.HttpResponse response = null; if (message != null) { ByteBuf byteBuf = ctx.alloc().buffer(); byteBuf.writeBytes(message.getBytes()); response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseStatus, byteBuf); } else { response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseStatus); } if (keepAlive) { // Add keep alive and content length if needed response.headers().add(Names.CONNECTION, Values.KEEP_ALIVE); if (message == null) response.headers().add(Names.CONTENT_LENGTH, 0); else response.headers().add(Names.CONTENT_LENGTH, message.getBytes().length); } ctx.writeAndFlush(response); committed = true; }
@Test public void testCompatibleExtensionTogetherSuccess() { // initialize expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("main"))) .andReturn(mainExtensionMock) .anyTimes(); expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("fallback"))) .andReturn(null) .anyTimes(); replay(mainHandshakerMock); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("fallback"))) .andReturn(fallbackExtensionMock) .anyTimes(); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("main"))) .andReturn(null) .anyTimes(); replay(fallbackHandshakerMock); expect(mainExtensionMock.rsv()).andReturn(WebSocketExtension.RSV1).anyTimes(); expect(mainExtensionMock.newReponseData()) .andReturn(new WebSocketExtensionData("main", Collections.<String, String>emptyMap())) .once(); expect(mainExtensionMock.newExtensionEncoder()).andReturn(new DummyEncoder()).once(); expect(mainExtensionMock.newExtensionDecoder()).andReturn(new DummyDecoder()).once(); replay(mainExtensionMock); expect(fallbackExtensionMock.rsv()).andReturn(WebSocketExtension.RSV2).anyTimes(); expect(fallbackExtensionMock.newReponseData()) .andReturn(new WebSocketExtensionData("fallback", Collections.<String, String>emptyMap())) .once(); expect(fallbackExtensionMock.newExtensionEncoder()).andReturn(new Dummy2Encoder()).once(); expect(fallbackExtensionMock.newExtensionDecoder()).andReturn(new Dummy2Decoder()).once(); replay(fallbackExtensionMock); // execute EmbeddedChannel ch = new EmbeddedChannel( new WebSocketServerExtensionHandler(mainHandshakerMock, fallbackHandshakerMock)); HttpRequest req = newUpgradeRequest("main, fallback"); ch.writeInbound(req); HttpResponse res = newUpgradeResponse(null); ch.writeOutbound(res); HttpResponse res2 = ch.readOutbound(); List<WebSocketExtensionData> resExts = WebSocketExtensionUtil.extractExtensions( res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS)); // test assertEquals(2, resExts.size()); assertEquals("main", resExts.get(0).name()); assertEquals("fallback", resExts.get(1).name()); assertNotNull(ch.pipeline().get(DummyDecoder.class)); assertNotNull(ch.pipeline().get(DummyEncoder.class)); assertNotNull(ch.pipeline().get(Dummy2Decoder.class)); assertNotNull(ch.pipeline().get(Dummy2Encoder.class)); }
private boolean handleResponseAndExit( final Channel channel, final NettyResponseFuture<?> future, AsyncHandler<?> handler, HttpRequest httpRequest, ProxyServer proxyServer, HttpResponse response) throws Exception { // store the original headers so we can re-send all them to // the handler in case of trailing headers future.setHttpHeaders(response.headers()); future.setKeepAlive( !HttpHeaders.Values.CLOSE.equalsIgnoreCase( response.headers().get(HttpHeaders.Names.CONNECTION))); HttpResponseStatus status = new ResponseStatus(future.getURI(), response, config); int statusCode = response.getStatus().code(); Request request = future.getRequest(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); HttpResponseHeaders responseHeaders = new ResponseHeaders(future.getURI(), response.headers()); return handleResponseFiltersReplayRequestAndExit(channel, future, status, responseHeaders) // || handleUnauthorizedAndExit( statusCode, realm, request, response, future, proxyServer, channel) // || handleContinueAndExit(channel, future, statusCode) // || handleProxyAuthenticationRequiredAndExit( statusCode, realm, request, response, future, proxyServer) || handleConnectOKAndExit( statusCode, realm, request, httpRequest, response, future, proxyServer, channel) // || handleRedirectAndExit(request, future, response, channel) // || handleHanderAndExit(channel, future, handler, status, responseHeaders, response); }
@Test public void testNoneExtensionMatchingSuccess() { // initialize expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown"))) .andReturn(null) .anyTimes(); expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown2"))) .andReturn(null) .anyTimes(); replay(mainHandshakerMock); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown"))) .andReturn(null) .anyTimes(); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown2"))) .andReturn(null) .anyTimes(); replay(fallbackHandshakerMock); // execute EmbeddedChannel ch = new EmbeddedChannel( new WebSocketServerExtensionHandler(mainHandshakerMock, fallbackHandshakerMock)); HttpRequest req = newUpgradeRequest("unknown, unknown2"); ch.writeInbound(req); HttpResponse res = newUpgradeResponse(null); ch.writeOutbound(res); HttpResponse res2 = ch.readOutbound(); // test assertFalse(res2.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS)); }
@Override public void fatalError(String message, String stack) { if (log.isDebugEnabled()) { log.debug("Sending HTTP error due to script error {}", message); } StringBuilder msg = new StringBuilder(message); if (stack != null) { msg.append('\n'); msg.append(stack); } ByteBuf data = Unpooled.copiedBuffer(msg, Charsets.UTF8); response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); response.headers().add("Content-Type", "text/plain"); response.headers().add("Content-Length", data.readableBytes()); calculateKeepAlive(true); channel.write(response); DefaultHttpContent chunk = new DefaultHttpContent(data); channel.write(chunk); sendLastChunk(); channel.flush(); if (!keepAlive) { shutDown(); } }
public HttpResponse clientToProxyRequest(HttpObject httpObject) { if (httpObject instanceof DefaultHttpRequest) { DefaultHttpRequest fullreq = (DefaultHttpRequest) httpObject; Content c = null; // only return if content exist & at least one quality is // available if ((c = content.get(fullreq.getUri())) != null && c.getQualities().size() > 0) { LOGGER.debug("Cached resource found {}", c.getUri()); HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.TEMPORARY_REDIRECT); Collections.shuffle(c.getQualities()); String redirectUri = UriBuilder.fromPath( "http://" + config.getFrontalHostName() + ":" + config.getFrontalPort()) .path("api") .path("content") .path(c.getId()) .path(c.getQualities().get(0)) .build() .toString(); response.headers().add("Location", redirectUri); LOGGER.debug("Redirecting it to ", redirectUri); return response; } } return null; }
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { logger.debug("================进入客户端InBoundHandler channelRead============"); // 如果是response if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; logger.debug( "客户端收到的响应CONTENT_TYPE:" + response.headers().get(HttpHeaders.Names.CONTENT_TYPE)); if (HttpHeaders.isContentLengthSet(response)) { reader = new ByteBufToBytes((int) HttpHeaders.getContentLength(response)); } } if (msg instanceof HttpContent) { HttpContent httpContent = (HttpContent) msg; ByteBuf content = httpContent.content(); reader.reading(content); content.release(); if (reader.isEnd()) { String resultStr = new String(reader.readFull()); logger.debug("收到的服务端的消息是:" + resultStr); ctx.close(); } } logger.debug("================出客户端InBoundHandler channelRead============"); }
@Override public Object encode(ChannelHandlerContext ctx, Object msg) throws Exception { List<Object> out = new ArrayList<Object>(); if (msg instanceof HttpRequest) { HttpRequest httpRequest = (HttpRequest) msg; SpdySynStreamFrame spdySynStreamFrame = createSynStreamFrame(httpRequest); int streamID = spdySynStreamFrame.getStreamID(); out.add(spdySynStreamFrame); addContent(out, streamID, httpRequest); } else if (msg instanceof HttpResponse) { HttpResponse httpResponse = (HttpResponse) msg; if (httpResponse.containsHeader(SpdyHttpHeaders.Names.ASSOCIATED_TO_STREAM_ID)) { SpdySynStreamFrame spdySynStreamFrame = createSynStreamFrame(httpResponse); int streamID = spdySynStreamFrame.getStreamID(); out.add(spdySynStreamFrame); addContent(out, streamID, httpResponse); } else { SpdySynReplyFrame spdySynReplyFrame = createSynReplyFrame(httpResponse); int streamID = spdySynReplyFrame.getStreamID(); out.add(spdySynReplyFrame); addContent(out, streamID, httpResponse); } } else if (msg instanceof HttpChunk) { HttpChunk chunk = (HttpChunk) msg; SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(currentStreamID); spdyDataFrame.setData(chunk.getContent()); spdyDataFrame.setLast(chunk.isLast()); if (chunk instanceof HttpChunkTrailer) { HttpChunkTrailer trailer = (HttpChunkTrailer) chunk; List<Map.Entry<String, String>> trailers = trailer.getHeaders(); if (trailers.isEmpty()) { out.add(spdyDataFrame); } else { // Create SPDY HEADERS frame out of trailers SpdyHeadersFrame spdyHeadersFrame = new DefaultSpdyHeadersFrame(currentStreamID); for (Map.Entry<String, String> entry : trailers) { spdyHeadersFrame.addHeader(entry.getKey(), entry.getValue()); } // Write HEADERS frame and append Data Frame out.add(spdyHeadersFrame); out.add(spdyDataFrame); } } else { out.add(spdyDataFrame); } } else { throw new UnsupportedMessageTypeException(msg); } return out.toArray(); }
HttpClientResponseImpl( HttpClientRequestImpl request, ClientConnection conn, HttpResponse response) { this.statusCode = response.getStatus().code(); this.statusMessage = response.getStatus().reasonPhrase(); this.request = request; this.conn = conn; this.response = response; }
public static HttpResponse createRejection(HttpRequest request, String reason) { HttpVersion version = request != null ? request.getProtocolVersion() : HttpVersion.HTTP_1_1; HttpResponse response = new DefaultHttpResponse(version, HttpResponseStatus.BAD_REQUEST); response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=\"utf-8\""); ChannelBuffer reasonBuffer = ChannelBuffers.wrappedBuffer(toBytes(reason)); response.setHeader( HttpHeaders.Names.CONTENT_LENGTH, Integer.toString(reasonBuffer.readableBytes())); response.setContent(reasonBuffer); return response; }
private SpdySynReplyFrame createSynReplyFrame(HttpResponse httpResponse) throws Exception { boolean chunked = httpResponse.isChunked(); // Get the Stream-ID from the headers int streamID = SpdyHttpHeaders.getStreamID(httpResponse); SpdyHttpHeaders.removeStreamID(httpResponse); // The Connection, Keep-Alive, Proxy-Connection, and Transfer-ENcoding // headers are not valid and MUST not be sent. httpResponse.removeHeader(HttpHeaders.Names.CONNECTION); httpResponse.removeHeader("Keep-Alive"); httpResponse.removeHeader("Proxy-Connection"); httpResponse.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING); SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID); // Unfold the first line of the response into name/value pairs SpdyHeaders.setStatus(spdyVersion, spdySynReplyFrame, httpResponse.getStatus()); SpdyHeaders.setVersion(spdyVersion, spdySynReplyFrame, httpResponse.getProtocolVersion()); // Transfer the remaining HTTP headers for (Map.Entry<String, String> entry : httpResponse.getHeaders()) { spdySynReplyFrame.addHeader(entry.getKey(), entry.getValue()); } if (chunked) { currentStreamID = streamID; spdySynReplyFrame.setLast(false); } else { spdySynReplyFrame.setLast(httpResponse.getContent().readableBytes() == 0); } return spdySynReplyFrame; }
/** * Verifies that a request returns the right response code once the blob has been deleted. * * @param httpRequest the {@link FullHttpRequest} to send to the server. * @param expectedStatusCode the expected {@link HttpResponseStatus}. * @throws ExecutionException * @throws InterruptedException */ private void verifyDeleted(FullHttpRequest httpRequest, HttpResponseStatus expectedStatusCode) throws ExecutionException, InterruptedException { Queue<HttpObject> responseParts = nettyClient.sendRequest(httpRequest, null, null).get(); HttpResponse response = (HttpResponse) responseParts.poll(); assertEquals("Unexpected response status", expectedStatusCode, response.getStatus()); assertTrue( "No Date header", HttpHeaders.getDateHeader(response, HttpHeaders.Names.DATE, null) != null); discardContent(responseParts, 1); assertTrue("Channel should be active", HttpHeaders.isKeepAlive(response)); }
public static boolean hasContents(HttpResponse response, byte[] expectedContents) { if (response.getContent() != null && HttpHeaders.getContentLength(response, 0) == expectedContents.length && response.getContent().readableBytes() == expectedContents.length) { byte[] compareBytes = new byte[expectedContents.length]; response.getContent().readBytes(compareBytes); return Arrays.equals(expectedContents, compareBytes); } return false; }
@Override public HttpResponse call() throws Exception { HttpResponse response = null; response = new DefaultFullHttpResponse(RtspVersions.RTSP_1_0, RtspResponseStatuses.OK); response.headers().add(RtspHeaderNames.SERVER, "RtspServer"); response.headers().add(RtspHeaderNames.CSEQ, this.request.headers().get(RtspHeaderNames.CSEQ)); response .headers() .add(RtspHeaderNames.PUBLIC, "SETUP,PLAY,PAUSE,TEARDOWN,GET_PARAMETER,OPTION"); return response; }
public void channelRead(final ChannelHandlerContext remoteChannelCtx, final Object msg) throws Exception { LoggerUtil.debug( logger, uaChannel.attr(ApnProxyConnectionAttribute.ATTRIBUTE_KEY), "Remote msg", msg); remainMsgCount++; if (remainMsgCount <= 5) { remoteChannelCtx.read(); } HttpObject ho = (HttpObject) msg; if (ho instanceof HttpResponse) { HttpResponse httpResponse = (HttpResponse) ho; LoggerUtil.info( forwardRestLogger, uaChannel.attr(ApnProxyConnectionAttribute.ATTRIBUTE_KEY), httpResponse.getStatus(), httpResponse.getProtocolVersion()); httpResponse.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); httpResponse.headers().set("Proxy-Connection", HttpHeaders.Values.KEEP_ALIVE); } if (uaChannel.isActive()) { uaChannel .writeAndFlush(ho) .addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { LoggerUtil.debug( logger, uaChannel.attr(ApnProxyConnectionAttribute.ATTRIBUTE_KEY), "Write to UA finished: " + future.isSuccess()); if (future.isSuccess()) { remainMsgCount--; remoteChannelCtx.read(); LoggerUtil.debug( logger, uaChannel.attr(ApnProxyConnectionAttribute.ATTRIBUTE_KEY), "Fire read again"); } else { remoteChannelCtx.close(); } } }); } else { remoteChannelCtx.close(); } }
private static void parseHeaders(@NotNull HttpResponse response, @NotNull ByteBuf buffer) { StringBuilder builder = new StringBuilder(); while (buffer.isReadable()) { builder.setLength(0); String key = null; boolean valueExpected = true; while (true) { int b = buffer.readByte(); if (b < 0 || b == '\n') { break; } if (b != '\r') { if (valueExpected && b == ':') { valueExpected = false; key = builder.toString(); builder.setLength(0); MessageDecoder.skipWhitespace(buffer); } else { builder.append((char) b); } } } if (builder.length() == 0) { // end of headers return; } // skip standard headers if (StringUtil.isEmpty(key) || StringUtilRt.startsWithIgnoreCase(key, "http") || StringUtilRt.startsWithIgnoreCase(key, "X-Accel-")) { continue; } String value = builder.toString(); if (key.equalsIgnoreCase("status")) { int index = value.indexOf(' '); if (index == -1) { LOG.warn("Cannot parse status: " + value); response.setStatus(HttpResponseStatus.OK); } else { response.setStatus( HttpResponseStatus.valueOf(Integer.parseInt(value.substring(0, index)))); } } else if (!(key.startsWith("http") || key.startsWith("HTTP"))) { response.headers().add(key, value); } } }
/** * Gets the blob info of the blob with blob ID {@code blobId} and verifies them against what is * expected. * * @param blobId the blob ID of the blob to HEAD. * @param expectedHeaders the expected headers in the response. * @param usermetadata if non-null, this is expected to come as the body. * @throws ExecutionException * @throws InterruptedException */ private void getBlobInfoAndVerify(String blobId, HttpHeaders expectedHeaders, byte[] usermetadata) throws ExecutionException, InterruptedException { FullHttpRequest httpRequest = buildRequest(HttpMethod.GET, blobId + "/" + RestUtils.SubResource.BlobInfo, null, null); Queue<HttpObject> responseParts = nettyClient.sendRequest(httpRequest, null, null).get(); HttpResponse response = (HttpResponse) responseParts.poll(); assertEquals("Unexpected response status", HttpResponseStatus.OK, response.getStatus()); checkCommonGetHeadHeaders(response.headers()); verifyBlobProperties(expectedHeaders, response); verifyUserMetadata(expectedHeaders, response, usermetadata, responseParts); assertTrue("Channel should be active", HttpHeaders.isKeepAlive(response)); }
public static Object extractErrorMessage(HttpResponse response) { if (response.getContent() == null || HttpHeaders.getContentLength(response, 0) == 0) { return ""; } byte[] bytes = new byte[response.getContent().readableBytes()]; response.getContent().readBytes(bytes); try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { return ""; } }
private void checkResponseCode(ChannelHandlerContext ctx, HttpResponse response) throws Exception { boolean discardBody = false; int code = response.getStatus().code(); if (code == HttpResponseStatus.NOT_FOUND.code() || code == HttpResponseStatus.BAD_REQUEST.code()) { exceptionCaught(ctx, new HttpException(response.getStatus())); discardBody = true; } setDiscardBody(discardBody); }
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) { // Generate an error page if response status code is not OK (200). if (res.getStatus().getCode() != 200) { res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8)); setContentLength(res, res.getContent().readableBytes()); } // Send the response and close the connection if necessary. ChannelFuture f = ctx.getChannel().write(res); if (!isKeepAlive(req) || res.getStatus().getCode() != 200) { f.addListener(ChannelFutureListener.CLOSE); } }
@Override public @Nullable FullHttpResponse handleRequest(ChannelHandlerContext ctx, HttpRequest request) throws Exception { QueryStringDecoder decoder = new QueryStringDecoder(request.uri()); List<String> agentIds = decoder.parameters().get("agent-id"); if (agentIds == null) { agentIds = ImmutableList.of(""); } String agentId = agentIds.get(0); List<String> traceIds = decoder.parameters().get("trace-id"); checkNotNull(traceIds, "Missing trace id in query string: %s", request.uri()); String traceId = traceIds.get(0); // check-live-traces is an optimization so glowroot server only has to check with remote // agents when necessary List<String> checkLiveTracesParams = decoder.parameters().get("check-live-traces"); boolean checkLiveTraces = false; if (checkLiveTracesParams != null && !checkLiveTracesParams.isEmpty()) { checkLiveTraces = Boolean.parseBoolean(checkLiveTracesParams.get(0)); } logger.debug( "handleRequest(): agentId={}, traceId={}, checkLiveTraces={}", agentId, traceId, checkLiveTraces); TraceExport traceExport = traceCommonService.getExport(agentId, traceId, checkLiveTraces); if (traceExport == null) { logger.warn("no trace found for id: {}", traceId); return new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND); } ChunkedInput<HttpContent> in = getExportChunkedInput(traceExport); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED); response.headers().set(HttpHeaderNames.CONTENT_TYPE, MediaType.ZIP.toString()); response .headers() .set("Content-Disposition", "attachment; filename=" + traceExport.fileName() + ".zip"); boolean keepAlive = HttpUtil.isKeepAlive(request); if (keepAlive && !request.protocolVersion().isKeepAliveDefault()) { response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); } HttpServices.preventCaching(response); ctx.write(response); ChannelFuture future = ctx.write(in); HttpServices.addErrorListener(future); if (!keepAlive) { HttpServices.addCloseListener(future); } // return null to indicate streaming return null; }
/** * Process server response: * * <pre> * HTTP/1.1 101 WebSocket Protocol Handshake * Upgrade: WebSocket * Connection: Upgrade * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Location: ws://example.com/demo * Sec-WebSocket-Protocol: sample * * 8jKS'y:G*Co,Wxa- * </pre> * * @param ctx Channel context * @param response HTTP response returned from the server for the request sent by * beginOpeningHandshake00(). * @throws WebSocketHandshakeException */ @Override public void performClosingHandshake(ChannelHandlerContext ctx, HttpResponse response) throws WebSocketHandshakeException { final HttpResponseStatus status = new HttpResponseStatus(101, "WebSocket Protocol Handshake"); if (!response.getStatus().equals(status)) { throw new WebSocketHandshakeException( "Invalid handshake response status: " + response.getStatus()); } String upgrade = response.getHeader(Names.UPGRADE); if (upgrade == null || !upgrade.equals(Values.WEBSOCKET)) { throw new WebSocketHandshakeException( "Invalid handshake response upgrade: " + response.getHeader(Names.UPGRADE)); } String connection = response.getHeader(Names.CONNECTION); if (connection == null || !connection.equals(Values.UPGRADE)) { throw new WebSocketHandshakeException( "Invalid handshake response connection: " + response.getHeader(Names.CONNECTION)); } byte[] challenge = response.getContent().array(); if (!Arrays.equals(challenge, expectedChallengeResponseBytes)) { throw new WebSocketHandshakeException("Invalid challenge"); } String protocol = response.getHeader(Names.SEC_WEBSOCKET_PROTOCOL); this.setSubProtocolResponse(protocol); ctx.getPipeline().replace("decoder", "ws-decoder", new WebSocket00FrameDecoder()); this.setOpenningHandshakeCompleted(true); }
protected void processHeadRequest( ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) { if (_logger.isTraceEnabled()) { Channel channel = channelHandlerContext.channel(); _logger.trace( "Client {}: processing head request {}", channel.remoteAddress(), fullHttpRequest.uri()); } SyncFile syncFile = _getSyncFile(fullHttpRequest); if (syncFile == null) { _sendError(channelHandlerContext, NOT_FOUND); return; } String lanTokenKey = syncFile.getLanTokenKey(); if ((lanTokenKey == null) || lanTokenKey.isEmpty()) { _sendError(channelHandlerContext, NOT_FOUND); return; } String encryptedToken = null; try { encryptedToken = LanTokenUtil.createEncryptedToken(lanTokenKey); } catch (Exception e) { _sendError(channelHandlerContext, NOT_FOUND); return; } HttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, OK); HttpHeaders httpHeaders = httpResponse.headers(); httpHeaders.set("connectionsCount", _syncTrafficShapingHandler.getConnectionsCount()); httpHeaders.set("downloadRate", _trafficCounter.lastWrittenBytes()); httpHeaders.set("encryptedToken", encryptedToken); httpHeaders.set("maxConnections", PropsValues.SYNC_LAN_SERVER_MAX_CONNECTIONS); channelHandlerContext.writeAndFlush(httpResponse); }
/** * Gets the blob with blob ID {@code blobId} and verifies that the headers and content match with * what is expected. * * @param blobId the blob ID of the blob to GET. * @param range the {@link ByteRange} for the request. * @param expectedHeaders the expected headers in the response. * @param expectedContent the expected content of the blob. * @throws ExecutionException * @throws InterruptedException */ private void getBlobAndVerify( String blobId, ByteRange range, HttpHeaders expectedHeaders, ByteBuffer expectedContent) throws ExecutionException, InterruptedException, RestServiceException { HttpHeaders headers = null; if (range != null) { headers = new DefaultHttpHeaders() .add(RestUtils.Headers.RANGE, RestTestUtils.getRangeHeaderString(range)); } FullHttpRequest httpRequest = buildRequest(HttpMethod.GET, blobId, headers, null); Queue<HttpObject> responseParts = nettyClient.sendRequest(httpRequest, null, null).get(); HttpResponse response = (HttpResponse) responseParts.poll(); assertEquals( "Unexpected response status", range == null ? HttpResponseStatus.OK : HttpResponseStatus.PARTIAL_CONTENT, response.getStatus()); checkCommonGetHeadHeaders(response.headers()); assertEquals( "Content-Type does not match", expectedHeaders.get(RestUtils.Headers.AMBRY_CONTENT_TYPE), response.headers().get(HttpHeaders.Names.CONTENT_TYPE)); assertEquals( RestUtils.Headers.BLOB_SIZE + " does not match", expectedHeaders.get(RestUtils.Headers.BLOB_SIZE), response.headers().get(RestUtils.Headers.BLOB_SIZE)); assertEquals( "Accept-Ranges not set correctly", "bytes", response.headers().get(RestUtils.Headers.ACCEPT_RANGES)); byte[] expectedContentArray = expectedContent.array(); if (range != null) { long blobSize = Long.parseLong(expectedHeaders.get(RestUtils.Headers.BLOB_SIZE)); assertEquals( "Content-Range header not set correctly", RestUtils.buildContentRangeAndLength(range, blobSize).getFirst(), response.headers().get(RestUtils.Headers.CONTENT_RANGE)); ByteRange resolvedRange = range.toResolvedByteRange(blobSize); expectedContentArray = Arrays.copyOfRange( expectedContentArray, (int) resolvedRange.getStartOffset(), (int) resolvedRange.getEndOffset() + 1); } else { assertNull( "Content-Range header should not be set", response.headers().get(RestUtils.Headers.CONTENT_RANGE)); } if (expectedContentArray.length < FRONTEND_CONFIG.frontendChunkedGetResponseThresholdInBytes) { assertEquals( "Content-length not as expected", expectedContentArray.length, HttpHeaders.getContentLength(response)); } byte[] responseContentArray = getContent(responseParts, expectedContentArray.length).array(); assertArrayEquals( "GET content does not match original content", expectedContentArray, responseContentArray); assertTrue("Channel should be active", HttpHeaders.isKeepAlive(response)); }
/** * Sets the Date and Cache headers for the HTTP Response * * @param response HTTP response * @param fileToCache file to extract content type */ private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE)); // Date header Calendar time = new GregorianCalendar(); response.headers().set(DATE, dateFormatter.format(time.getTime())); // Add cache headers time.add(Calendar.SECOND, HTTP_CACHE_SECONDS); response.headers().set(EXPIRES, dateFormatter.format(time.getTime())); response.headers().set(CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS); response .headers() .set(LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified()))); }
private boolean exitAfterSpecialCases( final HttpResponse response, final Channel channel, final NettyResponseFuture<?> future) throws Exception { HttpRequest httpRequest = future.getNettyRequest().getHttpRequest(); ProxyServer proxyServer = future.getProxyServer(); int statusCode = response.getStatus().code(); Request request = future.getCurrentRequest(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (statusCode == UNAUTHORIZED_401) { return exitAfterHandling401( channel, future, response, request, statusCode, realm, proxyServer, httpRequest); } else if (statusCode == PROXY_AUTHENTICATION_REQUIRED_407) { return exitAfterHandling407( channel, future, response, request, statusCode, proxyServer, httpRequest); } else if (statusCode == CONTINUE_100) { return exitAfterHandling100(channel, future, statusCode); } else if (REDIRECT_STATUSES.contains(statusCode)) { return exitAfterHandlingRedirect(channel, future, response, request, statusCode, realm); } else if (httpRequest.getMethod() == HttpMethod.CONNECT && statusCode == OK_200) { return exitAfterHandlingConnect( channel, future, request, proxyServer, statusCode, httpRequest); } return false; }
/** * Sets the value of response headers after making sure that the response metadata is not already * sent. * * @param headerName The name of the header. * @param headerValue The intended value of the header. * @throws IllegalArgumentException if any of {@code headerName} or {@code headerValue} is null. * @throws IllegalStateException if response metadata has already been written to the channel. */ private void setResponseHeader(String headerName, Object headerValue) { if (headerName != null && headerValue != null) { long startTime = System.currentTimeMillis(); if (headerValue instanceof Date) { HttpHeaders.setDateHeader(responseMetadata, headerName, (Date) headerValue); } else { HttpHeaders.setHeader(responseMetadata, headerName, headerValue); } if (responseMetadataWritten.get()) { nettyMetrics.deadResponseAccessError.inc(); throw new IllegalStateException( "Response metadata changed after it has already been written to the channel"); } else { logger.trace( "Header {} set to {} for channel {}", headerName, responseMetadata.headers().get(headerName), ctx.channel()); nettyMetrics.headerSetTimeInMs.update(System.currentTimeMillis() - startTime); } } else { throw new IllegalArgumentException( "Header name [" + headerName + "] or header value [" + headerValue + "] null"); } }