-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8331195: Improve com.sun.net.httpserver.HttpExchange usability #28132
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
8331195: Improve com.sun.net.httpserver.HttpExchange usability #28132
Conversation
|
/csr needed |
|
👋 Welcome back michaelm! A progress list of the required criteria for merging this PR into |
|
@Michael-Mc-Mahon This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 95 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
|
@Michael-Mc-Mahon has indicated that a compatibility and specification (CSR) request is needed for this pull request. @Michael-Mc-Mahon please create a CSR request for issue JDK-8331195 with the correct fix version. This pull request cannot be integrated until the CSR request is approved. |
|
@Michael-Mc-Mahon 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. |
Webrevs
|
|
This is a good idea, but it kind of hides the fact that passing 0 may not do what you think it does. Typically the pitfall is to assume that if you have an array of bytes then you can can call In addition I would suggest adding code snipets showing both cases (one using a byte array and passing |
Actually, that case is not so bad. What happens is that chunked encoding is selected but the response body
The worse case is expecting a negative value to mean an indefinite (chunked encoded) length. You definitely don't get what you expect in that case. |
I've added an API note. I'd prefer not to drown the whole spec out with code samples just for this issue if possible. |
dfuch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the @apiNote and explicitely mentionning the value of RSPBODY_CHUNKED. The new text looks good to me now.
Could be good to double check what would happen if you have something like that:
public void handle(final HttpExchange exchange) throws IOException {
byte[] bytes = getResponseBody(exchange.getRequestURI());
long fixedlen = bytes.length == 0 ? RSPBODY_EMPTY : bytes.length;
exchange.sendResponseHeaders(200, fixedlen);
try (OutputStream os = exchange.getResponseBody()) {
os.write(bytes);
}
}
where getResponseBody(exchange.getRequestURI()); returns new byte[0];
will os.write throw, or will it be no-op?
If it throws then should it be specified that sendResponseHeaders closes the output stream?
That would work fine. What possibly needs to be mentioned is that with chunked encoding, you must always |
| /** | ||
| * No response body is being sent with this response | ||
| * | ||
| * @since 26 | ||
| */ | ||
| public static final long RSPBODY_EMPTY = -1l; | ||
|
|
||
| /** | ||
| * The response body is unspecified and will be chunk encoded | ||
| * | ||
| * @since 26 | ||
| */ | ||
| public static final long RSPBODY_CHUNKED = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add:
@see #sendResponseHeaders(int, long)
to make it clearer what these constants are for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add:
@see #sendResponseHeaders(int, long)to make it clearer what these constants are for?
Good idea
|
I've said all my objections before. I think if we waited for member patterns we could have an API that doesn't need the constants and I think that the constants do not solve for the bad patterns today. |
Seriously consider that if we had member patterns would we add this API? If the answer is no (and I think it is no) lets just not do it |
public void handle(final HttpExchange exchange) throws IOException {
byte[] bytes = getResponseBody(exchange.getRequestURI());
long fixedlen = bytes.length == 0 ? RSPBODY_EMPTY : bytes.length;
exchange.sendResponseHeaders(200, fixedlen);
try (OutputStream os = exchange.getResponseBody()) {
os.write(bytes);
}
}versus public void handle(final HttpExchange exchange) throws IOException {
byte[] bytes = getResponseBody(exchange.getRequestURI());
exchange.sendResponseHeaders(200, ResponseLength.known(bytes));
try (OutputStream os = exchange.getResponseBody()) {
os.write(bytes);
}
}This has the benefit of us being able to deprecate And in the presence of such an API there are no uses for the constants so...do you see my frustration? You need to know to look for |
|
I don't disagree but adding new APIs is a bigger maintenance cost than adding two simple constants. |
|
I don't agree that you have to go looking for these constants. I think we have to look at it from the point of view of a developer new to the API and someone reading the apidoc for the first time will be clearly drawn to the constant names. I agree a new method with new parameter types would be nicer from an IDE perspective. But if we are going to add a new method then I think we are going to have a wider discussion such as occurred previously with this issue. So, even if we end up doing that and deprecating the present sendResponseHeaders() this effort is not going to get in the way of that. |
dfuch
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please hold off integrating right now - I've launched a couple of tests.
My tier1 and tier2 test run passes |
| 0, | ||
| "/", exchange -> { | ||
| exchange.sendResponseHeaders(200, 0); | ||
| exchange.sendResponseHeaders(200, RSPBODY_EMPTY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing that this is intentionally using RSPBODY_EMPTY and previously it was a bug to send 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, I just heard the answer to this offline. This looks OK to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Jaikiran. I think 0 was probably not intended. I decided to "fix" it in this place, but leave it in the others
| System.out.println("Sending response for request " + exchange.getRequestURI() + " from " + exchange.getRemoteAddress()); | ||
| reqFinishedProcessing.countDown(); | ||
| exchange.sendResponseHeaders(200, 0); | ||
| exchange.sendResponseHeaders(200, RSPBODY_CHUNKED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this use RSPBODY_EMPTY instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted above, I decided to change it in one place, but leave it as is, in others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Michael. That's fine with me.
|
Overall this looks good to me. I just have one question which I've added inline. |
jaikiran
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright year updates look good to me and so does the rest of this PR. I just have one comment here #28132 (comment)
|
/integrate |
|
Going to push as commit 1877ff9.
Your commit was automatically rebased without conflicts. |
|
@Michael-Mc-Mahon Pushed as commit 1877ff9. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
I'd like to return to this issue with a new PR that addresses the usability issue minimally. Namely to define numeric constants
for the counter-intuitive responseLength values in
HttpExchange.sendResponseHeaders. The apidoc then refers to the constant names rather than the numeric values.I've updated the implementation and some tests (though not all yet) to use the constant names. I'm open to suggestions on the names themselves. Once that is agreed, I'll update the remaining tests and any other call sites in the implementation.
Thanks,
Michael
Progress
Issues
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28132/head:pull/28132$ git checkout pull/28132Update a local copy of the PR:
$ git checkout pull/28132$ git pull https://git.openjdk.org/jdk.git pull/28132/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 28132View PR using the GUI difftool:
$ git pr show -t 28132Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28132.diff
Using Webrev
Link to Webrev Comment