8 个版本 (5 个破坏性更新)

0.5.0 2024年6月28日
0.4.0 2024年6月7日
0.3.0 2023年6月14日
0.2.2 2021年1月4日
0.0.0 2016年6月26日

#154 in 开发工具

Download history 119/week @ 2024-04-19 168/week @ 2024-04-26 145/week @ 2024-05-03 50/week @ 2024-05-10 7/week @ 2024-05-17 37/week @ 2024-05-24 41/week @ 2024-05-31 239/week @ 2024-06-07 141/week @ 2024-06-14 131/week @ 2024-06-21 275/week @ 2024-06-28 13/week @ 2024-07-05 76/week @ 2024-07-12 7/week @ 2024-07-19 43/week @ 2024-07-26 10/week @ 2024-08-02

每月下载量136
用于 pact_mock_server_cli

MIT 许可证

165KB
3.5K SLoC

webmachine-rust

将 Webmachine-Ruby (https://github.com/webmachine/webmachine-ruby) 移植到 Rust。

Build Status

webmachine-rust 是 webmachine 的 Ruby 版本的移植。它实现了一个有限状态机来处理 HTTP 协议,提供语义化的 HTTP 处理(基于 Webmachine 项目的图示)。它基本上是一个 HTTP 工具包,用于使用 Hyper rust 包构建友好的 HTTP 应用程序。

Webmachine-rust 与 Hyper 一起工作,位于 Hyper 处理器和您的应用程序代码之间。它提供了一个资源结构体,包含回调来处理在状态机对请求执行时所需的决策,以下序列。

REQUEST -> Hyper Handler -> WebmachineDispatcher -> WebmachineResource -> 您的应用程序代码 -> WebmachineResponse -> Hyper -> RESPONSE

特性

  • 为您处理内容协商、条件请求和响应代码的难点。
  • 提供了一个具有扩展点的资源结构体,让您描述有关特定资源的相关信息。

缺失的功能

目前,以下来自 webmachine-ruby 的功能尚未实现

  • 可视化调试器
  • 流式响应体

实现缺陷

此实现存在以下缺陷

  • 自动解码请求体和编码响应体。
  • 没有简单的机制来生成不同内容类型的体(例如 JSON 与 XML)。
  • 没有简单的机制来处理资源中的子路径。
  • 动态确定资源上允许的方法。

Hyper 入门

按照 Hyper crate 的入门文档设置您的服务器 Hyper 服务。您需要定义一个 WebmachineDispatcher,将资源路径映射到您的 webmachine 资源(WebmachineResource)。每个 WebmachineResource 定义了实现资源所需的所有回调(通过闭包)和值。

注意:本例使用 maplit crate 提供 btreemap 宏,并使用 log crate 的日志宏。

use webmachine_rust::*;
use webmachine_rust::context::*;
use webmachine_rust::headers::*;
use serde_json::{Value, json};
use std::io::Read;
use std::net::SocketAddr;
use std::convert::Infallible;
use std::sync::Arc;
use maplit::btreemap;
use tracing::error;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{body, Request};

async fn start_server() -> anyhow::Result<()> {
 // setup the dispatcher, which maps paths to resources. We wrap it in an Arc so we can
 // use it in the loop below.
 let dispatcher = Arc::new(WebmachineDispatcher {
   routes: btreemap!{
         "/myresource" => WebmachineResource {
           // Methods allowed on this resource
           allowed_methods: vec!["OPTIONS", "GET", "HEAD", "POST"],
           // if the resource exists callback
           resource_exists: callback(&|_, _| true),
           // callback to render the response for the resource
           render_response: callback(&|_, _| {
               let json_response = json!({
                  "data": [1, 2, 3, 4]
               });
               Some(json_response.to_string())
           }),
           // callback to process the post for the resource
           process_post: callback(&|_, _|  /* Handle the post here */ Ok(true) ),
           // default everything else
           .. WebmachineResource::default()
         }
     }
 });

 // Create a Hyper server that delegates to the dispatcher. See https://hyper.rs/guides/1/server/hello-world/
 let addr: SocketAddr = "0.0.0.0:8080".parse()?;
 let listener = TcpListener::bind(addr).await?;
 loop {
   let dispatcher = dispatcher.clone();
   let (stream, _) = listener.accept().await?;
   let io = TokioIo::new(stream);
   tokio::task::spawn(async move {
     if let Err(err) = http1::Builder::new()
       .serve_connection(io, service_fn(|req: Request<body::Incoming>| dispatcher.dispatch(req)))
       .await
     {
       error!("Error serving connection: {:?}", err);
     }
   });
 }
 Ok(())
}

示例实现

有关使用此 crate 的项目示例,请查看 Pact 参考实现中的 Pact Mock Server

依赖项

~7–14MB
~157K SLoC