To make repro easier:
https://gist.github.com/mwisnicki/6df71b2b5f7712306fca27bf34c24e94

On Tue, 10 Aug 2021 at 04:00, Marcin Wisnicki <mwisni...@gmail.com> wrote:
>
> However I've noticed that in Tomcat the behaviour can only be achieved
> by throwing an exception before close.
> If I don't throw and simply return or call close before exception
> Tomcat will write terminal '0'.
>
> Is there a way to trigger immediate close without that write('0')
> without using exceptions?
>
> On Tue, 10 Aug 2021 at 03:27, Marcin Wisnicki <mwisni...@gmail.com> wrote:
> >
> > Thanks, it seems like it must be one of Spring Boot's filters breaking
> > it. I should've tried without it first, mea culpa.
> > In a pure tomcat container it works as you described whereas with
> > Spring something inserts final 0 so the aborted connection looks like
> > a valid chunked response to clients.
> >
> > I'll move my question to a more appropriate forum.
> >
> > On Tue, 10 Aug 2021 at 02:45, Mark Thomas <ma...@apache.org> wrote:
> > >
> > > On 10/08/2021 02:25, Marcin Wisnicki wrote:
> > > > I have a servlet (it's really a SpringBoot controller but it shouldn't
> > > > matter?) in Tomcat 9.0.46 that streams responses of unknown size to
> > > > the browser.
> > > >
> > > > I've discovered that if the streaming process fails in the middle of
> > > > the write, the client will simply get an incomplete file and think it
> > > > was successful.
> > >
> > > Then you have a broken client.
> > >
> > > > Indeed there is no way to tell from the browser side there was an error.
> > >
> > > That statement is incorrect.
> > >
> > > >    void doGet(HttpServletResponse resp) {
> > > >      resp.setStatus(200);
> > > >      resp.setHeader("Content-Disposition", "...");
> > > >      resp.setContentType("application/octet-stream");
> > > >      var out = resp.getOutputStream();
> > > >      out.flush();
> > > >      if (true) throw new RuntimeException("simulated error");
> > > >      // status is already sent here, can't change it!
> > > >    }
> > > >
> > > > As far as I can tell a web server should close connection with TCP RST
> > > > or write some garbage that's not a valid chunked response.
> > >
> > > You won't see a TCP RST. You will see invalid chunked encoding.
> > >
> > > > This is what some other servers do such as express.js.
> > > >
> > > > Unfortunately Tomcat does neither and also there seems to be no way to
> > > > trigger that using either Servlet or Tomcat api.
> > >
> > > Again, that statement is incorrect.
> > >
> > > > I've tested it by setting "Connection: close" then writing garbage and
> > > > it seems browser recognized download error.
> > > > But then I lose chunking in the output stream and can't actually write
> > > > a response.
> > > >
> > > > How do people solve it?
> > >
> > > Look at the following from a test using telnet to make a request to the
> > > sample servlet above:
> > >
> > > $ telnet localhost 8080
> > > Trying ::1...
> > > Connected to localhost.
> > > Escape character is '^]'.
> > > GET /tomcat-bugs/user004 HTTP/1.1
> > > Host: localhost
> > >
> > > HTTP/1.1 200
> > > Content-Type: text/plain
> > > Transfer-Encoding: chunked
> > > Date: Tue, 10 Aug 2021 06:38:06 GMT
> > >
> > > Connection closed by foreign host.
> > > $
> > >
> > > The headers are sent when the Servlet flushes the response. That is as
> > > required by the Servlet specification.
> > >
> > > What tells the client that the response is incomplete is that chunked
> > > encoding is being used but there is no final chunk.
> > >
> > > Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to