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

feat(http1): add support for receiving trailer fields #3637

Merged
merged 11 commits into from
May 13, 2024

Conversation

hjr3
Copy link
Contributor

@hjr3 hjr3 commented Apr 17, 2024

Closes #2703

In #3375 we were strict about sending trailers per RFC 7230. In this PR, I have been much more accepting of trailers. Is this the behavior we want?

Some questions:

  • If the client does not send TE: trailers but the server sends trailer headers, should trailers be parsed and passed along?
  • If the server does not include a trailers: ... header indicating which trailer headers are being returned, should trailers be parsed and passed along? I think this one is almost certainly "yes".
  • If the server includes trailers with invalid header names, such as Content-Length: 5, should that still be parsed and passed along?

tests/server.rs Outdated Show resolved Hide resolved
src/proto/h1/decode.rs Outdated Show resolved Hide resolved
Copy link
Member

@dswij dswij left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! It looks great overall.

If the server does not include a trailers: ... header indicating which trailer headers are being returned, should trailers be parsed and passed along? I think this one is almost certainly "yes".

Yes. I think hyper should pass this along and let users decide what to do with the extra trailers.

If the server includes trailers with invalid header names, such as Content-Length: 5, should that still be parsed and passed along?

I'm not too sure about this one. I see two possible options:

  1. Pass it along but mark it as unexpected
  2. Err it

I'm interested to see what the others think about this

trace!("found possible trailers");
match decode_trailers(
&mut trailers_buf.take().expect("Trailer is None"),
// decoder enforces that trailers count will not exceed usize::MAX
Copy link
Member

Choose a reason for hiding this comment

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

where are we enforcing that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i also added a check in 545f8c4

src/proto/h1/decode.rs Outdated Show resolved Hide resolved
match byte {
b'\n' => {
if *trailers_cnt == usize::MAX as u64 {
return Poll::Ready(Err(io::Error::new(
Copy link
Member

Choose a reason for hiding this comment

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

Can we write some tests covering this as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added in 545f8c4

i also lowered the trailer limit to 1024 as i cannot imagine a use case for sending a million trailers.

Copy link
Member

Choose a reason for hiding this comment

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

Yea, limits are needed, both on number of field pairs, and bytes itself, or else we expose servers to OOM attacks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a size limit in f194be1

The trailer limit is now 1024 instead of usize::MAX. There is also a
test proving that the trailer limit is respected.
The size of the trailer fields is now limited. The limit accounts for a
single, very large trailer field or many trailer fields that exceed the
limit in aggregate.
src/proto/h1/decode.rs Outdated Show resolved Hide resolved
hjr3 added 2 commits May 2, 2024 06:21
Trailer parsing now honors h1_max_headers option. It also supports a
future h1_max_header_size option.
Copy link
Member

@dswij dswij left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the PR!

Anything you want to add? @seanmonstar

Copy link
Member

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

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

Alright, just got to review it all. Looks really good, thank you!

The one thing I think that could help is to add some docs about the support, including what is and isn't enforced. But then, as I looked around so as to suggest where, I realized that there's likely several behavioral things for HTTP/1 or HTTP/2 that aren't really documented. So, in that case, it doesn't seem fair to block this on wanting the docs. Rather, I'll open an issue to decide on where to put those, and what things are missing.

@seanmonstar seanmonstar merged commit ac84af6 into hyperium:master May 13, 2024
21 checks passed
@hjr3 hjr3 deleted the http1-send-trailers branch May 14, 2024 13:42
@hjr3
Copy link
Contributor Author

hjr3 commented May 14, 2024

@seanmonstar Please feel free to assign me any relevant issues. I already some blog posts on sending trailers:

I had planned on writing one for receiving trailers. I had a note to ask you if you wanted this sort of content in examples, the hyper.rs guides, etc.

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.

Receiving HTTP/1.1 trailers
3 participants