Announcing Gotham 0.3

First of all, hello there! This is the first announcement after the call for maintainers back in summer, and includes the efforts of several new faces:

Together, as well as input from the original authors @bradleybeddoes and @smangelsdorf, we are the new maintainers of the Gotham project. Today we’re excited to announce the release of Gotham 0.3, which follows the evolution of the broader Rust ecosystem.

What’s in Gotham 0.3

Following along with the changes in libraries such as tokio and hyper, along with the release of the new http crate, Gotham has changed fairly significantly in this release, in terms of both public API and usability.

Some broad highlights of this release include:

In the sections below, we’ll cover some of the more interesting features.

Ecosystem Updates

The 0.3 update has a heavy focus on adopting the changes in the broader Rust ecosystem, beginning with the adoption of the new tokio crate. This was contributed by @whitfin and had the added advantage of removing the only platform-specific code in Gotham. It also opened up several new APIs to control Gotham startup - such as thread count, executor, etc.

In addition Gotham 0.3 upgrades Hyper to 0.12 and adopts the new http crate, to keep Gotham up to date with the latest performance improvements and maintain a familiar API signature. This is due to a huge effort from @nyarly to adopt the new APIs internally, whilst keeping the impact to the Gotham API minimal.

Of course, aside from this, all dependencies of Gotham have been updated to their latest and greatest to avoid any potential bugs which might have been fixed since the last release.

Shorthand Responses

Gotham enables you to return a response through the use of the IntoResponse trait. In Gotham 0.3, this trait is implemented for some shorthand structures to enable easier return handling without having to construct a response. Here is a simple example:

const HELLO_WORLD: &'static str = "Hello, world!";

pub fn say_hello(state: State) -> (State, &'static str) {
    (state, HELLO_WORLD)
}

pub fn main() {
    gotham::start("127.0.0.1:7878", || Ok(say_hello))
}

This is possible as there is a blanket conversion for types implementing Into<Body> for Hyper. As &'static str is one such type, the conversion is automatic. Other basic types are also included, such as Bytes, String and Vec<u8> - making it possible to shorthand many reponses.

Taking it a little further, you can also control the status code and mime type of the response created, using Tuple structures:

(mime::Mime, Into<Body>)
(hyper::StatusCode, mime::Mime, Into<Body>)

This allows for a different style when defining requests. The old create_response helpers are still around though; so if you don’t like this syntax you can stick with the old.

Async Static File Serving

Mentioned as part of the 0.2 announcement, the ability to asynchronously serve static assets is very much something that has been requested to be available as part of Gotham. The 0.3 release includes initial support for this, courtesy of @colinbankier, via a simple API. Below are a few examples of exposing static assets:

build_simple_router(|route| {
    // You can use `to_file` on a route to expose a single asset:
    route.get("/").to_file("assets/index.html");

    // Alternatively, you can use `to_dir` to expose a directory of assets:
    route.get("/static").to_dir("assets");

    // Finally, you can customize options for compression, cache control, etc:
    route.get("/static").to_dir(
        FileOptions::new("assets")
            .with_cache_control("no-cache")
            .with_gzip(true)
            .build(),
    );
});

The structure of this API makes it extremely quick to implement a static site using Gotham. The snippet below shows a complete example of serving a static site from the assets directory using Gotham to serve the requests.

extern crate gotham;

use gotham::router::builder::*;

pub fn main() {
    gotham::start("127.0.0.1:7878", build_simple_router(|route| {
        route.get("/*").to_dir("assets");
    }))
}

We think this is a great improvement for those looking at Gotham for static sites!

Shared State Middlewares

A common question we often see is how to share state across requests. Whilst this has been possible via the use of middleware for a long time, it’s not always obvious exactly how to go about it - and it’s definitely a lot of boilerplate for something so simple. Contributed by @whitfin, Gotham 0.3 includes a new built-in middleware to offer shared state without having to bind it yourself. Below is an example of mutable state across requests, used to keep track of the number of requests the server has received. Note that dependencies and use clauses have been omitted for brevity:

