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
15 changes: 14 additions & 1 deletion src/main/java/com/testingbot/tunnel/proxy/HttpLogHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private void log(Request request, Response response, String requestId, long star
boolean failed = failure != null || status >= 500;
// BODY is refused for this module, so it can only arrive here by mistake; treat it as
// HEADERS rather than silently logging nothing.
if (mode == Mode.ERRORS && !failed) {
if (mode == Mode.ERRORS && (!failed || isSquidInternal(request))) {
return;
}

Expand All @@ -149,6 +149,19 @@ private void log(Request request, Response response, String requestId, long star
LOG.log(failed ? Level.WARNING : Level.INFO, line.toString());
}

/**
* Squid's own requests through the tunnel, which fail by design. Web warms up every new
* tunnel with {@code GET http://127.0.0.1:1/squid-internal-tunnel-warmup} through both of
* Squid's ports, to absorb the cold-start 502 before a customer's first request does. Port 1
* is refused, so each answers 502 here, and printed a WARNING with headers on every start
* that read as a failed tunnel. Only the default {@code errors} mode drops them: {@code url}
* and {@code headers} asked for every request.
*/
private static boolean isSquidInternal(Request request) {
String path = request.getHttpURI().getPath();
return path != null && path.startsWith("/squid-internal");
}

/** CONNECT carries an authority rather than a URL; log whichever the request actually has. */
private static String target(Request request) {
String authority = request.getHttpURI().getAuthority();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,13 @@ private String proxyGetEchoing(String extraHeaders) throws Exception {
}

private void proxyGet(String extraHeaders) throws Exception {
proxyGet("/page", extraHeaders);
}

private void proxyGet(String path, String extraHeaders) throws Exception {
try (Socket socket = new Socket("127.0.0.1", proxyPort)) {
socket.setSoTimeout(10_000);
String request = "GET http://127.0.0.1:" + originPort + "/page HTTP/1.1\r\n"
String request = "GET http://127.0.0.1:" + originPort + path + " HTTP/1.1\r\n"
+ "Host: 127.0.0.1:" + originPort + "\r\n"
+ extraHeaders
+ "Connection: close\r\n\r\n";
Expand Down Expand Up @@ -295,6 +299,32 @@ void errors_logsWithHeadersOnServerError() throws Exception {
assertThat(logged).contains("X-Custom: visible");
}

@Test
void errors_staysQuietForSquidsWarmupRequest() throws Exception {
// Web sends this through every new tunnel and it fails by design; logged, it printed
// two WARNINGs on every start that read as a broken tunnel.
startOrigin(502);
startProxy("errors", null);

proxyGet("/squid-internal-tunnel-warmup", "");

// A deliberate wait, not a guess at readiness: this asserts a record never appears,
// so there is nothing to poll for and the only way to be wrong is to look too early.
Thread.sleep(200);
assertThat(captured.count()).isZero();
}

@Test
void url_stillLogsSquidsWarmupRequest() throws Exception {
// url asked for every request, so it is not this handler's place to leave one out.
startOrigin(502);
startProxy("url", null);

proxyGet("/squid-internal-tunnel-warmup", "");

assertThat(awaitLogged()).contains("/squid-internal-tunnel-warmup").contains("502");
}

@Test
void reusesAnIncomingCorrelationId() throws Exception {
// A trace that starts in the test framework should stay joined up through the tunnel.
Expand Down
Loading