sendConnect sends a raw CONNECT request to the proxy and returns the response. This is needed to test proxy authentication challenges because Go's HTTP client doesn't expose the response when CONNECT fails with a non-2xx status.
(t *testing.T, proxyAddr, targetHost, proxyAuth string)
| 444 | // This is needed to test proxy authentication challenges because Go's HTTP client |
| 445 | // doesn't expose the response when CONNECT fails with a non-2xx status. |
| 446 | func sendConnect(t *testing.T, proxyAddr, targetHost, proxyAuth string) *http.Response { |
| 447 | t.Helper() |
| 448 | |
| 449 | conn, err := net.Dial("tcp", proxyAddr) |
| 450 | require.NoError(t, err) |
| 451 | t.Cleanup(func() { _ = conn.Close() }) |
| 452 | |
| 453 | // Build CONNECT request. |
| 454 | var reqBuf bytes.Buffer |
| 455 | _, err = fmt.Fprintf(&reqBuf, "CONNECT %s HTTP/1.1\r\n", targetHost) |
| 456 | require.NoError(t, err) |
| 457 | _, err = fmt.Fprintf(&reqBuf, "Host: %s\r\n", targetHost) |
| 458 | require.NoError(t, err) |
| 459 | if proxyAuth != "" { |
| 460 | _, err = fmt.Fprintf(&reqBuf, "Proxy-Authorization: %s\r\n", proxyAuth) |
| 461 | require.NoError(t, err) |
| 462 | } |
| 463 | _, err = reqBuf.WriteString("\r\n") |
| 464 | require.NoError(t, err) |
| 465 | |
| 466 | // Send the CONNECT request to the proxy. |
| 467 | _, err = conn.Write(reqBuf.Bytes()) |
| 468 | require.NoError(t, err) |
| 469 | |
| 470 | // Read and parse the proxy's response. |
| 471 | // On success (200), the proxy establishes a tunnel. |
| 472 | // On auth failure (407), the proxy returns a challenge with Proxy-Authenticate header. |
| 473 | resp, err := http.ReadResponse(bufio.NewReader(conn), nil) |
| 474 | require.NoError(t, err) |
| 475 | |
| 476 | return resp |
| 477 | } |
| 478 | |
| 479 | func TestNew(t *testing.T) { |
| 480 | t.Parallel() |