Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.net.HostAndPort;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;

import java.net.URI;
Expand Down Expand Up @@ -32,12 +33,7 @@ public static String getHostFromRequest(HttpRequest httpRequest) {
}
}

// if there was no host in the URI, attempt to grab the host from the Host header
if (host == null || host.isEmpty()) {
host = parseHostHeader(httpRequest, false);
}

return host;
return parseHost(host, httpRequest, false);
}

/**
Expand All @@ -48,15 +44,16 @@ public static String getHostFromRequest(HttpRequest httpRequest) {
* @return host and port of the request
*/
public static String getHostAndPortFromRequest(HttpRequest httpRequest) {
String host = null;
if (startsWithHttpOrHttps(httpRequest.uri())) {
try {
return getHostAndPortFromUri(httpRequest.uri());
host = getHostAndPortFromUri(httpRequest.uri());
} catch (URISyntaxException e) {
// the URI could not be parsed, so return the host and port in the Host header
}
}

return parseHostHeader(httpRequest, true);
return parseHost(host, httpRequest, true);
}

/**
Expand Down Expand Up @@ -97,6 +94,20 @@ public static String getHostAndPortFromUri(String uriString) throws URISyntaxExc
}
}

private static String parseHost(String host, HttpRequest httpRequest, boolean includePort) {
// if there was no host in the URI, attempt to grab the host from the Host header
if (isEmpty(host)) {
host = parseHostHeader(httpRequest, includePort);
}

// if there was not a Host header, and the method is CONNECT, use that as the host
if (isEmpty(host)) {
host = hostFromConnect(httpRequest, includePort);
}

return host;
}

/**
* Retrieves the host and, optionally, the port from the specified request's Host header.
*
Expand All @@ -120,4 +131,26 @@ private static String parseHostHeader(HttpRequest httpRequest, boolean includePo
return null;
}
}

/**
* Retrieves the host and, optionally, the port from the specified request's URI if the method is CONNECT.
*
* @param httpRequest HTTP request
* @param includePort when true, include the port
* @return the host and, optionally, the port specified in the request's URI
*/
private static String hostFromConnect(HttpRequest httpRequest, boolean includePort) {
if (HttpMethod.CONNECT.equals(httpRequest.method())) {
if (includePort) {
return httpRequest.uri();
}
HostAndPort parsedHostAndPort = HostAndPort.fromString(httpRequest.uri());
return parsedHostAndPort.getHost();
}
return null;
}

private static boolean isEmpty(String str) {
return str == null || str.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import io.netty.handler.codec.http.HttpResponse;
import com.browserup.bup.mitm.manager.ImpersonatingMitmManager;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
Expand Down Expand Up @@ -37,6 +39,16 @@
public class LittleProxyIntegrationTest {
@Test
public void testLittleProxyMitm() throws IOException, InterruptedException {
testLittleProxyMitm(null);
}

@Test
public void testLittleProxyMitmHttp1_0() throws IOException, InterruptedException {
testLittleProxyMitm(HttpVersion.HTTP_1_0);
}

private void testLittleProxyMitm(ProtocolVersion protocolVersion) throws IOException, InterruptedException
{
final AtomicBoolean interceptedGetRequest = new AtomicBoolean();
final AtomicBoolean interceptedGetResponse = new AtomicBoolean();

Expand Down Expand Up @@ -79,7 +91,9 @@ public HttpObject serverToProxyResponse(HttpObject httpObject) {
.start();

try (CloseableHttpClient httpClient = getNewHttpClient(proxyServer.getListenAddress().getPort())) {
try (CloseableHttpResponse response = httpClient.execute(new HttpGet("https://www.google.com"))) {
HttpGet httpGet = new HttpGet("https://www.google.com");
httpGet.setProtocolVersion(protocolVersion);
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
assertEquals("Expected to receive an HTTP 200 from http://www.google.com", 200, response.getStatusLine().getStatusCode());

EntityUtils.consume(response.getEntity());
Expand Down