/** * 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 endOpeningHandshake(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); return; }
public static void send(HttpResponse response, Channel channel, @Nullable HttpRequest request) { ChannelBuffer content = response.getContent(); setContentLength( response, content == ChannelBuffers.EMPTY_BUFFER ? 0 : content.readableBytes()); boolean keepAlive = request != null && addKeepAliveIfNeed(response, request); addCommonHeaders(response); send(response, channel, !keepAlive); }
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); } }
/* * 私有函数,服务器发送响应给用户时将被调用调用 * @param [ctx] channelHandler中的上下文 * @param [req] 消息请求 * @param [res] 消息响应 */ private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) { if (res.getStatus().getCode() != 200) { // 将响应信息以UTF_8编码格式写回 ChannelBuffer content = ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8); int contentLength = res.getContent().readableBytes(); buildResponse(res, false, null, content, contentLength); } ChannelFuture f = ctx.getChannel().write(res); if (!isKeepAlive(req) || res.getStatus().getCode() != 200) { f.addListener(ChannelFutureListener.CLOSE); } }
@Override public Message toCamelMessage( HttpResponse response, Exchange exchange, NettyHttpConfiguration configuration) throws Exception { LOG.trace("toCamelMessage: {}", response); NettyHttpMessage answer = new NettyHttpMessage(null, response); answer.setExchange(exchange); if (configuration.isMapHeaders()) { populateCamelHeaders(response, answer.getHeaders(), exchange, configuration); } // keep the body as is, and use type converters answer.setBody(response.getContent()); return answer; }
private void sendHttpResponse(Channel channel, HttpRequest request, HttpResponse response) { if (!channel.isOpen()) { return; } // response的内容已在各Listener中填充 response.headers().set(Names.CONTENT_LENGTH, response.getContent().readableBytes()); response.headers().set(Names.SERVER, "NAVI/1.1.4(UNIX)"); if (!HttpHeaders.isKeepAlive(request) || response.getStatus() != HttpResponseStatus.OK || ServerConfigure.isChannelClose()) { response.headers().set(Names.CONNECTION, "close"); channel.setAttachment(WRITING); ChannelFuture f = channel.write(response); f.addListener(ChannelFutureListener.CLOSE); f.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { log.error(f.getCause().getMessage(), f.getCause()); } } }); } else { if (request.getProtocolVersion() == HttpVersion.HTTP_1_0) { response.headers().add(Names.CONNECTION, "Keep-Alive"); } channel.setAttachment(WRITING); ChannelFuture f = channel.write(response); f.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); f.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { log.error(f.getCause().getMessage(), f.getCause()); } } }); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Channel ch = e.getChannel(); ClientConnection conn = connectionMap.get(ch); Object msg = e.getMessage(); if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; conn.handleResponse(response); ChannelBuffer content = response.getContent(); if (content.readable()) { conn.handleResponseChunk(new Buffer(content)); } if (!response.isChunked()) { conn.handleResponseEnd(); } } else if (msg instanceof HttpChunk) { HttpChunk chunk = (HttpChunk) msg; if (chunk.getContent().readable()) { Buffer buff = new Buffer(chunk.getContent()); conn.handleResponseChunk(buff); } if (chunk.isLast()) { if (chunk instanceof HttpChunkTrailer) { HttpChunkTrailer trailer = (HttpChunkTrailer) chunk; conn.handleResponseEnd(trailer); } else { conn.handleResponseEnd(); } } } else if (msg instanceof WebSocketFrame) { WebSocketFrame frame = (WebSocketFrame) msg; conn.handleWsFrame(frame); } else { throw new IllegalStateException("Invalid object " + e.getMessage()); } }
public void writeResponse(byte[] responseValue) { this.responseContent = ChannelBuffers.dynamicBuffer(responseValue.length); this.responseContent.writeBytes(responseValue); // 1. Create the Response object HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); // 2. Set the right headers response.setHeader(CONTENT_TYPE, "binary"); response.setHeader(CONTENT_TRANSFER_ENCODING, "binary"); // 3. Copy the data into the payload response.setContent(responseContent); response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes()); if (logger.isDebugEnabled()) { logger.debug("Response = " + response); } // Write the response to the Netty Channel this.getRequestMessageEvent.getChannel().write(response); }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Channel ch = ctx.getChannel(); if (!handshaker.isHandshakeComplete()) { handshaker.finishHandshake(ch, (HttpResponse) e.getMessage()); handler.onConnect(); return; } if (e.getMessage() instanceof HttpResponse) { HttpResponse response = (HttpResponse) e.getMessage(); String message = "Unexpected HttpResponse (status=" + response.getStatus() + ", content=" + response.getContent().toString(CharsetUtil.UTF_8) + ')'; log.error(String.format("Web socket client: %s", message)); throw new Exception(message); } WebSocketFrame frame = (WebSocketFrame) e.getMessage(); if (frame instanceof TextWebSocketFrame) { TextWebSocketFrame textFrame = (TextWebSocketFrame) frame; try { handler.onReceive(MAPPER.parseObject(textFrame.getText())); } catch (Exception e1) { log.error("Error while decoding JSON websocket message", e1); } } else if (frame instanceof PongWebSocketFrame) { } else if (frame instanceof CloseWebSocketFrame) { ch.close(); } }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!readingChunks) { HttpResponse response = (HttpResponse) e.getMessage(); StringBuilder sb = new StringBuilder(); if (LOG.isDebugEnabled()) { sb.append("STATUS: ") .append(response.getStatus()) .append(", VERSION: ") .append(response.getProtocolVersion()) .append(", HEADER: "); } if (!response.getHeaderNames().isEmpty()) { for (String name : response.getHeaderNames()) { for (String value : response.getHeaders(name)) { if (LOG.isDebugEnabled()) { sb.append(name + " = " + value); } if (this.length == -1 && name.equals("Content-Length")) { this.length = Long.valueOf(value); } } } } if (LOG.isDebugEnabled()) { LOG.debug(sb.toString()); } if (response.getStatus() == HttpResponseStatus.NO_CONTENT) { LOG.info("There are no data corresponding to the request"); return; } this.raf = new RandomAccessFile(file, "rw"); this.fc = raf.getChannel(); if (response.isChunked()) { readingChunks = true; } else { ChannelBuffer content = response.getContent(); if (content.readable()) { fc.write(content.toByteBuffer()); } } } else { HttpChunk chunk = (HttpChunk) e.getMessage(); if (chunk.isLast()) { readingChunks = false; long fileLength = fc.position(); fc.close(); raf.close(); if (fileLength == length) { LOG.info("Data fetch is done (total received bytes: " + fileLength + ")"); } else { LOG.info( "Data fetch is done, but cannot get all data " + "(received/total: " + fileLength + "/" + length + ")"); } } else { fc.write(chunk.getContent().toByteBuffer()); } } }
/** * Sends nested multipart response. Outer multipart wraps all the keys requested. Each key has a * separate multipart for the versioned values. */ @Override public void sendResponse(StoreStats performanceStats, boolean isFromLocalZone, long startTimeInMs) throws Exception { // multiPartKeys is the outer multipart MimeMultipart multiPartKeys = new MimeMultipart(); ByteArrayOutputStream keysOutputStream = new ByteArrayOutputStream(); for (Entry<ByteArray, List<Versioned<byte[]>>> entry : versionedResponses.entrySet()) { ByteArray key = entry.getKey(); String contentLocationKey = "/" + this.storeName + "/" + new String(Base64.encodeBase64(key.get())); // Create the individual body part - for each key requested MimeBodyPart keyBody = new MimeBodyPart(); try { // Add the right headers keyBody.addHeader(CONTENT_TYPE, "application/octet-stream"); keyBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary"); keyBody.addHeader(CONTENT_LOCATION, contentLocationKey); } catch (MessagingException me) { logger.error("Exception while constructing key body headers", me); keysOutputStream.close(); throw me; } // multiPartValues is the inner multipart MimeMultipart multiPartValues = new MimeMultipart(); for (Versioned<byte[]> versionedValue : entry.getValue()) { byte[] responseValue = versionedValue.getValue(); VectorClock vectorClock = (VectorClock) versionedValue.getVersion(); String eTag = RestUtils.getSerializedVectorClock(vectorClock); // Create the individual body part - for each versioned value of // a key MimeBodyPart valueBody = new MimeBodyPart(); try { // Add the right headers valueBody.addHeader(CONTENT_TYPE, "application/octet-stream"); valueBody.addHeader(CONTENT_TRANSFER_ENCODING, "binary"); valueBody.addHeader(RestMessageHeaders.X_VOLD_VECTOR_CLOCK, eTag); valueBody.setContent(responseValue, "application/octet-stream"); multiPartValues.addBodyPart(valueBody); } catch (MessagingException me) { logger.error("Exception while constructing value body part", me); keysOutputStream.close(); throw me; } } try { // Add the inner multipart as the content of the outer body part keyBody.setContent(multiPartValues); multiPartKeys.addBodyPart(keyBody); } catch (MessagingException me) { logger.error("Exception while constructing key body part", me); keysOutputStream.close(); throw me; } } try { multiPartKeys.writeTo(keysOutputStream); } catch (Exception e) { logger.error("Exception while writing mutipart to output stream", e); throw e; } ChannelBuffer responseContent = ChannelBuffers.dynamicBuffer(); responseContent.writeBytes(keysOutputStream.toByteArray()); // Create the Response object HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); // Set the right headers response.setHeader(CONTENT_TYPE, "multipart/binary"); response.setHeader(CONTENT_TRANSFER_ENCODING, "binary"); // Copy the data into the payload response.setContent(responseContent); response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes()); // Write the response to the Netty Channel this.messageEvent.getChannel().write(response); if (performanceStats != null && isFromLocalZone) { recordStats(performanceStats, startTimeInMs, Tracked.GET_ALL); } keysOutputStream.close(); }