/// Request counter, used to track the number of requests made.
///
/// Due to being shared across many worker threads, the internal counter
/// is bound inside an `Arc` (to enable sharing) and a `Mutex` (to enable
/// modification from multiple threads safely).
///
/// This struct must implement `Clone` and `StateData` to be applicable
/// for use with the `StateMiddleware`, and be shared via `Middleware`.
#[derive(Clone, StateData)]
struct RequestCounter {
    inner: Arc<Mutex<usize>>,
}

/// Counter implementation.
impl RequestCounter {
    /// Creates a new request counter, setting the base state to `0`.
    fn new() -> Self {
        Self {
            inner: Arc::new(Mutex::new(0)),
        }
    }

    /// Increments the internal counter state by `1`, and returns the
    /// new request counter as an atomic operation.
    fn incr(&self) -> usize {
        let mut w = self.inner.lock().unwrap();
        *w += 1;
        *w
    }
}

/// Basic `Handler` to say hello and return the current request count.
///
/// The request counter is shared via the state, so we can safely
/// borrow one from the provided state. As the counter uses locks
/// internally, we don't have to borrow a mutable reference either!
fn say_hello(state: State) -> (State, Response<Body>) {
    let message = {
        // borrow a reference to the counter from the state
        let counter = RequestCounter::borrow_from(&state);

        // create our message, incrementing our request counter
        format!("Hello from request #{}!\n", counter.incr())
    };

    // create the response
    let body = (message, mime::TEXT_PLAIN);
    let res = create_response(&state, StatusCode::OK, body);

    // done!
    (state, res)
}

/// Start a server and call the `Handler` we've defined above
/// for each `Request` we receive.
pub fn main() {
    // create our state middleware to share the counter
    let middleware = StateMiddleware::new(RequestCounter::new());

    // create a middleware pipeline from our middleware
    let pipeline = single_middleware(middleware);

    // construct a basic chain from our pipeline
    let (chain, pipelines) = single_pipeline(pipeline);

    // build a router with the chain & pipeline
    gotham::start("127.0.0.1:7878", build_router(chain, pipelines, |route| {
        route.get("/").to(say_hello);
    }))
}

Although this example looks quite large due to completeness, the relevant part to look at here is the StateMiddleware used inside main() to attach the RequestCounter as a middleware component. After this is configured you can easily borrow your counter (via RequestCounter::borrow_from(&state)) in any of your handlers and modify using the safety guarantees you’re used to.

Due to the routing API Gotham offers, it’s also possible to attach different states to different parts of your router to offer isolation across handlers. It should also be noted that you can attach multiple StateMiddleware to a single router, as long as the internal type (in this case RequestCounter) is unique.

Customized Startup

In Gotham 0.2 a server would automatically start on a predetermined number of threads, and would use a runtime entirely controlled by Gotham. Although this is typically the desired outcome, Gotham 0.3 introduces a few more APIs to control the server startup:

// Same as previous; uses default threads + runtime
gotham::start("127.0.0.1:7878", router());

// Allows control of thread counts; in this case a single thread
gotham::start_with_num_threads("127.0.0.1:7878", router(), 1);

// Allows control of the `TaskExecutor` used
gotham::start_on_executor("127.0.0.1:7878", executor());

// Returns a `Future` to spawn a Gotham server
gotham::init_server("127.0.0.1:7878", router());

Each of these APIs are just delegates to each other so there’s little maintenance overhead to offering them, but they provide a little extra control over the Gotham service. A good example of this was contributed by @im-0, who used init_server to implement a graceful shutdown for their application by using a select and a shutdown signal from tokio_signal.

A Note from the Maintainers

Although Gotham’s call for maintainers has been answered, please get in touch if you’re interested in contributing! We’re always interested in hearing new ideas and potential improvements to Gotham, especially those based on a 0.4 timeline. The 0.4 roadmap is still being figured out, so feel free to let us know your ideas.

We’d like to say thank you to the developers of our dependencies, the Rust language team themselves, and of course everybody who was involved in the 0.3 release - whether it be a new feature, an example or filing an issue, we couldn’t have done this without you.

