Tower Web — A new web framework for Rust

I previously announced Tower and mentioned that a web framework was in the works. It took longer than I had hoped (as it sometimes does with software), but today, I am opening up Tower Web.

Tower Web is an asynchronous HTTP web framework that focuses on removing boilerplate. It is built on top of Tokio, Hyper, and of course Tower. It works today on stable Rust.

Here is “hello world”.

Tower Web uses a macro based approach. The impl_web! macro looks at the impl blocks and generates the necessary glue code to serve HelloWorld as an HTTP service.

The @get("/") doc comment is meaningful. This tells Tower Web that GET requests to / should be mapped to the hello_world method. Tower Web opted to use doc comments as annotations to enable supporting stable Rust today. Once attribute macros land on the stable channel, Tower Web will switch to attribute macros.

This hello world example is cool, but it doesn’t illustrate where Tower Web really shines.

Decoupling HTTP and application logic

This example extracts a request path segment and uses that as part of the response. What is interesting is that the greet method is implemented without any special types. It just takes a String as the argument.

Tower Web uses convention over configuration. The convention is that the argument identifier will match the capture identifier. In this case, both the argument and capture are named name. Because of this, Tower Web knows that the name argument should be populated with the value captured from the path.

Because the method is written without any special types, testing also becomes very easy.

When it comes to more complicated types, such as JSON request bodies, Tower Web also has you covered.

The #[derive(Extract)] generates an extract implementation for the type. It uses Serde under the hood, so all the various Serde annotations work here too. When used as an argument named body, Tower Web will deserialize the request body into the struct. Once again, the method has been implemented without any HTTP specific types.

The following curl request will succeed:

curl --vv --request POST -H 'content-type: application/json' --data '{"foo":1,"bar":"baz"}' http://localhost:8080/data

Tower Web is able to do validation on the type as well. The foo field is defined to be numeric and required. Omitting it results in an HTTP 400, bad request, response.

Responding

In this example, we respond with a custom type. The resource method is also annotated with @content_type("json"). This indicates that MyData should be serialized using the JSON format.

Also note that MyData has an attribute: #[web(status = "201")]. This tells Tower Web to set the HTTP response status code to 201. There are a number of other ways to customize the response with #[derive(Response)] and these are documented in the API docs and examples.

Asynchronous

Note that impl Future is bound with Send. Tower Web uses Hyper to serve the application and Hyper requires the response future to be bound by Send.

Just a taste

Warp — the future of asynchronous web for Rust

The goal is to avoid fragmentation and rally behind a single crate. There is no need to duplicate effort and re-implement the world each time.

In a month or so, Tower Web will become a part of Warp. Warp will then provide both the filter based API and the macro API offered by Tower Web. This will let us focus on a single library.

Merging with Warp will also enable mixing and matching the various API styles. For example, you could build a single service using both filters and macros. Or, you could respond from a filter with a #[derive(Response)] struct.

In the short term, while I gather feedback from the initial release, feature development will happen in the Tower Web repository.

Acknowledgements

Conclusion

I do stuff. I say stuff. It's serious business.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store