- Notifications
You must be signed in to change notification settings - Fork 6.1k
8368695: Support 101 switching protocol in jdk.httpserver #27751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back SentryMan! A progress list of the required criteria for merging this PR into |
❗ This change is not yet ready to be integrated. |
@SentryMan The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
cc9740e
to c44eee2
Compare @SentryMan Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. See OpenJDK Developers’ Guide for more information. |
Webrevs
|
Is the intention behind this to support websocket? |
To speak plainly, my plan is not for adding official websocket support into the JDK. That part I can do on my own, the only thing I lack is access to the input/output streams after sending a 101 code. (the current logic in send headers closes both after sending 101 headers) |
Don't get me wrong though, if you guys decide you want to fully support websocket, I'll gladly offer a PR. (But I highly doubt such a thing will happen) |
Right, I don't think we want to support websocket. There are plenty of third party implementations out there and it's a bit too far removed from the purpose as a lightweight server, for serving mainly static content. However, if we were to allow this enabling functionality, it would have to be documented and specified, so that other people could use it. I'd have preferred if the general shape of such an "upgrade API" was discussed on the net-dev email list but we can discuss it here, without prejudice to whether it goes ahead or not. As a minimum, the feature would have to be "opt in" by the handler, probably through a new method on HttpExchange and we have to consider the impact on the rest of the API, such as what happens when HttpServer.stop is called. |
For me, it was already implied that 101 status could be sent, because the documentation for
For http2 I'm in agreement for a new method, as supporting that kind of upgrade is has far more complexity and requires consuming the body before upgrading. For WebSocket though, such a thing can be accomplished cleanly through the current API. Indeed, in some other implementations of
Requiring a manual call of
Testing locally, calling stop appears to work the same as an extended GET request. What kind of test assertions would you like to see? |
In fact, this might be a good way of thinking about it. When you call server.createContext( "/test", exchange -> { exchange.sendResponseHeaders(200, 0); exchange.getResponseBody().write("My Response".getBytes()); try (var is = exchange.getRequestBody()) { is.transferTo(exchange.getResponseBody()); } }); |
Right. But your PR changes the request body input stream preemptively, before |
That is true, but it's only for GET requests. Thus it effectively remains optional as regular GET request handlers wouldn't attempt to read the body. |
So your proposal is that we support switching protocols only for GET requests, and only for those that have no Content-length header in the request header? |
Essentially yes, because that's all that's needed to support implementing the websocket protocol. |
But that would be an incompatible change, isn't it? Consider the following:
wouldn't that now block forever if the request contains an upgrade header? |
That we even return an inputstream for a GET request is pretty strange but yeah that would indeed block forever. I'll fix to keep compatibility. |
Before going any further in the review I would like to see how this new feature would be documented. If we eventually decide to take it on board, then more extensive tests will be needed too. |
My thought was to add an implnote to
For sendResponseHeaders, it's currently already implied that you can send 101. So I would add an implnote clarifying the behavior. Something like:
Naturally, tell me what other cases you'd like and it shall be done |
Here is a proposal for discussion. This would be added to the end of the class level docs for HttpExchange
The apidoc for HttpServer.stop would need to mention that sockets detached from the upgrade mechanism are also closed. |
Thanks @Michael-Mc-Mahon for driving this discussion. Would this text be normative - that it - would any implementation plugged through the SPI need to support this? If not we should find some way to tie that to the JDK built-in implementation. I know that the HttpServer API itself is not part of the Java SE spec - but maybe we should set some expectations of what an implementation plugged through the SPI must, should, or might do. |
Isn't the behavior the same as with regular chunked encoding? Do we need a note for that as well? In both cases we aren't exactly passing a reference to the raw streams.
Doesn't closing the exchange call close on both the input/output stream? |
Well - no. The connection will be reused for the next request when the chunked streams are closed.
We may need to link back to the upgrade paragraph in |
I see, we should probably close the actual streams when calling close on the upgrade stream.
I suppose you're right, but it would be nice if calling close on HttpExchange would also close the upgraded streams. |
Chunked encoding does not expose the "raw" socket either. There is a framing structure (though primitive)
|
Maybe we could allow sendResponseHeaders to throw
Actually that won't work. Let me think about it ... It really needs to be a new method to allow for existing implementations that don't support it ... Something like |
While some implementations do it that way I'm not completely sure it's right to make all of them try to implement Upgrade.
Not totally sold on this
A separate method to do essentially the same thing as sendResponseHeaders? The main change is the implicit swap of the streams. I would be agreeable with this if For context on why I would prefer to stick with |
UpgradeInputStream
to ensure that the server keeps track of when the upgraded request is closedsendResponseHeaders
will not immediately close the output streamsendResponseHeaders
will use anUndefLengthOutputStream
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/27751/head:pull/27751
$ git checkout pull/27751
Update a local copy of the PR:
$ git checkout pull/27751
$ git pull https://git.openjdk.org/jdk.git pull/27751/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 27751
View PR using the GUI difftool:
$ git pr show -t 27751
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/27751.diff
Using Webrev
Link to Webrev Comment