@Override public void handle(Channel channel, NettyResponseFuture<?> future, Object e) throws Exception { if (e instanceof HttpResponse) { HttpResponse response = (HttpResponse) e; Channels.setAttribute(channel, new UpgradeCallback(future, channel, response)); } else if (e instanceof WebSocketFrame) { final WebSocketFrame frame = (WebSocketFrame) e; WebSocketUpgradeHandler handler = WebSocketUpgradeHandler.class.cast(future.getAsyncHandler()); NettyWebSocket webSocket = NettyWebSocket.class.cast(handler.onCompleted()); invokeOnSucces(channel, handler); if (webSocket != null) { if (frame instanceof CloseWebSocketFrame) { Channels.setDiscard(channel); CloseWebSocketFrame closeFrame = CloseWebSocketFrame.class.cast(frame); webSocket.onClose(closeFrame.statusCode(), closeFrame.reasonText()); } else { ByteBuf buf = frame.content(); if (buf != null && buf.readableBytes() > 0) { try { NettyResponseBodyPart part = nettyConfig .getBodyPartFactory() .newResponseBodyPart(buf, frame.isFinalFragment()); handler.onBodyPartReceived(part); if (frame instanceof BinaryWebSocketFrame) { webSocket.onBinaryFragment(part); } else if (frame instanceof TextWebSocketFrame) { webSocket.onTextFragment(part); } else if (frame instanceof PingWebSocketFrame) { webSocket.onPing(part); } else if (frame instanceof PongWebSocketFrame) { webSocket.onPong(part); } } finally { buf.release(); } } } } else { logger.debug("UpgradeHandler returned a null NettyWebSocket "); } } else { logger.error("Invalid message {}", e); } }
private boolean exitAfterHandling100( final Channel channel, final NettyResponseFuture<?> future, int statusCode) { future.setHeadersAlreadyWrittenOnContinue(true); future.setDontWriteBodyBecauseExpectContinue(false); // directly send the body Channels.setAttribute( channel, new Callback(future) { @Override public void call() throws IOException { Channels.setAttribute(channel, future); requestSender.writeRequest(future, channel); } }); return true; }
private boolean exitAfterHandlingReactiveStreams( Channel channel, NettyResponseFuture<?> future, HttpResponse response, AsyncHandler<?> handler, HttpRequest httpRequest) throws IOException { if (handler instanceof StreamedAsyncHandler) { StreamedAsyncHandler<?> streamedAsyncHandler = (StreamedAsyncHandler<?>) handler; StreamedResponsePublisher publisher = new StreamedResponsePublisher(channel.eventLoop(), channelManager, future, channel); // FIXME do we really need to pass the event loop? // FIXME move this to ChannelManager channel.pipeline().addLast(channel.eventLoop(), "streamedAsyncHandler", publisher); Channels.setAttribute(channel, publisher); return streamedAsyncHandler.onStream(publisher) != State.CONTINUE; } return false; }
@Override public void call() throws Exception { WebSocketUpgradeHandler handler = WebSocketUpgradeHandler.class.cast(future.getAsyncHandler()); Request request = future.getRequest(); HttpResponseStatus status = new NettyResponseStatus(future.getUri(), config, response, channel); HttpResponseHeaders responseHeaders = new NettyResponseHeaders(response.headers()); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); if (exitAfterProcessingFilters(channel, future, handler, status, responseHeaders)) { return; } future.setHttpHeaders(response.headers()); if (exitAfterHandlingRedirect( channel, future, response, request, response.getStatus().code(), realm)) return; boolean validStatus = response.getStatus().equals(SWITCHING_PROTOCOLS); boolean validUpgrade = response.headers().get(HttpHeaders.Names.UPGRADE) != null; String connection = response.headers().get(HttpHeaders.Names.CONNECTION); if (connection == null) connection = response.headers().get(HttpHeaders.Names.CONNECTION.toLowerCase(Locale.ENGLISH)); boolean validConnection = HttpHeaders.Values.UPGRADE.equalsIgnoreCase(connection); boolean statusReceived = handler.onStatusReceived(status) == State.UPGRADE; if (!statusReceived) { try { handler.onCompleted(); } finally { future.done(); } return; } final boolean headerOK = handler.onHeadersReceived(responseHeaders) == State.CONTINUE; if (!headerOK || !validStatus || !validUpgrade || !validConnection) { requestSender.abort(channel, future, new IOException("Invalid handshake response")); return; } String accept = response.headers().get(HttpHeaders.Names.SEC_WEBSOCKET_ACCEPT); String key = getAcceptKey( future .getNettyRequest() .getHttpRequest() .headers() .get(HttpHeaders.Names.SEC_WEBSOCKET_KEY)); if (accept == null || !accept.equals(key)) { requestSender.abort( channel, future, new IOException( String.format("Invalid challenge. Actual: %s. Expected: %s", accept, key))); } channelManager.upgradePipelineForWebSockets(channel.pipeline()); invokeOnSucces(channel, handler); future.done(); // set back the future so the protocol gets notified of frames Channels.setAttribute(channel, future); }