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

fix: Body's reader is now optional; may be checked for emptiness #14

Merged
merged 1 commit into from Jan 14, 2020

Conversation

mmstick
Copy link
Contributor

@mmstick mmstick commented Dec 18, 2019

SUMMARY:

Fixes the integration issue with isahc, whereby a isahc::Body created from
isahc::Body::readerhas a length of None, which signals to isahc::Client
to send a body with an unknown length. A length of None is interpreted as
being unknown, and therefore a body is sent with every request. This causes a
501 error on servers which do not permit a body in the request, such as GET
requests to Cloudflare CDNs.

CHANGES:

  • Changed http_client::Body's reader field to being optional
  • Added a http_client::Body::is_empty method to check for emptiness
  • On creating a new request for isahc::Client:
    • Create a isahc::Body::empty if http_client::Body is empty
    • Create a isahc::Body::reader if otherwise not empty

@SirVer
Copy link

SirVer commented Dec 19, 2019

This looks like a reasonable change to me, though I cannot comment if there is ever a use case where somebody wants to send a non-empty body, but with zero length. I assume there is, since isahc decided to model essentially three things:

  1. Body::empty
  2. Body("")
  3. Body(s) where s.len() > 0

Http before this change only allowed 2 and 3, after this change only allows 1. and 3. Is that acceptable?

@mmstick
Copy link
Contributor Author

mmstick commented Dec 19, 2019

Actually, 2 is still permitted if you create a body with an empty string or array. It's only considered empty if you create a body with Body::empty().

@SirVer
Copy link

SirVer commented Dec 20, 2019

@mmstick Huh, it reads as if this code is eating that case: https://github.com/http-rs/http-client/pull/14/files#diff-5f9a78c705c3d5bd9ffa2d115d3085acR46

i.e. if your string is empty, it will be turned into Body::empty by http-client. Or am I misunderstanding the code?

@yoshuawuyts
Copy link
Member

yoshuawuyts commented Dec 20, 2019

The bug we're trying to fix sounds like: "if we don't have a body, actually don't send a body". My understanding of the use cases we need to support:

  1. empty body (aka "no body")
  2. body with known length
  3. body with no known length (chunk encoding)

I just merged #15 which allows discerning between the second and third cases. The current patch should probably be rebased on master so we can cover all cases.

Is this all accurate?

@mmstick
Copy link
Contributor Author

mmstick commented Dec 20, 2019

@SirVer That would be a negative, because the impl for From<String> / From<Vec<u8>> calls Body::from_reader(), rather than Body::empty(), and Body::from_reader() always creates Some(<trait object>) rather than None. The Body::is_empty() only checks if the reader field is None, as it has no way of knowing that a trait object is technically empty.

Copy link

@SirVer SirVer 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 explanations!

@yoshuawuyts
Copy link
Member

http-rs/surf#117 (comment) might need to be applied, but we can do that in a follow-up patch. Overall this looks great, and we should merge!

SUMMARY:

Fixes the integration issue with isahc, whereby a `isahc::Body` created from
`isahc::Body::reader`has a length of `None`, which signals to `isahc::Client`
to send a body with an unknown length. A length of `None` is interpreted as
being unknown, and therefore a body is sent with every request. This causes a
501 error on servers which do not permit a body in the request, such as GET
requests to Cloudflare CDNs.

CHANGES:

* Changed `http_client::Body`'s `reader` field to being optional
* Added a `http_client::Body::is_empty` method to check for emptiness
* On creating a new request for `isahc::Client`:
  - Create a `isahc::Body::empty` if `http_client::Body` is empty
  - Create a `isahc::Body::reader` if otherwise not empty
@mmstick
Copy link
Contributor Author

mmstick commented Jan 10, 2020

Change made

@yoshuawuyts yoshuawuyts merged commit cc5ee28 into http-rs:master Jan 14, 2020
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.

None yet

3 participants