jetty.project icon indicating copy to clipboard operation
jetty.project copied to clipboard

Read response body on failed WebSocket upgrade attempt

Open jacob-pro opened this issue 5 months ago • 3 comments
trafficstars

Jetty Version

12.0.19

Jetty Environment

ee10

Java Version

21

Question

When making a WebSocket connection I am able to catch the UpgradeException with message Failed to upgrade to websocket: Unexpected HTTP Response Status Code.

In this case I can see the response status code and response headers by capturing the handshake response.

try {
    AtomicReference<Response> responseRef = new AtomicReference<>();
    client.connect(backendListener, uri, clientUpgrade, new JettyUpgradeListener() {
        @Override
        public void onHandshakeResponse(Request request, Response response) {
            log.debug("Received HTTP {} response from WebSocket backend", response);
            responseRef.set(response);
        }
    }).get();
} catch (UpgradeException e) {
    if (e.getCause().getMessage().startsWith("Failed to upgrade to websocket: Unexpected HTTP Response Status Code")) {
        Response response = responseRef.get();
        log.info("Status: {}", response.getStatus());
        log.info("Headers: {}", response.getHeaders());
        // InputStream responseBody = response.getBody() ??
    }
}

Is there any way to read the response body stream from the handshake as well? As far as I can tell the Response does not have any methods that support reading?

Use-Case

When connecting to a WebSocket endpoint, the server may reject the upgrade request with a HTTP 4XX or 5XX error. For example the request headers could be invalid. When this happens I would like to be able to read the response body to learn more about the error cause.

As per the WebSocket spec

If the status code received from the server is not 101, the
       client handles the response per HTTP [[RFC2616](https://datatracker.ietf.org/doc/html/rfc2616)] procedures.  In
       particular, the client might perform authentication if it
       receives a 401 status code; the server might redirect the client
       using a 3xx status code (but clients are not required to follow
       them), etc.  Otherwise, proceed as follows.

jacob-pro avatar Jun 09 '25 15:06 jacob-pro

Currently, the response body is discarded, so there is no way to retrieve it. Also, browsers don't expose failed WebSocket upgrades (just an error).

This is the first time we got this specific request.

Can you control the body generation on the server?

sbordet avatar Jun 09 '25 15:06 sbordet

Since this is a WebSocket Client the HTTP response body isn't relevant anyway.

If this was an HTTP Client that could also do WebSocket then the HTTP response body would have relevance to the HTTP Client.

joakime avatar Jun 09 '25 15:06 joakime

@joakime it is the HTTP response of the HTTP request for the WebSocket upgrade.

JettyUpgradeListener's Request and Response parameters are those of jetty-client.

So it can be done, just we do not currently do it since typically the headers are enough.

sbordet avatar Jun 09 '25 16:06 sbordet