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; }
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); }
@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); }
public NettyRequest newNettyRequest( Request request, boolean forceConnect, ProxyServer proxyServer) throws IOException { Uri uri = request.getUri(); HttpMethod method = forceConnect ? HttpMethod.CONNECT : HttpMethod.valueOf(request.getMethod()); boolean connect = method == HttpMethod.CONNECT; boolean allowConnectionPooling = config.isAllowPoolingConnections() && (!HttpUtils.isSecure(uri) || config.isAllowPoolingSslConnections()); HttpVersion httpVersion = !allowConnectionPooling || (connect && proxyServer.isForceHttp10()) ? HttpVersion.HTTP_1_0 : HttpVersion.HTTP_1_1; String requestUri = requestUri(uri, proxyServer, connect); NettyBody body = body(request, connect); HttpRequest httpRequest; NettyRequest nettyRequest; if (body instanceof NettyDirectBody) { ChannelBuffer buffer = NettyDirectBody.class.cast(body).channelBuffer(); httpRequest = new DefaultHttpRequest(httpVersion, method, requestUri); // body is passed as null as it's written directly with the request httpRequest.setContent(buffer); nettyRequest = new NettyRequest(httpRequest, null); } else { httpRequest = new DefaultHttpRequest(httpVersion, method, requestUri); nettyRequest = new NettyRequest(httpRequest, body); } HttpHeaders headers = httpRequest.headers(); if (!connect) { // assign headers as configured on request for (Entry<String, List<String>> header : request.getHeaders()) { headers.set(header.getKey(), header.getValue()); } if (isNonEmpty(request.getCookies())) headers.set(COOKIE, CookieEncoder.encode(request.getCookies())); if (config.isCompressionEnforced() && !headers.contains(ACCEPT_ENCODING)) headers.set(ACCEPT_ENCODING, GZIP_DEFLATE); } if (body != null) { if (body.getContentLength() < 0) headers.set(TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED); else headers.set(CONTENT_LENGTH, body.getContentLength()); if (body.getContentType() != null) headers.set(CONTENT_TYPE, body.getContentType()); } // connection header and friends boolean webSocket = isWebSocket(uri.getScheme()); if (!connect && webSocket) { String origin = "http://" + uri.getHost() + ":" + (uri.getPort() == -1 ? isSecure(uri.getScheme()) ? 443 : 80 : uri.getPort()); headers .set(UPGRADE, HttpHeaders.Values.WEBSOCKET) // .set(CONNECTION, HttpHeaders.Values.UPGRADE) // .set(ORIGIN, origin) // .set(SEC_WEBSOCKET_KEY, getKey()) // .set(SEC_WEBSOCKET_VERSION, "13"); } else if (!headers.contains(CONNECTION)) { String connectionHeaderValue = connectionHeader(allowConnectionPooling, httpVersion == HttpVersion.HTTP_1_1); if (connectionHeaderValue != null) headers.set(CONNECTION, connectionHeaderValue); } if (!headers.contains(HOST)) headers.set(HOST, hostHeader(request, uri)); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); // don't override authorization but append addAuthorizationHeader(headers, systematicAuthorizationHeader(request, realm)); setProxyAuthorizationHeader( headers, systematicProxyAuthorizationHeader(request, proxyServer, realm, connect)); // Add default accept headers if (!headers.contains(ACCEPT)) headers.set(ACCEPT, "*/*"); // Add default user agent if (!headers.contains(USER_AGENT) && config.getUserAgent() != null) headers.set(USER_AGENT, config.getUserAgent()); return nettyRequest; }