jetty / jetty/jetty.project

jetty-12 ee10 Closure of Response Object

Open
#9,651 2 comments 0 reactions 0 assignees View on GitHub
Bug TCK
Dominant language
Java
Stars
4.1k
Forks
2k
Avg merge
3d 56m
Merged PRs (30d)
48

Description

The Servlet Specification 6.0 says:

> 5.7. Closure of Response Object
> When a response is closed, the container must immediately flush all remaining content in the response
> buffer to the client. The following events indicate that the servlet has satisfied the request and that the
> response object is to be closed:
> • The termination of the service method of the servlet.
> • The amount of content specified in the setContentLength or setContentLengthLong method of the
> response has been greater than zero and has been written to the response.
> • The sendError method is called.
> • The sendRedirect method is called.
> • The complete method on AsyncContext is called.

The tck has a test which sets the `contentLength` then writes more bytes than that, and also tries to set a header:

```
int size = 40;
response.setContentLength(size);

PrintWriter pw = response.getWriter();
pw.println("Test PASSED");
StringBuffer tmp = new StringBuffer(2 * size);
int i = 0;

while (i < 8) {
tmp = tmp.append("111111111x");
i = i + 1;
}
pw.println(tmp);
response.addIntHeader("header1", 12345);
```
Tck test is `com/sun/ts/tests/servlet/spec/httpservletresponse/URLClient.java.flushBufferTest`

Jetty fails the tck test because we respond with an `500` error instead of ignoring the extra content:

```

Error 500 java.io.IOException: written 92 > 40 content-length

HTTP ERROR 500 java.io.IOException: written 92 > 40 content-length

URI:http://localhost:38225/servlet_spec_httpservletresponse_web/HttpTestServlet?testname=flushBufferTest
STATUS:500
MESSAGE:java.io.IOException: written 92 > 40 content-length
CAUSED BY:java.io.IOException: written 92 > 40 content-length

Caused by:

java.io.IOException: written 92 > 40 content-length

at org.eclipse.jetty.server.internal.HttpChannelState$ChannelResponse.write(HttpChannelState.java:1093)
at org.eclipse.jetty.ee10.servlet.HttpOutput.channelWrite(HttpOutput.java:215)
at org.eclipse.jetty.ee10.servlet.HttpOutput.channelWrite(HttpOutput.java:200)
at org.eclipse.jetty.ee10.servlet.HttpOutput.write(HttpOutput.java:804)
at java.base/java.io.ByteArrayOutputStream.writeTo(ByteArrayOutputStream.java:161)
at org.eclipse.jetty.ee10.servlet.writer.Iso88591HttpWriter.write(Iso88591HttpWriter.java:62)
at org.eclipse.jetty.ee10.servlet.writer.HttpWriter.write(HttpWriter.java:69)
at org.eclipse.jetty.ee10.servlet.writer.ResponseWriter.println(ResponseWriter.java:426)
at org.eclipse.jetty.ee10.servlet.writer.ResponseWriter.println(ResponseWriter.java:445)
at com.sun.ts.tests.servlet.spec.httpservletresponse.HttpTestServlet.flushBufferTest(HttpTestServlet.java:59)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.sun.ts.tests.servlet.common.servlets.HttpTCKServlet.invokeTest(HttpTCKServlet.java:91)
at com.sun.ts.tests.servlet.common.servlets.HttpTCKServlet.doGet(HttpTCKServlet.java:116)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
at org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service(ServletHolder.java:1383)
at org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:738)
at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1601)
at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle(ServletHandler.java:1534)
at org.eclipse.jetty.ee10.servlet.ServletChannel.lambda$0(ServletChannel.java:425)
at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch(ServletChannel.java:659)
at org.eclipse.jetty.ee10.servlet.ServletChannel.handle(ServletChannel.java:420)
at org.eclipse.jetty.ee10.servlet.ServletHandler.handle(ServletHandler.java:458)
at org.eclipse.jetty.ee10.servlet.security.SecurityHandler.handle(SecurityHandler.java:564)
at org.eclipse.jetty.ee10.servlet.SessionHandler.handle(SessionHandler.java:664)
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:819)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:149)
at org.eclipse.jetty.server.Handler$Sequence.handle(Handler.java:665)
at org.eclipse.jetty.server.Handler$Wrapper.handle(Handler.java:611)
at org.eclipse.jetty.server.Server.handle(Server.java:175)
at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:553)
at org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:480)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
at java.base/java.lang.Thread.run(Thread.java:833)


Powered by Jetty:// 12.0.0-SNAPSHOT

```

Contributor guide

Open the contributing guide

Research direction

Start with the response-writing paths in jetty-server/.../HttpChannelState.java and jetty-ee10/.../HttpOutput.java, using the stack trace to follow the content-length failure. Run com/sun/ts/tests/servlet/spec/httpservletresponse/URLClient.java.flushBufferTest and compare its behavior with the Servlet Specification 6.0 requirements. Done means the TCK test no longer receives the reported 500 error.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.