3 个不稳定版本

0.2.0 2019年7月31日
0.1.1 2019年6月6日
0.1.0 2019年5月31日
0.0.0 2019年3月5日

#1282HTTP服务器

0BSD 许可证

81KB
768 代码行

Hyperdrive

crates.io docs.rs Build Status

此crate提供类似Rocket风格的声明式HTTP请求路由和守卫。它可以在同步和完全异步应用程序(使用hyper对futures 0.1的支持)中使用,并在稳定Rust上运行。

您可以使用属性,如#[post("/user/{id}/posts")]来声明Web应用程序的端点,此crate将生成根据方法和方法路径分发传入请求的代码。

请参阅变更日志以了解最新版本中发生了什么变化。

Rust版本策略

Hyperdrive支持最新的稳定Rust版本,以及之前的两个稳定版本。只要这3个Rust版本仍然受到支持,提升最低支持的Rust版本(MSRV)不被视为破坏性更改。

示例

此示例展示了如何使用Hyperdrive为简单的webservice定义路由以及如何启动一个hyper服务器,该服务器将使用用户提供的同步处理程序提供这些路由

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() {
    // Prepare a hyper server using Hyperdrive's `SyncService` adapter.
    // If you want to write an async handler, you could use `AsyncService` instead.
    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's make a login request to it
    let response = reqwest::Client::new()
        .post(&format!("http://127.0.0.1:{}/login", port))
        .body(r#"{ "email": "[email protected]", "password": "hunter2" }"#)
        .send()
        .unwrap();

    // This login request should succeed
    assert_eq!(response.status(), StatusCode::OK);
}

依赖项

~15MB
~285K SLoC