RFR: 8368695: Support 101 switching protocol in jdk.httpserver [v10]

Daniel Fuchs dfuchs at openjdk.org
Wed Feb 18 13:18:12 UTC 2026


On Wed, 18 Feb 2026 04:11:56 GMT, Josiah Noel <duke at openjdk.org> wrote:

>> Remaking the PR since I messed up the upstream merge on the other one. See (https://github.com/openjdk/jdk/pull/27751) for the bulk of the previous discussion
>> 
>> - adds a flag to ExchangeImpl to signal whether the current request is a GET Upgrade request
>> - Adds a new `UpgradeInputStream`/`UpgradeOutputStream` to ensure that the server keeps track of when the upgraded request is closed
>> - on 101 response codes, `sendResponseHeaders` will not immediately close the output stream 
>> - on 101 response codes, `sendResponseHeaders` will use an `UpgradeInputStream`
>
> Josiah Noel has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Update UpgradeOutputStream.java

src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java line 207:

> 205:             && headers.containsKey("Upgrade")
> 206:             && values.stream().filter("Upgrade"::equalsIgnoreCase).findAny().isPresent();
> 207:     }

I believe we should also check that `Content-Length` and `Transfer-Encoding` are not present, as that would indicate a GET with a body.

src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java line 308:

> 306: 
> 307:         /* check for connection upgrade */
> 308:         if (rCode == 101) {

Shouldn't we check `upgrade` here too?

src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java line 315:

> 313:                     () -> "sendResponseHeaders: rCode = " + rCode + ": forcing contentLen = 0");
> 314:             }
> 315:             contentLen = 0;

Suggestion:

            contentLen = RSPBODY_CHUNKED;

src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java line 349:

> 347:                 } else if (upgrade && rCode == 101) {
> 348:                     o.setWrappedStream (new UpgradeOutputStream(this, ros));
> 349:                     close = true;

Suggestion:

                    // the connection should not be returned to the pool but should
                    // be closed when the upgraded exchange finishes
                    close = true;

src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java line 2:

> 1: /*
> 2:  * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.

Suggestion:

 * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.

src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java line 46:

> 44:         if (!t.upgraded) {
> 45:             return -1;
> 46:         }

This will prevent draining the input stream properly if the request is not upgraded.

src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java line 69:

> 67:           t.getServerImpl().requestCompleted(t.getConnection());
> 68:         }
> 69:     }

This is incorrect if `t.upgraded == false`. I believe there need to be more thought about what happens when an upgrade request is not upgraded.

src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java line 72:

> 70: 
> 71:     @Override
> 72:     public byte[] readAllBytes() throws IOException {

should throw if closed

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822195367
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822157777
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822160222
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822183050
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822204842
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822290905
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822276502
PR Review Comment: https://git.openjdk.org/jdk/pull/27989#discussion_r2822277740


More information about the net-dev mailing list