[][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 an Entity, 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 a BodyWriter (which implements std::io::Writer). The caller should produce the complete body or call BodyWriter::abort, causing the HTTP stream to terminate abruptly.

Why two ways?

They have pros and cons. This chart shows some of them:

servestreaming_body
automatic byte range servingyesno (always sends full body)
backpressureyesno
conditional GETyesunimplemented (always sends body)
sends first byte before length knownnoyes
automatic gzip content encodingnoyes

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 std::io::Write implementation that makes a chunked hyper response body stream. Automatically applies gzip content encoding if requested by the client.

ChunkedReadFile

A HTTP entity created from a std::fs::File which reads the file chunk-by-chunk within a tokio::task::block_in_place closure.

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 Expires, Cache-Control, and Vary headers if desired.

should_gzip

Returns iff it's preferable to use Content-Encoding: gzip when responding to the given request, rather than no content coding.

streaming_body

Adds a streaming body to the given request if a body is needed.