package com.grendelscan.commons.http.wrappers;
import java.io.IOException;
import java.net.URISyntaxException;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.params.HttpProtocolParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.grendelscan.commons.http.HttpConstants;
import com.grendelscan.commons.http.apache_overrides.requests.GenericRequestWithBody;
import com.grendelscan.commons.http.URIStringUtils;
// Need to take a closer look at synchronization here
public class HttpRequestWrapper extends HttpMessageWrapper
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequestWrapper.class);
private static final long serialVersionUID = -4950627342682724871L;
private String method;
private String uri;
private boolean secure;
private ProtocolVersion version;
public transient static final ProtocolVersion DEFAULT_PROTOCL_VERSION = new ProtocolVersion("HTTP", 1, 1);
private String networkHost;
private int networkPort;
public HttpRequestWrapper(int transactionId)
{
super(transactionId);
method = "GET";
version = DEFAULT_PROTOCL_VERSION;
}
@Override
public String toString()
{
return new String(getBytes());
}
@Override public byte[] getBytes()
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
out.write(method.getBytes());
out.write(' ');
out.write(uri.getBytes());
out.write(' ');
out.write(version.toString().getBytes());
out.write(HttpConstants.CRLF_BYTES);
out.write(super.getBytes());
}
catch (IOException e)
{
LOGGER.error("Weird problem getting bytes from request wrapper: " + e.toString(), e);
}
return out.toByteArray();
}
public void setVersion(String protocol, int major, int minor)
{
version = new ProtocolVersion(protocol, major, minor);
}
public void setVersion(ProtocolVersion version)
{
this.version = version;
}
public void copyNetworkTarget(HttpRequestWrapper source)
{
networkHost = source.networkHost;
networkPort = source.networkPort;
secure = source.secure;
}
public String getAbsoluteUriString()
{
try
{
if (!URIStringUtils.getScheme(uri).isEmpty())
{
return uri;
}
}
catch (URISyntaxException e)
{
IllegalStateException ise = new IllegalStateException("Really, really weird problem with uri parsing", e);
LOGGER.error(e.toString(), e);
throw ise;
}
String absolute = secure ? "https://" : "http://";
absolute += getHost();
if (networkPort > 0 && ((secure && networkPort != 443) ||
(!secure && networkPort != 80)))
{
absolute += ":" + networkPort;
}
absolute += uri;
return absolute;
}
public String getMethod()
{
return method;
}
public HttpRequest getRequest()
{
HttpRequestBase request = null;
request = new GenericRequestWithBody(method, uri, this);
ProtocolVersion versionToUse = version;
if (versionToUse == null)
{
versionToUse = HttpRequestWrapper.DEFAULT_PROTOCL_VERSION;
}
HttpProtocolParams.setVersion(request.getParams(), versionToUse);
if (headers != null)
{
request.setHeaders(headers.getReadOnlyHeaderArray());
}
return request;
}
public HttpHost getHttpHost()
{
String hostToUse = networkHost;
int portToUse = networkPort;
if (networkHost == null || networkHost.isEmpty())
{
hostToUse = getHost();
}
if (networkPort == 0)
{
try
{
portToUse = URIStringUtils.getPort(getAbsoluteUriString());
}
catch (URISyntaxException e)
{
LOGGER.error("Very weird problem getting port number from URL", e);
}
}
return new HttpHost(hostToUse, portToUse, secure ? "HTTPS" : "HTTP");
}
/**
* Checks for an absolute URL, then returns the FIRST host header value
* @return
*/
public String getHost()
{
String host = null;
Header header = getHeaders().getFirstHeader("Host");
if (header != null)
{
host = header.getValue();
}
if (host == null || host.isEmpty())
{
try
{
host = URIStringUtils.getHost(uri);
}
catch (URISyntaxException e)
{
LOGGER.trace("No host defined. Unusual, but could be true");
}
}
return host;
}
public String getQuery()
{
try
{
return URIStringUtils.getQuery(uri);
}
catch (URISyntaxException e)
{
IllegalStateException ise = new IllegalStateException("Really, really weird problem with uri parsing", e);
LOGGER.error(e.toString(), e);
throw ise;
}
}
public String getPath()
{
try
{
return URIStringUtils.getDirectory(uri);
}
catch (URISyntaxException e)
{
IllegalStateException ise = new IllegalStateException("Really, really weird problem with uri parsing", e);
LOGGER.error(e.toString(), e);
throw ise;
}
}
public String getURI()
{
return uri;
}
// /**
// *
// * @return same as getHost() + ":" + getNetworkPort();
// */
// public String getHostAndPort()
// {
// return getHost() + ":" + getNetworkPort();
// }
public HttpRequestWrapper clone(int transactionId)
{
HttpRequestWrapper clone = new HttpRequestWrapper(transactionId);
super.clone(clone);
clone.method = new String(method);
clone.uri = new String(uri);
clone.version = version; // ProtocolVersion is immutable, so we can reuse the object
clone.networkHost = new String(networkHost);
clone.networkPort = networkPort;
clone.secure = secure;
return clone;
}
// public void setRequest(HttpRequest request)
// {
// if (!((request instanceof HttpTrace) || (request instanceof HttpOptions) ||
// (request instanceof HttpHead) || (request instanceof HttpGet) ||
// (request instanceof HttpPut) || (request instanceof HttpPost)))
// {
// RuntimeException e = new RuntimeException("Unknown HttpRequest type");
// throw e;
// }
// String host = request.getFirstHeader(HttpHeaders.HOST).getValue();
// setHeaders(new HttpHeadersWrapper());
// getHeaders().addHeaders(request.getAllHeaders());
// uri = request.getRequestLine().getUri();
// method = request.getRequestLine().getMethod();
// version = request.getProtocolVersion();
// }
//
/**
* NOTE: This will override the network host value if adjustToRelativeURI is true
* @param uri
* @param adjustToRelativeURI
* @throws URISyntaxException
*/
public void setURI(final String uri, boolean adjustToRelativeURI)
{
if (adjustToRelativeURI)
{
String hostValue;
try
{
String tmpHost = URIStringUtils.getHost(uri);
if (!tmpHost.isEmpty())
{
hostValue = tmpHost;
getHeaders().removeHeaders(HttpHeaders.HOST);
getHeaders().addHeader(HttpHeaders.HOST, hostValue);
this.networkHost = hostValue;
}
this.uri = URIStringUtils.escapeUri(URIStringUtils.getRelativeUri(uri));
String tmpScheme = URIStringUtils.getScheme(uri);
if (!tmpScheme.isEmpty())
{
secure = tmpScheme.equalsIgnoreCase("https");
}
int tmpPort = URIStringUtils.getPort(uri);
if (tmpPort > 0)
{
this.networkPort = tmpPort;
}
}
catch (URISyntaxException e)
{
LOGGER.error("Illegal URL syntax: " + e.toString(), e);
throw new IllegalArgumentException(e);
}
}
else
{
this.uri = URIStringUtils.escapeUri(uri);
}
}
public final boolean isSecure()
{
return secure;
}
public final void setSecure(boolean secure)
{
this.secure = secure;
}
public final void setMethod(String method)
{
this.method = method;
}
public final String getNetworkHost()
{
return networkHost;
}
public final void setNetworkHost(String networkHost)
{
this.networkHost = networkHost;
}
public final int getNetworkPort()
{
return networkPort;
}
public final void setNetworkPort(int networkPort)
{
this.networkPort = networkPort;
}
public final ProtocolVersion getVersion()
{
return version;
}
}