[−][src]Crate http_serve
Helpers for serving HTTP GET and HEAD responses with hyper 0.11.x and tokio. A future version is likely to switch to the interface of the http crate.
This crate supplies two ways to respond to HTTP GET and HEAD requests:
- the
serve
function can be used to serve anEntity
, a trait representing reusable, byte-rangeable HTTP entities.Entity
must be able to produce exactly the same data on every call, know its size in advance, and be able to produce portions of the data on demand. - the
streaming_body
function can be used to add a body to an otherwise-complete response. If a body is needed, it returns aBodyWriter
(which implementsstd::io::Writer
). The caller should produce the complete body or callBodyWriter::abort
, causing the HTTP stream to terminate abruptly.
Why two ways?
They have pros and cons. This chart shows some of them:
serve | streaming_body | |
---|---|---|
automatic byte range serving | yes | no (always sends full body) |
backpressure | yes | no |
conditional GET | yes | unimplemented (always sends body) |
sends first byte before length known | no | yes |
automatic gzip content encoding | no | yes |
Use serve
when:
- metadata (length, etag, etc) and byte ranges can be regenerated cheaply and consistently
via a lazy
Entity
. - data can be fully buffered in memory or on disk and reused many times. You may want to
create a pair of buffers for gzipped (for user-agents which specify
Accept-Encoding: gzip
) vs raw.
Consider streaming_body
if data would be fully buffered each time a response is sent.
Once you return a hyper::server::Response
to hyper, your only way to signal error to the
client is to abruptly close the HTTP connection while sending the body. If you want the ability
to return a well-formatted error to the client while producing body bytes, you must buffer the
entire body in-memory before returning anything to hyper.
If you are buffering a response in memory, serve
requires copying the bytes (when using
Data = Vec<u8>
or similar) or atomic reference-counting (with Data = Arc<Vec<u8>>
or
similar). streaming_body
doesn't need to keep its own copy for potential future use; it may
be cheaper because it can simply hand ownership of the existing Vec<u8>
s to hyper.
Why the weird type bounds? Why not use hyper::Body
and hyper::Chunk
for everything?
These bounds are compatible with hyper::Body
and hyper::Chunk
, and most callers will use
those types. There are times when it's desirable to have more flexible ownership provided by a
type such as reffers::ARefs<'static, [u8]>
. One is mmap
-based file serving: a
hyper::Chunk
would require copying the data in each chunk. An implementation with ARefs
could instead mmap
and mlock
the data on another thread and provide chunks which munmap
when dropped. In these cases, the caller can supply an alternate implementation of the
http_body::Body
trait which uses a different Data
type than hyper::Chunk
.
Structs
BodyWriter | A |
ChunkedReadFile | A HTTP entity created from a |
StreamingBodyBuilder |
Traits
Entity | A reusable, read-only, byte-rangeable HTTP entity for GET and HEAD serving. Must return exactly the same data on every call. |
Functions
serve | Serves GET and HEAD requests for a given byte-ranged entity.
Handles conditional & subrange requests.
The caller is expected to have already determined the correct entity and appended
|
should_gzip | Returns iff it's preferable to use |
streaming_body | Adds a streaming body to the given request if a body is needed. |