Closed seanmonstar closed 1 year ago
cc @LucioFranco @hawkw
As a consumer, I like this proposal.
hyper::body::Empty
: an empty body, yielding no data or trailers. Since it never yields data, itsBuf
type could even be some enumNeverBuf {}
.
I don't want to jinx this, but it's possible that !
might get stabilized with https://github.com/rust-lang/rust/pull/79366. I don't think it'll be stable in time for Hyper 0.14, but there's a chance it might be stable in time for Hyper 0.15 (if planned).
Does this imply that the Client type can drop its body type parameter? That'd be quite nice for reasons even beyond this issue, like allowing non 'static
bodies.
I don't see how the client would drop its body type parameter... it still needs to know what kind of bodies you expect to send.
I like this proposal, I'd also consider adding a GenericBody
which is an enum of all of the bodies + the boxed one? We may also want to provide utils like EitherBody
to compose them. Overall, I am a fan of this, no major nits.
Would be nice to still be able to use all types at once, as @LucioFranco said. I belive most of apps mix those, eg. Full
for data, Streaming
for SSE etc. If body type goes into server template parameter, it would be a bit harder to return multi-variant version. Boxing is an option, but still requires some allocations. Having enum of three types doesn't sound bad.
Something I didn't consider when responding to this initially: what implications, if any, does this proposed change have for h2-style patterns where the initial handshake request has a body of ()
but the client subsequently expected to write to a stream handle?
If you expect different requests to have different body behaviors, you can use a body type that captures that.
So, it does seem like this is desirable, but I'm going to punt to the next milestone, since proposing this right when 0.14 was almost ready is kinda late.
I'm interested in implementing this if it is ok. I agree with @LucioFranco that we need to have a GenericBody type. BoxBody would also work but it requires allocation. I also don't see a Channel type on @seanmonstar's proposal, so I guess we need to add that too.
Those body types (maybe except for Streaming
and GenericBody
?) seem to be unspecific to hyper
and to be able to be implemented in http-body
or somewhere. They can be generic over the data and error types so that hyper
can re-export them as, for example, pub type Full<T = Bytes, E = crate::Error> = http_body::Full<T, E>
.
Having concrete Body
implementations outside of hyper
might be useful for abstractions (like tower-http
) that do not necessarily depend on a specific version of hyper
.
Having concrete Body implementations outside of hyper might be useful for abstractions (like tower-http) that do not necessarily depend on a specific version of hyper.
I'd like to +1 this. Body things that aren't hyper specific would be nice to have in http-body if thats appropriate.
Earlier today I opened a PR for adding Empty
to http-body https://github.com/hyperium/http-body/pull/37. I use it in ServeDir
.
The http-body-util
crate now has many of these variants. We likely won't re-export directly from hyper, since that util crate is less stable. Next steps for hyper 1.0 are to remove the internal variants of hyper::Body
, and replace their usage in tests and examples with those from http-body-util
.
Hi, @seanmonstar. I'm trying to work on the Remove Body's Once variant
.
However, I met a problem on the ffi
part:
ffi_fn! {
/// Construct a new HTTP request.
fn hyper_request_new() -> *mut hyper_request {
Box::into_raw(Box::new(hyper_request(Request::new(Body::empty()))))
} ?= std::ptr::null_mut()
}
I can't remove Body::empty()
(which depends on Once
) because hyper_request
uses Body
directly:
pub struct hyper_request(pub(super) Request<Body>);
Any ideas?
Oh, good catch! Here, I broke it out into a sub-issue, so we can chat there about this specific part: https://github.com/hyperium/hyper/issues/2922
This has been suggested before: the current trait
hyper::body::HttpBody
should be renamed tohyper::Body
, and the existing structhyper::Body
should be split up into more descriptive implementations. I'm coming around to that idea, so here's the full proposal.Proposal
hyper::body::HttpBody
tohyper::Body
hyper::Body
type:hyper::body::Empty
: an empty body, yielding no data or trailers. Since it never yields data, itsBuf
type could even be someenum NeverBuf {}
.hyper::body::Full
: the full body, able to yield 1 data buffer (whathyper::Body::from(buf)
is in 0.13).hyper::body::Streaming
: the streaming bodies received from a remote over HTTP/1 or 2.hyper::body::BoxBody
A client response would then be
Response<Streaming>
(as would a serverRequest<Streaming>
), since they are streamed from the connection. Hopefully, this should make the intent clearer when you have aRequest<Empty>
orResponse<Full>
, instead of justRequest<Body>
.Status: Accepted
Progress
stream
variantOnce
variantbody::Sender
type andBody::channel()
constructor private.Body
toRecv
temporarilyHttpBody
re-export toBody