Skip to content

Commit b13eed3

Browse files
author
ilyasse benrkia
committed
fix: bypass proxy for Runtime API HTTP calls
Use Proxy.NO_PROXY when opening HttpURLConnection to RAPID endpoints. This prevents customer-configured http.proxyHost from routing internal Runtime API calls through the proxy, which fails when RAPID is not on a loopback address (localhost is implicitly exempt in most proxy implementations). The hot path (nextInvocation/postInvocationResponse) already bypasses Java's ProxySelector via the native C++/libcurl NativeClient and is not affected. Proxy.NO_PROXY is per-connection scoped, zero impact on customer handler HTTP calls.
1 parent 1f8f306 commit b13eed3

2 files changed

Lines changed: 61 additions & 4 deletions

File tree

aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.OutputStream;
1515
import java.net.HttpURLConnection;
1616
import java.net.MalformedURLException;
17+
import java.net.Proxy;
1718
import java.net.URL;
1819
import java.util.HashMap;
1920
import java.util.Map;
@@ -175,8 +176,7 @@ void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize
175176
private int doPost(String endpoint,
176177
Map<String, String> headers,
177178
byte[] payload) throws IOException {
178-
URL url = createUrl(endpoint);
179-
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
179+
HttpURLConnection conn = createConnection(endpoint);
180180
conn.setRequestMethod("POST");
181181
conn.setRequestProperty("Content-Type", DEFAULT_CONTENT_TYPE);
182182
conn.setRequestProperty("User-Agent", USER_AGENT);
@@ -201,8 +201,7 @@ private int doPost(String endpoint,
201201
}
202202

203203
private int doGet(String endpoint) throws IOException {
204-
URL url = createUrl(endpoint);
205-
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
204+
HttpURLConnection conn = createConnection(endpoint);
206205
conn.setRequestMethod("GET");
207206
conn.setRequestProperty("User-Agent", USER_AGENT);
208207

@@ -212,6 +211,15 @@ private int doGet(String endpoint) throws IOException {
212211
return responseCode;
213212
}
214213

214+
/**
215+
* Opens a direct connection to the given endpoint, bypassing any
216+
* customer-configured proxy.
217+
*/
218+
private HttpURLConnection createConnection(String endpoint) throws IOException {
219+
URL url = createUrl(endpoint);
220+
return (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
221+
}
222+
215223
private URL createUrl(String endpoint) {
216224
try {
217225
return new URL(endpoint);

aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.util.ArrayList;
2626
import java.util.List;
27+
import java.net.InetAddress;
2728
import java.util.function.Function;
2829
import java.util.function.Supplier;
2930

@@ -533,6 +534,54 @@ public void reportInvocationErrorWithInvocationIdTest() {
533534
}
534535
}
535536

537+
@Test
538+
public void connectionBypassesConfiguredProxy() throws Exception {
539+
// Bind RAPID mock to a non-loopback IP so Java's ProxySelector doesn't
540+
// auto-exempt it. On loopback (127.0.0.1), the JVM skips proxy regardless.
541+
MockWebServer nonLoopbackServer = new MockWebServer();
542+
InetAddress nonLoopback = InetAddress.getLocalHost();
543+
nonLoopbackServer.start(nonLoopback, 0);
544+
545+
MockWebServer fakeProxy = new MockWebServer();
546+
fakeProxy.start();
547+
// Enqueue a response so if proxy is used, the test fails fast instead of hanging indefinitely.
548+
fakeProxy.enqueue(new MockResponse().setResponseCode(HTTP_ACCEPTED));
549+
550+
String previousProxyHost = System.getProperty("http.proxyHost");
551+
String previousProxyPort = System.getProperty("http.proxyPort");
552+
553+
System.setProperty("http.proxyHost", fakeProxy.getHostName());
554+
System.setProperty("http.proxyPort", String.valueOf(fakeProxy.getPort()));
555+
556+
try {
557+
MockResponse mockResponse = new MockResponse();
558+
mockResponse.setResponseCode(HTTP_ACCEPTED);
559+
nonLoopbackServer.enqueue(mockResponse);
560+
561+
String endpoint = "http://" + nonLoopback.getHostAddress() + ":" + nonLoopbackServer.getPort();
562+
LambdaError lambdaError = new LambdaError(errorRequest, RapidErrorType.AfterRestoreError);
563+
lambdaRuntimeApiClientImpl.reportLambdaError(endpoint, lambdaError, 1024 * 1024, null);
564+
565+
// Request arrived at RAPID mock directly
566+
assertEquals(1, nonLoopbackServer.getRequestCount());
567+
// Nothing went to the fake proxy
568+
assertEquals(0, fakeProxy.getRequestCount());
569+
} finally {
570+
if (previousProxyHost != null) {
571+
System.setProperty("http.proxyHost", previousProxyHost);
572+
} else {
573+
System.clearProperty("http.proxyHost");
574+
}
575+
if (previousProxyPort != null) {
576+
System.setProperty("http.proxyPort", previousProxyPort);
577+
} else {
578+
System.clearProperty("http.proxyPort");
579+
}
580+
nonLoopbackServer.shutdown();
581+
fakeProxy.shutdown();
582+
}
583+
}
584+
536585
private String getHostnamePort() {
537586
return mockWebServer.getHostName() + ":" + mockWebServer.getPort();
538587
}

0 commit comments

Comments
 (0)