4.6 KiB
Handy-Http Primitives
The Primitives library provides the foundational set of types and interfaces for Handy-Http. Most notably, the Primitives component defines the ServerHttpRequest and ServerHttpResponse structs, and the HttpRequestHandler interface. Together, these symbols form the basis for a common HTTP layer, loosely inspired by Java's Servlet specification. All other Handy-Http components build on top of Primitives' types to implement request handling, response writing, filtering, and all manner of other conveniences you'd expect in a web framework.
!!! info "Streams" Handy-Http makes extensive use of the streams library for low-level byte input and output operations. This library was also written by Andrew specifically for Handy-Http, and it'll be familiar to programmers coming from Java or other languages that have a stream concept.
In general, we *read* HTTP requests from an input stream, and *write* responses to an output stream. To allow for flexibility, the Primitives component only refers to streams using their object-oriented interface types, i.e. `InputStream!ubyte` and `OutputStream!ubyte`.
Requests
Whenever Handy-Http receives an HTTP request from a client, it will store that request content in a ServerHttpRequest which contains the client's address, HTTP method, requested URL, headers, query parameters, and an input stream for reading the request's body content, if available.
Responses
To respond to a client's HTTP request, you'll use a ServerHttpResponse, which allows you to provide a status and headers. Response body content is written to the response's output stream.
For your convenience the HttpStatus enum defines a list of every possible HTTP response status. Use these to set the response's status. Also, the ContentTypes enum defines some common Content-Type header values to use if you're returning a response body with a typical content type, like images, text, or JSON.
The HttpStatusException is an exception that can be thrown at any time during request processing, and if so, it's expected that the transport layer (see Transport) will gracefully set the indicated response status. You can use this as a quick means of escaping request processing if something goes wrong. However, due to the performance impacts associated with throwing and catching exceptions, try to avoid this for high-traffic, high-performance request processing.
Request Handlers
We combine the request and response types into one functional interface, HttpRequestHandler, which is defined as:
interface HttpRequestHandler {
void handle(ref ServerHttpRequest request, ref ServerHttpResponse response);
}
The job of a request handler is to read in an HTTP request, do some logic, and write to the given response. With the use of streams for I/O abstraction, request handlers are the basis for all of Handy-Http, and to achieve more complex behavior, one can simply extend or wrap another request handler.
Other Utilities
In addition to the basic HTTP types, the Primitives component provides some small utility types. These are generally used in the ServerHttpRequest and ServerHttpResponse structs to make it easier to work with the data, but you are free to use them elsewhere in your code.
Optional
The Optional type is a simplified version of D's standard library Nullable, that provides some convenience methods for mapping the underlying data if it's present.
Multi-Value Map
The MultiValueMap type defines a multi-valued mapping, where a key is mapped to an array of one or more values. The map is sorted by keys for O(log(n)) lookup and retrieval, and O(n*log(n)) insertion.
This is used internally for the ServerHttpResponse.headers property, to provide a simple interface for adding headers to a response before flushing it.