/******************************************************************************* * Copyright (c) 2011 Subgraph. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subgraph - initial API and implementation ******************************************************************************/ package com.subgraph.vega.internal.http.proxy; import java.net.URI; import java.net.URISyntaxException; import org.apache.http.Header; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.protocol.HTTP; import com.subgraph.vega.http.requests.custom.HttpEntityEnclosingMutableRequest; import com.subgraph.vega.http.requests.custom.HttpMutableRequest; public class UriRequestCreator { private final static String HTTP_SCHEME = "http://"; private final static String HTTPS_SCHEME = "https://"; private final boolean preferHostHeader; public UriRequestCreator(boolean preferHostHeader) { this.preferHostHeader = preferHostHeader; } public HttpUriRequest createUriRequest(HttpRequest request, boolean isSSL) throws HttpException { final URI uri = getUriForRequest(request, isSSL); final HttpUriRequest uriRequest; if (request instanceof HttpEntityEnclosingRequest) { HttpEntityEnclosingMutableRequest tmp = new HttpEntityEnclosingMutableRequest(request.getRequestLine().getMethod(), uri); tmp.setEntity(((HttpEntityEnclosingRequest) request).getEntity()); uriRequest = tmp; } else { uriRequest = new HttpMutableRequest(request.getRequestLine().getMethod(), uri); } uriRequest.setParams(request.getParams()); uriRequest.setHeaders(request.getAllHeaders()); return uriRequest; } public URI getUriForRequest(HttpRequest request, boolean isSSL) throws HttpException { final String scheme = (isSSL) ? HTTPS_SCHEME : HTTP_SCHEME; final String hostname = getHostname(request); final String pathAndQuery = extractPathAndQuery(request.getRequestLine().getUri()); if(hostname == null) { throw new HttpException("Cannot create URI from request because no hostname is specified in either Host header or HTTP request line"); } try { return new URI(scheme + hostname + pathAndQuery); } catch (URISyntaxException e) { throw new HttpException("Cannot create URI from request because URI format is incorrect.", e); } } private String getHostname(HttpRequest request) { final String headerHostname = requestHostHeaderValue(request); final String pathHostname = maybeExtractHostname(request.getRequestLine().getUri()); if(headerHostname != null && pathHostname != null) { return (preferHostHeader) ? (headerHostname) : (pathHostname); } return (headerHostname != null) ? (headerHostname) : (pathHostname); } private String requestHostHeaderValue(HttpRequest request) { final Header hostHeader = request.getFirstHeader(HTTP.TARGET_HOST); if(hostHeader == null) { return null; } final String hostValue = hostHeader.getValue(); return (hostValue == null || hostValue.isEmpty()) ? (null) : (hostValue); } private String maybeExtractHostname(String requestUri) { final int hostnameIndex = indexOfHostname(requestUri); if(hostnameIndex == -1) return null; final int pathIndex = indexOfPath(requestUri); return requestUri.substring(hostnameIndex, pathIndex); } private int indexOfHostname(String requestUri) { if(requestUri.startsWith(HTTP_SCHEME)) { return HTTP_SCHEME.length(); } else if (requestUri.startsWith(HTTPS_SCHEME)) { return HTTPS_SCHEME.length(); } else { return -1; } } private String extractPathAndQuery(String requestUri) { final int hostnameIndex = indexOfHostname(requestUri); if(hostnameIndex == -1) { return maybeCreateRootPath(requestUri); } final int pathIndex = indexOfPath(requestUri); return maybeCreateRootPath( requestUri.substring(pathIndex) ); } private String maybeCreateRootPath(String path) { return (path.isEmpty()) ? ("/") : (path); } /* * * Returns 0 if not an absolute URI, otherwise searches for the first '/' character * after the hostname and if not found returns the length of the String. * * If result is 0 then the whole string is the path otherwise, the path can * be extracted with requestUri.substring(pathIndex) and the hostname can * be extracted with requestUri.substring(hostnameIndex, pathIndex) * */ private int indexOfPath(String requestUri) { final int hostnameIndex = indexOfHostname(requestUri); if(hostnameIndex == -1) return 0; final int idx = requestUri.indexOf("/", hostnameIndex); return (idx == -1) ? (requestUri.length()) : (idx); } }