Introducing Gotham 0.1

A flexible web framework that promotes stability, safety, security and speed.

Features

Built with Rust

Rust is a programming language that’s focused on safety, speed, and concurrency. It offers all the performance and control of a low-level language, but with the powerful abstractions of a high-level language.

Stability Focused

Gotham targets stable Rust. This will never change.

Gotham is also automatically tested against Rust beta and nightly.

No Garbage Collection

One of Rust’s key innovations is guaranteeing memory safety without requiring garbage collection. Gotham based applications automatically benefit from the predictability and performance of a system without garbage collection.

Statically Typed

Unlike many other web frameworks Gotham is statically typed ensuring your entire application is correctly expressed at compile time.

Async Everything

By leveraging Tokio, Gotham types are async out of the box.

Our async story is further enhanced by Hyper, a fast server that provides an elegant layer over stringly typed HTTP.

Blazingly Fast

Measure completed requests, including the 99th percentile, in µs.

Tour

A handler is a Rust function which generates a response to a HTTP request.

Handler
                      
pub fn greet(state: State, _req: Request) -> (State, Response) {
    let greeting = match GreetRequestPath::borrow_from(&state).name {
        Some(ref name) => format!("Hello, {}!\n", name),
        None => "Hello, world!\n".to_owned(),
    };

    let res = create_response(
        &state,
        StatusCode::Ok,
        Some((greeting.into_bytes(), mime::TEXT_PLAIN)),
    );

    (state, res)
}
                      
                    
HTTP Request
                      
$ curl http://localhost:7878/greet
Hello, world!
$ curl http://localhost:7878/greet/Rustaceans
Hello, Rustaceans!
                      
                    

Extractors parse request data into type-safe structures provided by your application.

PathExtractor
                      
#[derive(StateData, FromState, PathExtractor, StaticResponseExtender)]
pub struct ChallengeRequestPath {
    pub name: String,
}
                      
                    
QueryStringExtractor
                      
#[derive(StateData, FromState, QueryStringExtractor, StaticResponseExtender)]
pub struct ChallengeQueryString {
    pub count: Option<u8>,
}
                      
                    
Handler
                      
pub fn index(state: State, _req: Request) -> (State, Response) {
    let res = {
        let crp = ChallengeRequestPath::borrow_from(&state);
        let name = &crp.name;

        let cqs = ChallengeQueryString::borrow_from(&state);
        let count = cqs.count;

        let hello = match count {
            Some(count) => {
                format!(
                    "Hello, {}.\nIzzy Mandelbaum can lift {} kgs, so more weight than you!!\n",
                    name,
                    count + 1
                )
            }
            None => {
                format!(
                    "Hello, {}.\nIzzy Mandelbaum can lift more weight than you.\n",
                    name
                )
            }
        };

        create_response(
            &state,
            StatusCode::Ok,
            Some((hello.into_bytes(), mime::TEXT_PLAIN)),
        )
    };

    (state, res)
}
                      
                    

Middleware can add functionality to your application without duplicating code.

Using middleware
                      
// When defining a router, the middleware is added into a pipeline:
new_pipeline()
    .add(
        NewSessionMiddleware::default()
            .with_session_type::<Session>()
    )
// See our example app for a detailed example.
                      
                    
Handler
                      
pub fn index(state: State, _req: Request) -> (State, Response) {
    let response = {
        // A value of type `SessionData<Session>` is added to `state` by the middleware
        let session = SessionData::<Session>::borrow_from(&state);

        create_response(
            &state,
            StatusCode::Ok,
            Some((index_body(session.todo_list.clone()), mime::TEXT_HTML)),
        )

    };

    (state, response)
}
                      
                    

A Gotham application compiles to a standard Rust binary.

Main
                      
pub fn main() {
    let addr = "127.0.0.1:7878".parse().unwrap();

    let server = Http::new()
        .bind(&addr, NewHandlerService::new(router()))
        .unwrap();

    println!("Listening on http://{}", server.local_addr().unwrap());
    server.run().unwrap();
}
                      
                    
Running
                      
$ cargo run
   Compiling gotham-example-app v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 12.50 secs
     Running `target/debug/gotham_example_app`
Listening on http://127.0.0.1:7878
                      
                    

Community

Policies

Gotham is a young project that we want to create an energetic and respectful community around.

As a starting point we've adopted the following policies which we'd like your help in refining further.

These policies are in effect for any environment or tool that supports the Gotham project.

Help

Documentation

Chat

We collaborate via Gitter on the gotham-rs/gotham channel. Gotham specific chat and requests for help are both very welcome here.