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

Add TE header validation for HTTP/2 and HTTP/1.1 requests #498

Merged
merged 1 commit into from
Oct 20, 2024

Conversation

arturobernalg
Copy link
Member

This PR introduces two interceptors, H2RequestTE and RequestTE, to ensure the correct validation of the TE header in both HTTP/2 and HTTP/1.1 requests:

  • H2RequestTE: Ensures that the TE header in HTTP/2 requests only contains the trailers directive, as required by the protocol. Any other transfer coding present will result in a ProtocolException.

  • RequestTE: Validates the TE header in HTTP/1.1 requests by:
    Ensuring the chunked transfer coding is not explicitly listed, as it is implicitly supported.
    Verifying that the Connection: TE header is present to prevent TE from being forwarded by intermediaries.

@ok2c
Copy link
Member

ok2c commented Oct 17, 2024

@arturobernalg It is not our job to police the users, if they manually add headers to requests. We need to ensure strict protocol conformance of headers that HttpCore protocol interceptors generate and leave those added by the users alone. The TE interceptors can be useful, but we should not add them to the protocol processors by default. These checks eat into the overall execution time and transport performance. Let the users decide whether or not they want to have them.

What we might do is to have strict versions of protocol processors in addition to the default ones.

@arturobernalg arturobernalg force-pushed the te-header branch 2 times, most recently from 2d6f96f to bedfe0c Compare October 17, 2024 17:30
@arturobernalg arturobernalg marked this pull request as draft October 17, 2024 18:10
@ok2c
Copy link
Member

ok2c commented Oct 18, 2024

@arturobernalg

  1. @since tag should be 5.4
  2. Now we have similar check done twice, once in the new interceptors and another one in H2RequestConformance. I think these new checks should be moved to the existing interceptors.

@arturobernalg
Copy link
Member Author

@arturobernalg

1. `@since` tag should be 5.4

2. Now we have similar check done twice, once in the new interceptors and another one in `H2RequestConformance`.  I think these new checks should be moved to the existing interceptors.

@ok2c
I’ve made the changes as you suggested. I’ve removed the new TE checks for HTTP/2 since they were redundant with the existing validations in H2RequestConformance. Apologies for the oversight on my part, as I had previously validated your PR with these changes.

@ok2c
Copy link
Member

ok2c commented Oct 19, 2024

@ok2c I’ve made the changes as you suggested. I’ve removed the new TE checks for HTTP/2 since they were redundant with the existing validations in H2RequestConformance. Apologies for the oversight on my part, as I had previously validated your PR with these changes.

@arturobernalg Do not worry. This is why do reviews and cross check one another's changes.

* @param request the HTTP request to validate
* @throws HttpException if the {@code Connection: TE} header is missing
*/
private void validateConnectionHeader(final HttpRequest request) throws HttpException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg You can really optimize this bit by making use of MessageSupport#parseTokens. See how this is done in DefaultContentLengthStrategy

https://github.com/apache/httpcomponents-core/blob/master/httpcore5/src/main/java/org/apache/hc/core5/http/impl/DefaultContentLengthStrategy.java#L76

* @throws HttpException if the {@code Connection: TE} header is missing
*/
private void validateConnectionHeader(final HttpRequest request) throws HttpException {
final Header connectionHeader = request.getFirstHeader(HttpHeaders.CONNECTION);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg Please also note it is legal for a message to have multiple Connection headers. Just looking at the first one is not good enough. I think the same applies to TE

@arturobernalg arturobernalg force-pushed the te-header branch 2 times, most recently from 2dcd8b5 to 925c1f6 Compare October 19, 2024 20:13
@arturobernalg
Copy link
Member Author

@ok2c please take another look.

* @param teValue the value of the {@code TE} header
* @throws HttpException if the {@code TE} header contains invalid values
*/
private void validateTEField(final String teValue) throws HttpException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arturobernalg TE tokens can also be transmitted with multiple headers, like Connection.

TE: this
TE: that, trailers

Can you change this method to use MessageSupport#parseTokens?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@arturobernalg Your current approach results in an unnecessary creation of an array and a copy of the header value, which is wasteful. Please use MessageSupport#parseTokens that avoids all that.

@ok2c
Copy link
Member

ok2c commented Oct 19, 2024

@arturobernalg Please take a look ok2c@24a7c00 This is all it takes. The cost is 4 booleans and two lambdas.

Implemented a new RequestTE interceptor for validating the TE header in HTTP/1.1 requests, ensuring proper protocol handling. Introduced strict client and server options that allow users to enable additional protocol validation checks, such as the validation of TE headers for HTTP/2 and HTTP/1.1.
@arturobernalg
Copy link
Member Author

@arturobernalg Please take a look ok2c@24a7c00 This is all it takes. The cost is 4 booleans and two lambdas.

@ok2c You’re absolutely right. I’ve made the necessary changes as per your suggestion. Thanks for the feedback!

@arturobernalg arturobernalg merged commit 98f3252 into apache:master Oct 20, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants