Skip to content
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

Http11Processor's keep alive state and input buffer's swallow state must be synchronized #550

Merged
merged 4 commits into from
Sep 12, 2022

Conversation

malaysf
Copy link
Contributor

@malaysf malaysf commented Sep 2, 2022

Fixing a bug where a connection would be kept alive without swallowing the input from the request stream.

When a request comes in with a 100 Continue expectation, and the server immediately responds with a 200 status without reading the request body at all, the next request on the connection will fail because Tomcat cannot parse the HTTP verb. The first request left Http11Processor in a state where it kept the connection alive but did not discard the request body, thus reading the next request began at the wrong place in the stream.

The new unit test replicates the issue and is addressed by the code changes to keep the keepAlive and input buffer swallow state in sync with each other.

…g the input from the request stream.

When a request comes in with a 100 Continue expectation, and the server immediately responds with a 200 status without reading the request body at all, the next request on the connection will fail because Tomcat cannot parse the HTTP verb.

The new unit test replicates the issue and is addressed by the code changes to keep the keepAlive and input buffer swallow state in sync with each other.
@rmaucher
Copy link
Contributor

rmaucher commented Sep 5, 2022

A request with an expectation is not supposed to be performed the same way as an identical request without it. So you have to be careful and I don't think your patch is correct.
Looking at the code in Http11Processor.ack, it looks to me that it should work so I don't really understand yet.

@malaysf
Copy link
Contributor Author

malaysf commented Sep 6, 2022

The TestSwallowAbortedUploads test fails so I need to look into that.

We ran into this issue in production and were able to reproduce with curl or postman requests to an API that returns 200 without ever reading the request body.

I don't think that the core logic is wrong in Http11Processor.ack, in this situation ack is never called since the request body input stream is never read from, which triggers the ack.

When a request is started, Http11Processor.prepareExpectation sets inputBuffer.setSwallowInput(false); but keepAlive is still set to true. If keepAlive is true, then the inputBuffer's swallow state must be set to true as well to ensure that the request stream is advanced to the beginning of the next request, regardless of whether the servlet consumed all the bytes.

@markt-asf
Copy link
Contributor

I think you can just remove the inputBuffer.setSwallowInput(false) in Http11Processor.prepareExpectation(). If that is correct, I think there is at least one other call that can also be removed.

@malaysf
Copy link
Contributor Author

malaysf commented Sep 6, 2022

@markt-asf That does work and is a much simpler solution! It also doesn't break TestSwallowAbortedUploads (which I now understand why).

I will update my PR with that change. What is the other call that you think could be removed?

@markt-asf
Copy link
Contributor

I suspect the call in Http11Processor.ack() can also be removed.

@malaysf
Copy link
Contributor Author

malaysf commented Sep 7, 2022

Are you referring to the call to inputBuffer.setSwallowInput(true); in Http11Processor.ack? That does appear to be unnecessary now.

@markt-asf
Copy link
Contributor

Are you referring to the call to inputBuffer.setSwallowInput(true); in Http11Processor.ack? That does appear to be unnecessary now.

Yes. That was the one.

@malaysf
Copy link
Contributor Author

malaysf commented Sep 9, 2022

I've included that change too. Please let me know if there's anything else that should be done. Thanks!

@markt-asf markt-asf merged commit 7eae543 into apache:main Sep 12, 2022
markt-asf pushed a commit that referenced this pull request Sep 12, 2022
…k or reading request body. (#550)

* Fixing a bug where a connection would be kept alive without swallowing the input from the request stream.

When a request comes in with a 100 Continue expectation, and the server immediately responds with a 200 status without reading the request body at all, the next request on the connection will fail because Tomcat cannot parse the HTTP verb.

The new unit test replicates the issue and is addressed by removing the unnecessary changes to the swallowInput field of the Http11InputBuffer.
markt-asf pushed a commit that referenced this pull request Sep 12, 2022
…k or reading request body. (#550)

* Fixing a bug where a connection would be kept alive without swallowing the input from the request stream.

When a request comes in with a 100 Continue expectation, and the server immediately responds with a 200 status without reading the request body at all, the next request on the connection will fail because Tomcat cannot parse the HTTP verb.

The new unit test replicates the issue and is addressed by removing the unnecessary changes to the swallowInput field of the Http11InputBuffer.
markt-asf pushed a commit that referenced this pull request Sep 12, 2022
…k or reading request body. (#550)

* Fixing a bug where a connection would be kept alive without swallowing the input from the request stream.

When a request comes in with a 100 Continue expectation, and the server immediately responds with a 200 status without reading the request body at all, the next request on the connection will fail because Tomcat cannot parse the HTTP verb.

The new unit test replicates the issue and is addressed by removing the unnecessary changes to the swallowInput field of the Http11InputBuffer.
@malaysf
Copy link
Contributor Author

malaysf commented Sep 12, 2022

@markt-asf Thanks for reviewing and merging. Could this please also be included in 9.0.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants