cataclysm 0.2.0-alpha.0

A simple http framework
Documentation
# Cataclysm. A simple rust http server


**Work in progress**: The work is completely unusable in its current state, but updates will come soon until a full HTTP/1.1 server is functional. This legend will be removed when such a state is reached.

Cataclysm is an http framework influenced by [actix-web](https://actix.rs/), and built over [tokio](https://tokio.rs/). A minimal working example is the following

```Rust
extern crate cataclysm;

use cataclysm::{Server, Path, http::{Response, Method}};

async fn hello() -> Response {
    Response::ok().body("hello")
}

#[tokio::main]

async fn main() {
    let server = Server::builder(
        Path::new("/hello").with(Method::Get.to(hello))
    ).build();

    server.run("localhost:8000").await.unwrap();
}
```

## Closures as callbacks


Until `async closures` become stable, the option to pass closures as a path handler is with a closure that returns an async block

```Rust
let server = Server::builder(
    Path::new("/data").with(Method::Post.to( |data: Vec<u8>| async {
        // Do something with data
        // ...
        Response::ok().body("worked!")
    }))
).build();
```

## Extractors


Some data can be retrieved from an http request by just adding arguments to the callback, with types that implement the `Extractor` trait. The default implementation list is the following

* `String`: Tries to extract the body as a valid utf-8 string. Returns Bad-Request if the operation fails
* `Vec<u8>`: Returns the content of the `http` call as a stream of bytes
* `Request`: Returns the request for a bit more control within the callback

## Layers


Cataclysm allows for layer handling, a.k.a. middleware.

```Rust
let path = Path::new("/hello")
    .with(Method::Get.to(world))
    .layer(|req: Request, pipeline: Box<Pipeline>| async {
        // Example of timing layer / middleware
        let now = std::time::Instant::now();
        // Execute the deeper layers of the pipeline
        let response = pipeline.execute(req).await;
        // Measure and print time
        let elapsed = now.elapsed().as_nanos();
        info!("Process time: {} ns", elapsed);
        // We return the request for further possible processing.
        request
}.boxed()).nested(Path::new("hola").with(Method::Delete.to(hello)));
```

As seen in the example, layer functions receive a `Request` and a boxed `Pipeline` enum. The `Pipeline` enum contains a nested structure of futures (the layers + the core handler), and has the `execute` to simplify things a bit. This function must return a `Pin<Box<_>>` future, so either use the `boxed` method from the `FutureExt` trait from the `futures` crate, or wrap it manually.