diff options
Diffstat (limited to 'third_party/rust/http/src/lib.rs')
-rw-r--r-- | third_party/rust/http/src/lib.rs | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/third_party/rust/http/src/lib.rs b/third_party/rust/http/src/lib.rs new file mode 100644 index 0000000000..38a4c2aa7e --- /dev/null +++ b/third_party/rust/http/src/lib.rs @@ -0,0 +1,211 @@ +#![doc(html_root_url = "https://docs.rs/http/0.2.9")] + +//! A general purpose library of common HTTP types +//! +//! This crate is a general purpose library for common types found when working +//! with the HTTP protocol. You'll find `Request` and `Response` types for +//! working as either a client or a server as well as all of their components. +//! Notably you'll find `Uri` for what a `Request` is requesting, a `Method` +//! for how it's being requested, a `StatusCode` for what sort of response came +//! back, a `Version` for how this was communicated, and +//! `HeaderName`/`HeaderValue` definitions to get grouped in a `HeaderMap` to +//! work with request/response headers. +//! +//! You will notably *not* find an implementation of sending requests or +//! spinning up a server in this crate. It's intended that this crate is the +//! "standard library" for HTTP clients and servers without dictating any +//! particular implementation. Note that this crate is still early on in its +//! lifecycle so the support libraries that integrate with the `http` crate are +//! a work in progress! Stay tuned and we'll be sure to highlight crates here +//! in the future. +//! +//! ## Requests and Responses +//! +//! Perhaps the main two types in this crate are the `Request` and `Response` +//! types. A `Request` could either be constructed to get sent off as a client +//! or it can also be received to generate a `Response` for a server. Similarly +//! as a client a `Response` is what you get after sending a `Request`, whereas +//! on a server you'll be manufacturing a `Response` to send back to the client. +//! +//! Each type has a number of accessors for the component fields. For as a +//! server you might want to inspect a requests URI to dispatch it: +//! +//! ``` +//! use http::{Request, Response}; +//! +//! fn response(req: Request<()>) -> http::Result<Response<()>> { +//! match req.uri().path() { +//! "/" => index(req), +//! "/foo" => foo(req), +//! "/bar" => bar(req), +//! _ => not_found(req), +//! } +//! } +//! # fn index(_req: Request<()>) -> http::Result<Response<()>> { panic!() } +//! # fn foo(_req: Request<()>) -> http::Result<Response<()>> { panic!() } +//! # fn bar(_req: Request<()>) -> http::Result<Response<()>> { panic!() } +//! # fn not_found(_req: Request<()>) -> http::Result<Response<()>> { panic!() } +//! ``` +//! +//! On a `Request` you'll also find accessors like `method` to return a +//! `Method` and `headers` to inspect the various headers. A `Response` +//! has similar methods for headers, the status code, etc. +//! +//! In addition to getters, request/response types also have mutable accessors +//! to edit the request/response: +//! +//! ``` +//! use http::{HeaderValue, Response, StatusCode}; +//! use http::header::CONTENT_TYPE; +//! +//! fn add_server_headers<T>(response: &mut Response<T>) { +//! response.headers_mut() +//! .insert(CONTENT_TYPE, HeaderValue::from_static("text/html")); +//! *response.status_mut() = StatusCode::OK; +//! } +//! ``` +//! +//! And finally, one of the most important aspects of requests/responses, the +//! body! The `Request` and `Response` types in this crate are *generic* in +//! what their body is. This allows downstream libraries to use different +//! representations such as `Request<Vec<u8>>`, `Response<impl Read>`, +//! `Request<impl Stream<Item = Vec<u8>, Error = _>>`, or even +//! `Response<MyCustomType>` where the custom type was deserialized from JSON. +//! +//! The body representation is intentionally flexible to give downstream +//! libraries maximal flexibility in implementing the body as appropriate. +//! +//! ## HTTP Headers +//! +//! Another major piece of functionality in this library is HTTP header +//! interpretation and generation. The `HeaderName` type serves as a way to +//! define header *names*, or what's to the left of the colon. A `HeaderValue` +//! conversely is the header *value*, or what's to the right of a colon. +//! +//! For example, if you have an HTTP request that looks like: +//! +//! ```http +//! GET /foo HTTP/1.1 +//! Accept: text/html +//! ``` +//! +//! Then `"Accept"` is a `HeaderName` while `"text/html"` is a `HeaderValue`. +//! Each of these is a dedicated type to allow for a number of interesting +//! optimizations and to also encode the static guarantees of each type. For +//! example a `HeaderName` is always a valid `&str`, but a `HeaderValue` may +//! not be valid UTF-8. +//! +//! The most common header names are already defined for you as constant values +//! in the `header` module of this crate. For example: +//! +//! ``` +//! use http::header::{self, HeaderName}; +//! +//! let name: HeaderName = header::ACCEPT; +//! assert_eq!(name.as_str(), "accept"); +//! ``` +//! +//! You can, however, also parse header names from strings: +//! +//! ``` +//! use http::header::{self, HeaderName}; +//! +//! let name = "Accept".parse::<HeaderName>().unwrap(); +//! assert_eq!(name, header::ACCEPT); +//! ``` +//! +//! Header values can be created from string literals through the `from_static` +//! function: +//! +//! ``` +//! use http::HeaderValue; +//! +//! let value = HeaderValue::from_static("text/html"); +//! assert_eq!(value.as_bytes(), b"text/html"); +//! ``` +//! +//! And header values can also be parsed like names: +//! +//! ``` +//! use http::HeaderValue; +//! +//! let value = "text/html"; +//! let value = value.parse::<HeaderValue>().unwrap(); +//! ``` +//! +//! Most HTTP requests and responses tend to come with more than one header, so +//! it's not too useful to just work with names and values only! This crate also +//! provides a `HeaderMap` type which is a specialized hash map for keys as +//! `HeaderName` and generic values. This type, like header names, is optimized +//! for common usage but should continue to scale with your needs over time. +//! +//! # URIs +//! +//! Each HTTP `Request` has an associated URI with it. This may just be a path +//! like `/index.html` but it could also be an absolute URL such as +//! `https://www.rust-lang.org/index.html`. A `URI` has a number of accessors to +//! interpret it: +//! +//! ``` +//! use http::Uri; +//! use http::uri::Scheme; +//! +//! let uri = "https://www.rust-lang.org/index.html".parse::<Uri>().unwrap(); +//! +//! assert_eq!(uri.scheme(), Some(&Scheme::HTTPS)); +//! assert_eq!(uri.host(), Some("www.rust-lang.org")); +//! assert_eq!(uri.path(), "/index.html"); +//! assert_eq!(uri.query(), None); +//! ``` + +#![deny(warnings, missing_docs, missing_debug_implementations)] + +#[cfg(test)] +#[macro_use] +extern crate doc_comment; + +#[cfg(test)] +doctest!("../README.md"); + +#[macro_use] +mod convert; + +pub mod header; +pub mod method; +pub mod request; +pub mod response; +pub mod status; +pub mod uri; +pub mod version; + +mod byte_str; +mod error; +mod extensions; + +pub use crate::error::{Error, Result}; +pub use crate::extensions::Extensions; +#[doc(no_inline)] +pub use crate::header::{HeaderMap, HeaderName, HeaderValue}; +pub use crate::method::Method; +pub use crate::request::Request; +pub use crate::response::Response; +pub use crate::status::StatusCode; +pub use crate::uri::Uri; +pub use crate::version::Version; + +fn _assert_types() { + fn assert_send<T: Send>() {} + fn assert_sync<T: Sync>() {} + + assert_send::<Request<()>>(); + assert_send::<Response<()>>(); + + assert_sync::<Request<()>>(); + assert_sync::<Response<()>>(); +} + +mod sealed { + /// Private trait to this crate to prevent traits from being implemented in + /// downstream crates. + pub trait Sealed {} +} |