Not sure whether the responsibility lies here or with spring so I thought I'd 
ask here first. Here's the scenario.

We have a Jetty 9.2.7 async reverse proxy. It always sends back to the servers 
behind using chunked encoding.
We have backend servers built around embedded 7.0.23 (also tested the latest 
7.0.59).
Jetty is configured to make SSL connections to these servers. SSL is not the 
issue, though it may make it easier to reproduce. I can reproduce this issue at 
will.
Our backend servers are using Spring MVC with automatic argument assignment 
where some argument values come from decoded JSON in the body. For example:

@RequestMapping(method = RequestMethod.PUT, value = SOME_URL)
public @ResponseBody WebAsyncTask<SomeObject> ourMethod(@RequestBody @Valid 
final SomeObject f, @Min(1) @PathVariable(SOME_ID) final long someId, final 
HttpServletRequest request) {
}

Here's the issue.

Using Wireshark I noticed that quite often the first TCP segment passed from 
Jetty to the backend server contained the entire PUT request *except* (and this 
is important) the final 7 bytes chunk terminator. That arrives in the next 
segment on the wire.

\r\n
0
\r\n
\r\n

The nearly-complete segment causes Tomcat to wake up and start processing the 
request. To cut a very long call stack short, the automatic method argument 
assignment kicks into life and runs the Jackson JSON parser to read the 
incoming body data using org.apache.coyote.http11.filters.ChunkedInputFilter. 
Enough data is present in the buffer to fully process the request so our method 
is called with all the correct parameters and it does its stuff and sends back 
a response.

That's where it should end, but it doesn't.

The remaining 7 bytes arrive on the wire and wake up Tomcat's NIO loop again. 
Tomcat thinks it's a new request since the previous one has been completely 
handled. This causes a 400 Bad Request to be sent back up the wire following on 
from the correct response, and the connection is terminated which causes a 
closed connection to be present in Jetty's connection pool. That's bad.

My opinion is that the Jackson JSON parser shouldn't have to care about the 
type of stream it's reading from so the responsibility should be with the 
chunked input stream to ensure that it doesn't get into this state. Perhaps if 
it were to always read ahead the next chunk size before handing back a 
completed chunk of data then it could ensure that the trailing zero is always 
consumed.

Any thoughts?

- Andy
Visit our website at http://www.ubs.com 

This message contains confidential information and is intended only 
for the individual named. If you are not the named addressee you 
should not disseminate, distribute or copy this e-mail. Please 
notify the sender immediately by e-mail if you have received this 
e-mail by mistake and delete this e-mail from your system. 

E-mails are not encrypted and cannot be guaranteed to be secure or 
error-free as information could be intercepted, corrupted, lost, 
destroyed, arrive late or incomplete, or contain viruses. The sender 
therefore does not accept liability for any errors or omissions in the 
contents of this message which arise as a result of e-mail transmission. 
If verification is required please request a hard-copy version. This 
message is provided for informational purposes and should not be 
construed as a solicitation or offer to buy or sell any securities 
or related financial instruments. 

UBS Limited is a company limited by shares incorporated in the United 
Kingdom registered in England and Wales with number 2035362.  
Registered Office: 1 Finsbury Avenue, London EC2M 2PP
UBS Limited is authorised by the Prudential Regulation Authority 
and regulated by the Financial Conduct Authority and the Prudential 
Regulation Authority.

UBS AG is a public company incorporated with limited liability in
Switzerland domiciled in the Canton of Basel-City and the Canton of
Zurich respectively registered at the Commercial Registry offices in
those Cantons with new Identification No: CHE-101.329.561 as from 18
December 2013 (and prior to 18 December 2013 with Identification
No: CH-270.3.004.646-4) and having respective head offices at
Aeschenvorstadt 1, 4051 Basel and Bahnhofstrasse 45, 8001 Zurich,
Switzerland and is authorised and regulated by the Financial Market
Supervisory Authority in Switzerland.  Registered in the United
Kingdom as a foreign company with No: FC021146 and having a UK
Establishment registered at Companies House, Cardiff, with
No: BR 004507.  The principal office of UK Establishment: 1 Finsbury
Avenue, London EC2M 2PP.  In the United Kingdom, UBS AG is authorised
by the Prudential Regulation Authority and subject to regulation
by the Financial Conduct Authority and limited regulation by the
Prudential Regulation Authority.  Details about the extent of our
regulation by the Prudential Regulation Authority are available
from us on request.

UBS reserves the right to retain all messages. Messages are protected 
and accessed only in legally justified cases. 
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to