1 个不稳定版本

0.1.0 2022年5月31日

#84 in #state-machine

MIT 许可证

155KB
3.5K SLoC

ux-webmachine

Rust 中的异步 Web 机器

https://github.com/uglyog/webmachine-rust.git 的分支

Webmachine-Ruby (https://github.com/webmachine/webmachine-ruby) 的 Rust 版本。

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

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

请求 -> Hyper 处理程序 -> Webmachine 分发器 -> Webmachine 资源 -> 您的应用程序代码 -> Webmachine 响应 -> Hyper -> 响应

特性

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

未实现的功能

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

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

实现缺陷

此实现有以下缺陷:

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

开始使用 Hyper

遵循 Hyper 包的入门文档来为您的服务器设置 Hyper 服务。您需要定义一个 Webmachine 分发器,该分发器将资源路径映射到您的 webmachine 资源(WebmachineResource)。每个 WebmachineResource 定义了实现资源所需的回调(通过闭包)和值。Webmachine 分发器实现了 Hyper Service 特性,因此您可以将它传递给 make_service_fn

注意:此示例使用 maplit 包提供 btreemap 宏和 log 包提供日志宏。

use hyper::server::Server;
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 hyper::service::make_service_fn;
use std::convert::Infallible;

// setup the dispatcher, which maps paths to resources. The requirement of make_service_fn is
// that it has a static lifetime
fn dispatcher() -> WebmachineDispatcher<'static> {
  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()
         }
     }
  }
}

async fn start_server() -> Result<(), String> {
  // Create a Hyper server that delegates to the dispatcher
  let addr = "0.0.0.0:8080".parse().unwrap();
  let make_svc = make_service_fn(|_| async { Ok::<_, Infallible>(dispatcher()) });
  match Server::try_bind(&addr) {
    Ok(server) => {
      // start the actual server
      server.serve(make_svc).await;
      Ok(())
    },
    Err(err) => {
      error!("could not start server: {}", err);
      Err(format!("could not start server: {}", err))
    }
  }
}

示例实现

以下是一个使用此crate的项目示例:请查看Pact参考实现中的Pact Mock Server

依赖项

约13–24MB
约366K SLoC