28个版本 (11个重大变更)

0.12.2 2024年8月14日
0.12.0 2024年7月22日
0.10.2 2024年3月19日
0.3.0 2023年12月11日
0.2.3 2023年11月18日

#59 in HTTP服务器

Download history 368/week @ 2024-05-03 301/week @ 2024-05-10 264/week @ 2024-05-17 302/week @ 2024-05-24 283/week @ 2024-05-31 140/week @ 2024-06-07 166/week @ 2024-06-14 160/week @ 2024-06-21 252/week @ 2024-06-28 502/week @ 2024-07-05 182/week @ 2024-07-12 152/week @ 2024-07-19 135/week @ 2024-07-26 361/week @ 2024-08-02 160/week @ 2024-08-09 206/week @ 2024-08-16

每月873次下载
用于 stemma-soil-sensor-embass…

MIT 许可证

255KB
6.5K SLoC

picoserve

一个适用于裸机环境的异步无std HTTP服务器,深受axum启发。它是为embassy在Raspberry Pi Pico W上的使用而设计的,但应适用于其他嵌入式运行时和硬件。

特性

  • 不使用堆
  • 处理函数是接受零个或多个提取器作为参数的异步函数,并返回实现IntoResponse的某种东西
  • 使用serde进行查询和表单解析
  • JSON响应
  • 服务器端事件
  • Web套接字
  • 自动处理HEAD方法

缺点

  • 在版本0.*.*中,可能会有破坏性的API更改
  • 仅支持GET、POST和HEAD方法。
  • URL编码字符串,例如在查询和表单解析中,最大长度为1024。
  • 由于压力测试相对较少,建议不要直接将其暴露在互联网上,而是将其放置在nginx等代理后面,以充当安全层。
  • 某些序列化方法,例如DebugValue响应和JSON序列化,如果响应有效负载很大,可能会被调用多次。调用者必须确保在重复调用具有相同值的同一值时序列化输出的相同。
  • 框架不验证指定的响应体长度,即存储在"Content-Length"头中的值是否实际上是正文长度。

使用示例

tokio(用于测试目的)

use std::time::Duration;

use picoserve::routing::get;

#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
    let port = 8000;

    let app =
        std::rc::Rc::new(picoserve::Router::new().route("/", get(|| async { "Hello World" })));

    let config = picoserve::Config::new(picoserve::Timeouts {
        start_read_request: Some(Duration::from_secs(5)),
        read_request: Some(Duration::from_secs(1)),
        write: Some(Duration::from_secs(1)),
    })
    .keep_connection_alive();

    let socket = tokio::net::TcpListener::bind((std::net::Ipv4Addr::LOCALHOST, port)).await?;

    println!("https://127.0.0.1:{port}/");

    tokio::task::LocalSet::new()
        .run_until(async {
            loop {
                let (stream, remote_address) = socket.accept().await?;

                println!("Connection from {remote_address}");

                let app = app.clone();
                let config = config.clone();

                tokio::task::spawn_local(async move {
                    match picoserve::serve(&app, &config, &mut [0; 2048], stream).await {
                        Ok(handled_requests_count) => {
                            println!(
                                "{handled_requests_count} requests handled from {remote_address}"
                            )
                        }
                        Err(err) => println!("{err:?}"),
                    }
                });
            }
        })
        .await
}

依赖项

~2–11MB
~122K SLoC