【问题标题】:How do I pass App data to service route handler function in actix-web when using function decorations?使用函数装饰时,如何将 App 数据传递给 actix-web 中的服务路由处理程序函数?
【发布时间】:2019-10-18 15:30:53
【问题描述】:

我在文档中找到了如何创建全局状态的示例,该状态受 Mutex 保护,在处理线程之间共享,可供所有路由处理程序使用。完美的!但是,我更喜欢使用附加到我的函数的属性来连接我的路由处理程序。我不知道使用属性函数并传入全局状态的语法(如果允许)。

这是来自 https://docs.rs/actix-web/1.0.2/actix_web/web/struct.Data.html 的 actix-web 文档中的示例

use std::sync::Mutex;
use actix_web::{web, App};

struct MyData {
    counter: usize,
}

/// Use `Data<T>` extractor to access data in handler.
fn index(data: web::Data<Mutex<MyData>>) {
    let mut data = data.lock().unwrap();
    data.counter += 1;
}

fn main() {
    let data = web::Data::new(Mutex::new(MyData{ counter: 0 }));

    let app = App::new()
        // Store `MyData` in application storage.
        .register_data(data.clone())
        .service(
            web::resource("/index.html").route(
                web::get().to(index)));
}

注意名为 index 的路由处理程序是如何被传递给 web::Data 的。

现在这里是我的代码的一些 sn-ps。

use actix_web::{get, App, HttpResponse, HttpServer, Responder};
pub mod request;
pub mod routes;

const SERVICE_NAME : &str = "Shy Rules Engine";
const SERVICE_VERSION : &str  = "0.1";

#[get("/")]
fn index() -> impl Responder {
    HttpResponse::Ok().body(format!("{} version {}", SERVICE_NAME, SERVICE_VERSION))
}

mod expression_execute {

  #[post("/expression/execute")]
  fn route(req: web::Json<ExpressionExecuteRequest>) -> HttpResponse {

    // ... lots of code omitted ...

    if response.has_error() {
        HttpResponse::Ok().json(response)
    }
    else {
        HttpResponse::BadRequest().json(response)
    }
  }

}

pub fn shy_service(ip : &str, port : &str) {
    HttpServer::new(|| {
        App::new()
            .service(index)
            .service(expression_execute::route)
    })
    .bind(format!("{}:{}", ip, port))
    .unwrap()
    .run()
    .unwrap();
}

注意我是如何调用方法 App::service 来连接我的路由处理程序的。

还要注意我的路由处理程序如何没有接收到全局状态(因为我还没有将它添加到我的应用程序中)。如果我使用与使用register_data 的文档类似的模式来创建全局应用程序数据,我将对我的方法签名、getpost 属性以及其他任何内容进行哪些更改,以便我可以将该全局状态传递给处理程序?

还是不能使用getpost 属性来访问全局状态?

【问题讨论】:

  • 是什么阻止您在第二个示例中使用与第一个示例相同的 Data&lt;T&gt; 提取器?
  • 没有什么能阻止我使用流利的接口而不是向方法添加属性。但是,我和我的同事熟悉使用 Express 和 node.js 和 C# .Net 核心中使用属性的类似工具,并且这种风格更自然且更易于阅读(在我看来)。它是自我记录的,通知读者该函数是一个路由处理程序,并简明扼要地告诉他们它处理什么路由。
  • 不,我的意思是同时使用Data&lt;T&gt; 提取器和get 属性。看我的回答。

标签: rust global-variables actix-web


【解决方案1】:

你列出的两种情况确实没有太大区别:

//# actix-web = "1.0.8"
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use std::sync::Mutex;

const SERVICE_NAME : &str = "Shy Rules Engine";
const SERVICE_VERSION : &str  = "0.1";

struct MyData {
    counter: usize,
}

#[get("/")]
fn index(data: web::Data<Mutex<MyData>>) -> impl Responder {
    let mut data = data.lock().unwrap();
    data.counter += 1;
    println!("Endpoint visited: {}", data.counter);
    HttpResponse::Ok().body(format!("{} version {}", SERVICE_NAME, SERVICE_VERSION))
}

pub fn shy_service(ip : &str, port : &str) {
    let data = web::Data::new(Mutex::new(MyData{ counter: 0 }));

    HttpServer::new(move || {
        App::new()
            .register_data(data.clone())
            .service(index)
    })
    .bind(format!("{}:{}", ip, port))
    .unwrap()
    .run()
    .unwrap();
}

fn main() {
    shy_service("127.0.0.1", "8080");
}

您可以通过简单的curl http 端点来验证它是否有效。对于multiple extractors,您必须使用元组:

    #[post("/expression/execute")]
    fn route((req, data): (web::Json<ExpressionExecuteRequest>, web::Data<Mutex<MyData>>)) -> HttpResponse {
        unimplemented!()
    }

【讨论】:

  • 谢谢!我有一个困惑。我知道 Rust 没有方法重载。为什么在我的原始代码中,我将一个函数传递给具有一个方法签名的 App::service 方法,而您却向它传递了一个具有不同签名的函数,并添加了应用程序数据?
  • @PaulChernoch get 属性只是表达web::resource(...).route(web::get().to(...)) 的一种方便方式。 actix_web::Resource.to 采用 trait Factory 类型的处理程序。深入actix-web 源代码,可以看到为Fn()Fn(tuple) 实现的特征Factory 不超过10 个元素。那应该回答你的问题。
  • 谢谢。我尝试在源代码中查找,但不知道在哪里查找!
  • 值得注意的是,在 version 2.0.0 在 actix-web 中 register_data 被重命名为 app_data
猜你喜欢
  • 2021-08-06
  • 2010-12-30
  • 2016-01-16
  • 2021-11-15
  • 2016-02-14
  • 2021-11-21
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
相关资源
最近更新 更多