Hyperdrive
This crate provides Rocket-style declarative HTTP request routing and guarding.
It can be used in both synchronous and fully async apps (using hyper's support
for futures 0.1) and works on stable Rust.
You can declare the endpoints of your web application using attributes like
#[post("/user/{id}/posts")]
, and this crate will generate code that dispatches
incoming requests depending on the method and path.
Please refer to the changelog to see what changed in the last
releases.
Rust Version Policy
Hyperdrive supports the latest stable Rust release, as well as the 2 stable
releases before that. As long as these 3 Rust versions are still supported,
bumping the minimum supported Rust version (MSRV) is not considered a breaking
change.
Example
This example shows how to use Hyperdrive to define routes for a simple
webservice and how to spin up a hyper server that will serve these routes with a
user-provided sync handler:
use hyperdrive::{FromRequest, body::Json, service::SyncService};
use hyper::{Server, Body};
use http::{Response, StatusCode};
use futures::prelude::*;
use serde::Deserialize;
#[derive(FromRequest)]
enum Route {
#[get("/")]
Index,
#[get("/users/{id}")]
User {
id: u32,
},
#[post("/login")]
Login {
#[body]
data: Json<Login>,
},
}
#[derive(Deserialize)]
struct Login {
email: String,
password: String,
}
fn main() {
let srv = Server::bind(&"127.0.0.1:0".parse().unwrap())
.serve(SyncService::new(|route: Route, _| {
match route {
Route::Index => {
Response::new(Body::from("Hello World!"))
}
Route::User { id } => {
Response::new(Body::from(format!("User #{}", id)))
}
Route::Login { data } => {
if data.password == "hunter2" {
Response::new(Body::from(format!("Welcome, {}!", data.email)))
} else {
Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(Body::from("Invalid username or password"))
.expect("building response failed")
}
}
}
}));
let port = srv.local_addr().port();
std::thread::spawn(move || tokio::run(srv.map_err(|e| {
panic!("unexpected error: {}", e);
})));
let response = reqwest::Client::new()
.post(&format!("http://127.0.0.1:{}/login", port))
.body(r#"{ "email": "oof@example.com", "password": "hunter2" }"#)
.send()
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}