This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 2acee322ef8 [fix][proxy] Avoid intermittent 502 when admin proxy
follows a broker redirect for a request with a body (#25919)
2acee322ef8 is described below
commit 2acee322ef8ace78759677b997a57be454ed2eca
Author: Lari Hotari <[email protected]>
AuthorDate: Wed Jun 3 11:54:30 2026 +0300
[fix][proxy] Avoid intermittent 502 when admin proxy follows a broker
redirect for a request with a body (#25919)
---
.../pulsar/proxy/server/AdminProxyHandler.java | 31 +++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git
a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/AdminProxyHandler.java
b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/AdminProxyHandler.java
index 39db258b627..1c7953da428 100644
---
a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/AdminProxyHandler.java
+++
b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/AdminProxyHandler.java
@@ -47,6 +47,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.ProtocolHandlers;
import org.eclipse.jetty.client.RedirectProtocolHandler;
import org.eclipse.jetty.client.Request;
+import org.eclipse.jetty.client.Response;
import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
import org.eclipse.jetty.ee10.proxy.ProxyServlet;
import org.eclipse.jetty.http.HttpField;
@@ -120,7 +121,7 @@ class AdminProxyHandler extends ProxyServlet {
ProtocolHandlers protocolHandlers = httpClient.getProtocolHandlers();
if (protocolHandlers != null) {
- protocolHandlers.put(new RedirectProtocolHandler(httpClient));
+ protocolHandlers.put(new
NonAbortingRedirectProtocolHandler(httpClient));
}
httpClient.setIdleTimeout(config.getHttpProxyIdleTimeout());
@@ -128,6 +129,34 @@ class AdminProxyHandler extends ProxyServlet {
setTimeout(config.getHttpProxyTimeout());
}
+ /**
+ * A {@link RedirectProtocolHandler} that does not abort the in-flight
request when a redirect
+ * response is received.
+ *
+ * <p>Jetty's default {@link RedirectProtocolHandler#onSuccess(Response)}
aborts a request that
+ * still has a body to send when a redirect status is received, raising
+ * {@code HttpRequestException: "Aborting request after receiving a NNN
response"}. When a broker
+ * returns a 307 (to redirect an admin request to the bundle-owner broker)
before the proxy has
+ * finished streaming the request body, that abort can race ahead of the
redirect continuation in
+ * {@link RedirectProtocolHandler#onComplete} and surface to the proxy as
a spurious HTTP 502 Bad
+ * Gateway. The redirect itself is driven by {@code onComplete} from the
response (its status and
+ * {@code Location} header) and does not depend on the abort, so skipping
it lets the redirect
+ * always be followed on a fresh request (with the body replayed by
+ * {@link ReplayableProxyContentProvider}), which is the behavior this
proxy needs.
+ */
+ static class NonAbortingRedirectProtocolHandler extends
RedirectProtocolHandler {
+ NonAbortingRedirectProtocolHandler(HttpClient client) {
+ super(client);
+ }
+
+ @Override
+ public void onSuccess(Response response) {
+ // Intentionally do NOT abort the request here. The redirect is
followed in onComplete();
+ // aborting the in-flight request only races a 502 to the proxy
when the broker returns a
+ // redirect before the request body has finished sending.
+ }
+ }
+
// This class allows the request body to be replayed, the default
implementation
// does not
protected class ReplayableProxyContentProvider extends
ProxyInputStreamRequestContent {