@Override public Result exchangeTerminating(HttpExchange exchange, Result result) { if (result.isFailed()) return result; HttpResponse response = exchange.getResponse(); if ((response.getVersion() == HttpVersion.HTTP_1_1) && (response.getStatus() == HttpStatus.SWITCHING_PROTOCOLS_101)) { String connection = response.getHeaders().get(HttpHeader.CONNECTION); if ((connection == null) || !connection.toLowerCase(Locale.US).contains("upgrade")) { return new Result( result, new HttpResponseException( "101 Switching Protocols without Connection: Upgrade not supported", response)); } // Upgrade Response HttpRequest request = exchange.getRequest(); if (request instanceof HttpConnectionUpgrader) { HttpConnectionUpgrader listener = (HttpConnectionUpgrader) request; try { listener.upgrade(response, getHttpConnection()); } catch (Throwable x) { return new Result(result, x); } } } return result; }
public void setCredentials(HttpExchange exchange) throws IOException { StringBuilder buffer = new StringBuilder().append("Digest"); buffer .append(" ") .append("username") .append('=') .append('"') .append(securityRealm.getPrincipal()) .append('"'); buffer .append(", ") .append("realm") .append('=') .append('"') .append(String.valueOf(details.get("realm"))) .append('"'); buffer .append(", ") .append("nonce") .append('=') .append('"') .append(String.valueOf(details.get("nonce"))) .append('"'); buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"'); buffer .append(", ") .append("algorithm") .append('=') .append(String.valueOf(details.get("algorithm"))); String cnonce = newCnonce(exchange, securityRealm, details); buffer .append(", ") .append("response") .append('=') .append('"') .append(newResponse(cnonce, exchange, securityRealm, details)) .append('"'); buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop"))); buffer.append(", ").append("nc").append('=').append(NC); buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"'); exchange.setRequestHeader( HttpHeaders.AUTHORIZATION, new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1))); }
@Override public void exchangeTerminated(HttpExchange exchange, Result result) { super.exchangeTerminated(exchange, result); Response response = result.getResponse(); HttpFields responseHeaders = response.getHeaders(); String closeReason = null; if (result.isFailed()) closeReason = "failure"; else if (receiver.isShutdown()) closeReason = "server close"; if (closeReason == null) { if (response.getVersion().compareTo(HttpVersion.HTTP_1_1) < 0) { // HTTP 1.0 must close the connection unless it has // an explicit keep alive or it's a CONNECT method. boolean keepAlive = responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()); boolean connect = HttpMethod.CONNECT.is(exchange.getRequest().getMethod()); if (!keepAlive && !connect) closeReason = "http/1.0"; } else { // HTTP 1.1 or greater closes only if it has an explicit close. if (responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString())) closeReason = "http/1.1"; } } if (closeReason != null) { if (LOG.isDebugEnabled()) LOG.debug("Closing, reason: {} - {}", closeReason, connection); connection.close(); } else { if (response.getStatus() == HttpStatus.SWITCHING_PROTOCOLS_101) connection.remove(); else release(); } }
@Override protected void send(HttpExchange exchange) { normalizeRequest(exchange.getRequest()); // One connection maps to N channels, so for each exchange we create a new channel HttpChannel channel = new HttpChannelOverSPDY(getHttpDestination(), session); channel.associate(exchange); channel.send(); }
@Override protected void expire(HttpDestination destination) { try { super.expire(destination); } catch (IllegalStateException x) { _log.debug("On expire: ", x); onException(x); cancel(); } }
@Override public void onReply(Stream stream, ReplyInfo replyInfo) { HttpExchange exchange = getHttpExchange(); if (exchange == null) return; try { HttpResponse response = exchange.getResponse(); Fields fields = replyInfo.getHeaders(); short spdy = stream.getSession().getVersion(); HttpVersion version = HttpVersion.fromString(fields.get(HTTPSPDYHeader.VERSION.name(spdy)).getValue()); response.version(version); String[] status = fields.get(HTTPSPDYHeader.STATUS.name(spdy)).getValue().split(" ", 2); Integer code = Integer.parseInt(status[0]); response.status(code); String reason = status.length < 2 ? HttpStatus.getMessage(code) : status[1]; response.reason(reason); if (responseBegin(exchange)) { for (Fields.Field field : fields) { String name = field.getName(); if (HTTPSPDYHeader.from(spdy, name) != null) continue; // TODO: handle multiple values properly HttpField httpField = new HttpField(name, field.getValue()); responseHeader(exchange, httpField); } if (responseHeaders(exchange)) { if (replyInfo.isClose()) { responseSuccess(exchange); } } } } catch (Exception x) { responseFailure(x); } }
@Override protected void customizeExchange(HttpExchange exchange, HttpServletRequest request) { exchange.addRequestHeader("TB-Tunnel", this.app.getServerIP()); exchange.addRequestHeader( "TB-Credentials", this.app.getClientKey() + "_" + this.app.getClientSecret()); exchange.addRequestHeader("TB-Tunnel-Version", this.app.getVersion()); if (this.app.isBypassingSquid()) { exchange.addRequestHeader("TB-Tunnel-Port", "2010"); } for (String key : app.getCustomHeaders().keySet()) { exchange.addRequestHeader(key, app.getCustomHeaders().get(key)); } Logger.getLogger(ForwarderServlet.class.getName()) .log( Level.INFO, " >> [{0}] {1}", new Object[] {request.getMethod(), request.getRequestURL()}); if (app.isDebugMode()) { Enumeration<String> headerNames = request.getHeaderNames(); if (headerNames != null) { StringBuilder sb = new StringBuilder(); String header; while (headerNames.hasMoreElements()) { header = headerNames.nextElement(); sb.append(header) .append(": ") .append(request.getHeader(header)) .append(System.getProperty("line.separator")); } Logger.getLogger(ForwarderServlet.class.getName()).log(Level.INFO, sb.toString()); } } }
protected String newResponse( String cnonce, HttpExchange exchange, Realm securityRealm, Map details) { try { MessageDigest md = MessageDigest.getInstance("MD5"); // calc A1 digest md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1)); byte[] ha1 = md.digest(); // calc A2 digest md.reset(); md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1)); byte[] ha2 = md.digest(); md.update(TypeUtil.toString(ha1, 16).getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(NC.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(cnonce.getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1)); md.update((byte) ':'); md.update(TypeUtil.toString(ha2, 16).getBytes(StringUtil.__ISO_8859_1)); byte[] digest = md.digest(); // check digest return encode(digest); } catch (Exception e) { throw new RuntimeException(e); } }
@Override protected void send(HttpExchange exchange) { Request request = exchange.getRequest(); normalizeRequest(request); // Save the old idle timeout to restore it EndPoint endPoint = getEndPoint(); idleTimeout = endPoint.getIdleTimeout(); endPoint.setIdleTimeout(request.getIdleTimeout()); // One channel per connection, just delegate the send if (channel.associate(exchange)) channel.send(); else channel.release(); }
@Override protected void onRetry() throws IOException { super.onRetry(); }
@Override protected void sendHeaders(HttpExchange exchange, HttpContent content, Callback callback) { Request request = exchange.getRequest(); ContentProvider requestContent = request.getContent(); long contentLength = requestContent == null ? -1 : requestContent.getLength(); String path = request.getPath(); String query = request.getQuery(); if (query != null) path += "?" + query; HttpGenerator.RequestInfo requestInfo = new HttpGenerator.RequestInfo( request.getVersion(), request.getHeaders(), contentLength, request.getMethod(), path); try { HttpClient client = getHttpChannel().getHttpDestination().getHttpClient(); ByteBufferPool bufferPool = client.getByteBufferPool(); ByteBuffer header = bufferPool.acquire(client.getRequestBufferSize(), false); ByteBuffer chunk = null; ByteBuffer contentBuffer = null; boolean lastContent = false; if (!expects100Continue(request)) { content.advance(); contentBuffer = content.getByteBuffer(); lastContent = content.isLast(); } while (true) { HttpGenerator.Result result = generator.generateRequest(requestInfo, header, chunk, contentBuffer, lastContent); switch (result) { case NEED_CHUNK: { chunk = bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false); break; } case FLUSH: { int size = 1; boolean hasChunk = chunk != null; if (hasChunk) ++size; boolean hasContent = contentBuffer != null; if (hasContent) ++size; ByteBuffer[] toWrite = new ByteBuffer[size]; ByteBuffer[] toRecycle = new ByteBuffer[hasChunk ? 2 : 1]; toWrite[0] = header; toRecycle[0] = header; if (hasChunk) { toWrite[1] = chunk; toRecycle[1] = chunk; } if (hasContent) toWrite[toWrite.length - 1] = contentBuffer; EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint(); endPoint.write( new ByteBufferRecyclerCallback(callback, bufferPool, toRecycle), toWrite); return; } default: { throw new IllegalStateException(); } } } } catch (Exception x) { LOG.debug(x); callback.failed(x); } }
protected void setAccessToken(HttpExchange httpExchange) { httpExchange.setRequestHeader(TOKEN_HEADER, TOKEN_PREFIX + accessToken); }
/** * BASIC proxy authentication is of the form * * <p>encoded credentials are of the form: username:password */ public void setCredentials(HttpExchange exchange) throws IOException { exchange.setRequestHeader(HttpHeaders.PROXY_AUTHORIZATION_BUFFER, _authorization); }
protected boolean abort(Throwable failure) { HttpExchange exchange = channel.getHttpExchange(); return exchange != null && exchange.getRequest().abort(failure); }
@Override public void onFailure(Stream stream, Throwable x) { HttpExchange exchange = getHttpExchange(); if (exchange == null) return; exchange.getRequest().abort(x); }