From 939de07ae6b710f39ca3bc481d8b8e06f277e59c Mon Sep 17 00:00:00 2001 From: Jonathan Reem Date: Thu, 18 Sep 2014 20:17:27 -0700 Subject: [PATCH] (doc) Documented the internal design of Hyper. This includes a rationale and description of the overall design of Hyper as well as providing a guide to understanding and navigating the source. --- README.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/README.md b/README.md index 711d24a3..f983b397 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,113 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 3 measured \* No science was harmed in the making of this benchmark. +## Internal Design + +Hyper is designed as a relatively low-level wrapped 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`. + +#### 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`. ## License [MIT](./LICENSE) +