-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Experiment/12/improve default servlet #10222
Conversation
gregw
commented
Aug 4, 2023
- don't wrap the httpServletRequest unless necessary due to wrapping
- don't wrap the httpServletResponse unless necessary due to wrapping
- send content asynchronously if large and unfiltered
- Remove unused boolean return from ServletChannel.handle
- added TODOs where range request handling could calculate content length
+ don't wrap the httpServletRequest unless necessary due to wrapping + don't wrap the httpServletResponse unless necessary due to wrapping + send content asynchronously if large and unfiltered + Remove unused boolean return from ServletChannel.handle + added TODOs where range request handling could calculate content length
+ Call multipartlength, even though it is always -1
@lorban @sbordet @lachlan-roberts this PR improves the efficiency of the DefaultServlet. However, it has affected some range tests that were expecting content-length to be set, but that was only because the combined parts are less that an output buffer in size. It would be better if the mutlti-part was able to calculate the length. Perhaps it needs to pre-generate the part headers? But OK for now without the content-length |
Cleanup downcasting
Cleanup downcasting
Protect close after lasts
Prefer the wrapped servlet request/response
Do not use Wrappers for the wrapped servlet request/response
…/improve-default-servlet
+ Use static for bytes written
@lorban welcome back. Can you review this as a priority. I think it is a good cleanup of the default servlet and removes the intrinsic blocking that itches at my sole. |
@lachlan-roberts @sbordet would be good to get a review on this as well. |
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.
One thing that's making me scratch my head:
Now that ServletCoreRequest|Response
have been extracted as top-level classes next to ServletApiRequest|Response
I wonder if their names and proximity won't add confusion in the future?
...ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java
Outdated
Show resolved
Hide resolved
...ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java
Outdated
Show resolved
Hide resolved
...ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java
Outdated
Show resolved
Hide resolved
...ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java
Outdated
Show resolved
Hide resolved
...ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
Outdated
Show resolved
Hide resolved
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
Outdated
Show resolved
Hide resolved
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
Outdated
Show resolved
Hide resolved
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
Show resolved
Hide resolved
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java
Outdated
Show resolved
Hide resolved
Any suggestions? |
Since they are implementations, how about very long names? |
I don't think "Delegating" adds very much.... We could do |
updates from review
updates from review
updates from review
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 cannot come up with better *Request
class names, so the current ones probably are reasonable.
# Conflicts: # jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/AsyncContextState.java # jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannel.java
CI failure is a flaky test... giving it one more spin.... |
@lorban can you re review after I updated from merge conflict |
default -> | ||
{ | ||
if (BufferUtil.isEmpty(content)) | ||
callback.succeeded(); |
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.
What is the case where this happens?
If last
is true do we not need to do anything?
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.
@lachlan-roberts This can happen is something does a flush when last has already been sent. This can be needed when checking there is no data buffered in a writer.
{ | ||
if (sendErrorOrAbort("Insufficient content written")) | ||
long written = getBytesWritten(); |
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.
This getBytesWritten()
implementation is going directly to the ChannelResponse
, which will be the compressed content length if Gzip is used.
Is it possible that the ServletContextResponse
detects the content is incomplete because it was expecting the uncompressed content length from getBytesWritten()
?
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.
@lachlan-roberts The code is comparing the actual bytes written to the actual content-length header (if any). Either they both represent compressed content or they both don't.
@@ -2183,7 +2183,7 @@ public static Stream<Arguments> rangeScenarios() | |||
String body = response.getContent(); | |||
|
|||
assertThat(response, containsHeaderValue("Content-Type", "multipart/byteranges")); | |||
assertThat(response, containsHeaderValue("Content-Length", "" + body.length())); | |||
// TODO #10307 assertThat(response, containsHeaderValue("Content-Length", String.valueOf(body.length()))); |
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.
Why were these tests passing before but not now?
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.
@lachlan-roberts Because the content was written via the servlet HttpOutput which aggregated them and they were small enough examples to fit into a single buffer. Thus the content length was known. Now it is written without the copy, but that means the length is not known when the response is committed.
See issue.