#![feature(slicing_syntax, box_syntax, old_orphan_check, old_impl_check)] #![allow(unstable)] #![deny(missing_docs)] #![deny(warnings)] #![experimental] //! # Hyper //! Hyper is a fast, modern HTTP implementation written in and for Rust. It //! is a low-level typesafe abstraction over raw HTTP, providing an elegant //! layer over "stringly-typed" HTTP. //! //! Hyper offers both an HTTP/S client an HTTP server which can be used to drive //! complex web applications written entirely in Rust. //! //! ## Internal Design //! //! Hyper is designed as a relatively low-level wrapper over raw HTTP. It should //! allow the implementation of higher-level abstractions with as little pain as //! possible, and should not irrevocably hide any information from its users. //! //! ### Common Functionality //! //! Functionality and code shared between the Server and Client implementations can //! be found in `src` directly - this includes `NetworkStream`s, `Method`s, //! `StatusCode`, and so on. //! //! #### Methods //! //! Methods are represented as a single `enum` to remain as simple as possible. //! Extension Methods are represented as raw `String`s. A method's safety and //! idempotence can be accessed using the `safe` and `idempotent` methods. //! //! #### StatusCode //! //! Status codes are also represented as a single, exhaustive, `enum`. This //! representation is efficient, typesafe, and ergonomic as it allows the use of //! `match` to disambiguate known status codes. //! //! #### Headers //! //! Hyper's header representation is likely the most complex API exposed by Hyper. //! //! Hyper's headers are an abstraction over an internal `HashMap` and provides a //! typesafe API for interacting with headers that does not rely on the use of //! "string-typing." //! //! Each HTTP header in Hyper has an associated type and implementation of the //! `Header` trait, which defines an HTTP headers name as a string, how to parse //! that header, and how to format that header. //! //! Headers are then parsed from the string representation lazily when the typed //! representation of a header is requested and formatted back into their string //! representation when headers are written back to the client. //! //! #### NetworkStream and NetworkAcceptor //! //! These are found in `src/net.rs` and define the interface that acceptors and //! streams must fulfill for them to be used within Hyper. They are by and large //! internal tools and you should only need to mess around with them if you want to //! mock or replace `TcpStream` and `TcpAcceptor`. //! //! ### Server //! //! Server-specific functionality, such as `Request` and `Response` //! representations, are found in in `src/server`. //! //! #### Handler + Server //! //! A `Handler` in Hyper accepts a `Request` and `Response`. This is where //! user-code can handle each connection. The server accepts connections in a //! task pool with a customizable number of threads, and passes the Request / //! Response to the handler. //! //! #### Request //! //! An incoming HTTP Request is represented as a struct containing //! a `Reader` over a `NetworkStream`, which represents the body, headers, a remote //! address, an HTTP version, and a `Method` - relatively standard stuff. //! //! `Request` implements `Reader` itself, meaning that you can ergonomically get //! the body out of a `Request` using standard `Reader` methods and helpers. //! //! #### Response //! //! An outgoing HTTP Response is also represented as a struct containing a `Writer` //! over a `NetworkStream` which represents the Response body in addition to //! standard items such as the `StatusCode` and HTTP version. `Response`'s `Writer` //! implementation provides a streaming interface for sending data over to the //! client. //! //! One of the traditional problems with representing outgoing HTTP Responses is //! tracking the write-status of the Response - have we written the status-line, //! the headers, the body, etc.? Hyper tracks this information statically using the //! type system and prevents you, using the type system, from writing headers after //! you have started writing to the body or vice versa. //! //! Hyper does this through a phantom type parameter in the definition of Response, //! which tracks whether you are allowed to write to the headers or the body. This //! phantom type can have two values `Fresh` or `Streaming`, with `Fresh` //! indicating that you can write the headers and `Streaming` indicating that you //! may write to the body, but not the headers. //! //! ### Client //! //! Client-specific functionality, such as `Request` and `Response` //! representations, are found in `src/client`. //! //! #### Request //! //! An outgoing HTTP Request is represented as a struct containing a `Writer` over //! a `NetworkStream` which represents the Request body in addition to the standard //! information such as headers and the request method. //! //! Outgoing Requests track their write-status in almost exactly the same way as //! outgoing HTTP Responses do on the Server, so we will defer to the explanation //! in the documentation for sever Response. //! //! Requests expose an efficient streaming interface instead of a builder pattern, //! but they also provide the needed interface for creating a builder pattern over //! the API exposed by core Hyper. //! //! #### Response //! //! Incoming HTTP Responses are represented as a struct containing a `Reader` over //! a `NetworkStream` and contain headers, a status, and an http version. They //! implement `Reader` and can be read to get the data out of a `Response`. //! extern crate "rustc-serialize" as serialize; extern crate time; extern crate url; extern crate openssl; #[macro_use] extern crate log; #[cfg(test)] extern crate test; extern crate "unsafe-any" as uany; extern crate cookie; extern crate mucell; pub use std::io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr, Port}; pub use mimewrapper::mime; pub use url::Url; pub use client::Client; pub use method::Method::{Get, Head, Post, Delete}; pub use status::StatusCode::{Ok, BadRequest, NotFound}; pub use server::Server; use std::error::{Error, FromError}; use std::io::IoError; use self::HttpError::{HttpMethodError, HttpUriError, HttpVersionError, HttpHeaderError, HttpStatusError, HttpIoError}; macro_rules! todo( ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(5, "TODO: {:?}", format_args!($($arg)*)) }) ); macro_rules! inspect( ($name:expr, $value:expr) => ({ let v = $value; debug!("inspect: {:?} = {:?}", $name, v); v }) ); #[cfg(test)] #[macro_use] mod mock; pub mod client; pub mod method; pub mod header; pub mod http; pub mod net; pub mod server; pub mod status; pub mod uri; pub mod version; mod mimewrapper { /// Re-exporting the mime crate, for convenience. extern crate mime; } /// Result type often returned from methods that can have `HttpError`s. pub type HttpResult = Result; /// A set of errors that can occur parsing HTTP streams. #[derive(Show, PartialEq, Clone)] pub enum HttpError { /// An invalid `Method`, such as `GE,T`. HttpMethodError, /// An invalid `RequestUri`, such as `exam ple.domain`. HttpUriError(url::ParseError), /// An invalid `HttpVersion`, such as `HTP/1.1` HttpVersionError, /// An invalid `Header`. HttpHeaderError, /// An invalid `Status`, such as `1337 ELITE`. HttpStatusError, /// An `IoError` that occured while trying to read or write to a network stream. HttpIoError(IoError), } impl Error for HttpError { fn description(&self) -> &str { match *self { HttpMethodError => "Invalid Method specified", HttpUriError(_) => "Invalid Request URI specified", HttpVersionError => "Invalid HTTP version specified", HttpHeaderError => "Invalid Header provided", HttpStatusError => "Invalid Status provided", HttpIoError(_) => "An IoError occurred while connecting to the specified network", } } fn cause(&self) -> Option<&Error> { match *self { HttpIoError(ref error) => Some(error as &Error), HttpUriError(ref error) => Some(error as &Error), _ => None, } } } impl FromError for HttpError { fn from_error(err: IoError) -> HttpError { HttpIoError(err) } } impl FromError for HttpError { fn from_error(err: url::ParseError) -> HttpError { HttpUriError(err) } } //FIXME: when Opt-in Built-in Types becomes a thing, we can force these structs //to be Send. For now, this has the compiler do a static check. fn _assert_send() { _assert_send::>(); _assert_send::(); }