Crate aitch[][src]

aitch is a simple, lightweight toolkit for building HTTP servers in safe, stable Rust.

It builds upon the http crate, and provides additional types for representing HTTP handlers, bodies and middlewares. It provides both hyper and tiny_http backends for running handlers, but aims to be agnostic of the HTTP server library.

It's inspired by the simplicity (and popularity) of Go's net/http package, which builds applications/middlewares as a series of nested Handlers.

Defining Handler functions

Handlers are typically defined as functions with the signature:

This example is not tested
Fn(http::Request<impl Body>, http::response::Builder) -> impl Responder

Both synchronous and asychronous handlers are defined using this same signature.

A Responder is anything that implements IntoFuture<Item = http::Response<impl Body>>, whose Error can be converted into a Box<Error>. This will often be a Result for synchronous handlers, or something implementing Future for asynchronous handlers.

For example, to define a simple sychronous handler as a function:

fn handler(_: http::Request<()>, mut resp: http::response::Builder) -> impl Responder {
    resp.body("Hello, world!".to_owned())
}

More complex Handlers using the Handler trait

Handlers aren't limited to functions - any type that implements the Handler trait can be used.

For an example of how to implement the Handler trait for a more complex type, see the provided SimpleRouter, which routes HTTP requests to one of many handlers, based on the path in the HTTP request.

Serving Requests

In order for a Handler to serve requests, it needs to be passed to a server which can process HTTP requests.

aitch comes with two server implementations:

  • aitch::servers::hyper::Server, which uses hyper to receive and process requests. As hyper can take full advantage of asynchronous I/O, this server backend can support streaming request/response bodies.
  • aitch::servers::tiny_http::Server, which uses tiny_http to receive and process requests. tiny_http uses a thread-pool to synchronously process each request, and the entire request body will be buffered before being past to the Handler - there is no support for streaming bodies.

The following example demonstrates passing a Handler function to aitch::servers::hyper::Server, which allows it to listen and respond to requests:

let addr = "127.0.0.1:3000".parse()?;
aitch::servers::hyper::Server::new(addr, handler)?.run()

aitch aims to be agnostic of the server technology, and it should be possible to add support for other servers in third-party crates. The source code of the two provided server implementations should demonstrate how to do this.

Request/Response Bodies

The http::Request<B> and http::Response<B> types from the http crate do not restrict the type of the body used in requests and bodies.

The Body trait is used by aitch to place some contraints on the body types used, so that handlers, middlewares and servers can make assumptions about how to deserialize it from the raw HTTP request, and how they should be serialized to the raw HTTP responses.

Writing Middlewares

In the context of aitch, a middleware is anything that takes one Handler and returns another (possibly modified) Handler.

The simplest middleware, which does nothing but return the provided Handler is written as:

fn noop_middleware<B: Body>(handler: impl Handler<B>) -> impl Handler<B> {
    handler
}

Middlewares may mutate the http::response::Builder before calling their wrapped handler, in order to modify the response that will be returned:

fn with_served_by<B: Body>(handler: impl Handler<B>) -> impl Handler<B> {
    move |req, mut resp: http::response::Builder| {
        resp.header("X-Served-By", "aitch");
        // Middleware authors should be aware that the wrapped handler is
        // under no obligation to use the provided `http::response::Builder`.
        handler.handle(req, resp)
    }
}

aitch provides some sample middlewares, which provide more detailed examples of how third-party applications can create their own middleware.

Modules

handlers

A collection of useful HTTP handlers.

middlewares

A collection of useful HTTP middlewares.

servers

Server back-ends which can be used to serve a handler.

Structs

Json

A wrapper, indicating a type should be automatically (de)serialized from/to a HTTP request/response body.

Traits

Body

A trait defining the types that can be used in HTTP requests and responses.

Handler

A trait indicating that the type can be used to handler to a HTTP request.

Responder

A Responder is any type which is returned from a request Handler.

Functions

box_handler

Creates a BoxedHandler from any Handler.

Type Definitions

BodyStream

A streaming body, which can be used in a HTTP request or response.

BoxedHandler

A Box<Handler> with all types erased.

BoxedResponse

Represents a future returning a HTTP response, with all types erased.

Error

A generic error type for aitch handlers and middlewares.

ResponseBuilder

A type alias for http::response::Builder.

Result

A type alias to make working with Result<T, aitch::Error> more convenient.