The State of Gotham

Update (2018-06-04): The call for maintainers has been answered. Stay tuned.


When we set out to build Gotham, we had some main ideas that helped to shape it:

We’re excited about the framework we’ve built and the ideas we’ve put into it, but have paused to consider Gotham’s present and future position and want to share these thoughts with the community.

Major changes in the ecosystem

The current state of the web ecosystem in Rust is one of flux. There are some major efforts underway which will improve the future of both web and asynchronous applications (in no particular order):

Gotham is at a point now where everything is back on the table, including the design choices based on what was stable in Rust at the time we started Gotham in early 2017.

A call for maintainers

In recent months, development activity in Gotham has decreased. There are two major reasons that we’ve been less active as maintainers:

The second of these points is sufficiently demanding that we don’t have enough time to maintain Gotham as a serious contender in the Rust web framework arena.

We’d like to “pass the torch” to some new maintainer(s) who are willing to give Gotham the attention it deserves. If that’s you, please reach out to one of us via Gitter or email (@bradleybeddoes’ and @smangelsdorf’s email addresses are in the project’s Git history).

What’s next for Gotham?

Gotham, as it stands, isn’t going away. The repositories, crates and chat channel will remain. We’ll continue accepting security fixes and releasing patch versions if necessary, until we determine what’s next.

Feature contributions are still welcome, but may be delayed until a current or future maintainer has time to consider its relevance, impact on the wider framework, and the contribution itself.

Beyond that, it’s up to the next maintainer(s) to set the next priorities. We’re happy to provide our own thoughts on what that should be.

Bradley and Shaun

Gotham 0.2

Since the first release of the Gotham web framework in August 2017, we’ve been excitedly watching the community grow and get involved in the project. Today we’re pleased to announce the release of version 0.2, which includes new features and refinements identified by the community as well as some from our own wishlist.

Some highlights from version 0.2, out of the 99 issues and PRs that we’ve closed in the last 6 months:

Our thanks to everybody involved in the Gotham community by asking questions, providing feedback, and opening issues and pull requests. Anyone who’d like to get involved should come join us on Gitter or GitHub.

We’ve started adding some issues to the 0.3 roadmap, to get an idea of what we’d like to tackle next. Some of the noteworthy ones on our list so far:

You can find out more about the Gotham web framework at https://gotham.rs.

We’d again like to say a sincere thank you to the developers and communities of all our dependencies, and the Rust language. We’re excited for what 2018 will bring to the Rust ecosystem.

Bradley and Shaun

Announcing Gotham

For the last eight months, we’ve been hard at work on a project that we’re thrilled to be able to share with the wider Rust community.

We know it as Gotham and today we’re releasing 0.1.

Gotham is a flexible web framework that does not sacrifice safety, security or speed. The Gotham core team loves many of the elegant concepts that are found in dynamically typed web application frameworks, such as Rails/Phoenix/Django and aspire to achieve them with the type and memory safety guarantees provided by Rust.

Gotham is stability focused. With our release of Gotham 0.1, we’re compatible with Rust stable and every future release of Gotham will maintain that contract. Naturally, we build on beta and nightly as well so if you’re on the bleeding edge Gotham is good to go.

Gotham leverages async extensively thanks to the Tokio project and is further enhanced by being built directly on top of async Hyper. Completing web requests in µs with almost non-existent memory footprints is still taking some getting used to.

We wanted to get Gotham in the hands of the Rust community early with regular smaller iterations to follow. The Gotham 0.1 release includes the following features:

There are some important features still to be built and we hope that the community will help us define even more. Right now our roadmap includes:

You can find out more about Gotham at https://gotham.rs. We look forward to welcoming you into the Gotham community.

Finally, we’d like to say a very sincere thank you to the developers and communities of every dependency we’ve built Gotham on top of, including of course, Rust itself. Your work is amazing and we could not have gotten here without it. We look forward to working with you all in the future.

Bradley and Shaun

Gotham web framework RSS feed