actix-web app_data 在请求处理程序中总是 None

actix-web app_data is always None in request handler

我想在配置 Actix http 服务器时注册应用程序级数据,但是当我尝试使用 HttpRequest::app_data() 访问请求处理程序中的数据时,我总是得到 None。下面的代码在 expect 语句的 index 请求处理程序中发生恐慌。 但是,如果我使用 String 而不是我的 TestData 结构,它确实有效。

我做错了什么?

我的cargo.toml:

[...]

[dependencies]
actix-web = "3.0"
log = "0.4"
env_logger = "0.9"

我的代码:

use actix_web::{middleware, web, HttpRequest, Result, Responder, HttpResponse};
use actix_web::{App, HttpServer};
use std::sync::Arc;
#[macro_use]
extern crate log;
extern crate env_logger;


struct TestData {
  host: String
}

pub async fn index(req: HttpRequest) -> impl Responder {
  let td: &TestData = req.app_data().expect("Test data missing in request handler.");
  td.host.clone()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
  std::env::set_var("RUST_LOG", 
                    format!("actix_server={log_level},actix_web={log_level}", 
                            log_level="DEBUG"));
  env_logger::init();

  let server_data = web::Data::new(
    TestData {
      host: "Dadada".to_string(),
    }
  );

  HttpServer::new(move || {
     App::new()
      .app_data(server_data.clone())
      .route("/", web::get().to(index))
      .wrap(middleware::Logger::default())
  })
  .bind("127.0.0.1:8080")?
  .run()
  .await
}

您需要使用 turbo fish 语法将 Data<T> 类型指定为 app_data

pub async fn index(req: HttpRequest) -> impl Responder {
  let td: &TestData = req.app_data::<web::Data<TestData>>().expect("Test data missing in request handler.");

  td.host.clone()
}

如果您查看 HttpRequest::app_data 定义,您会发现 app_data 需要此信息来消除 get 调用

的歧义
pub fn app_data<T: 'static>(&self) -> Option<&T> {
        for container in self.0.app_data.iter().rev() {
            //Used here ------------------------\/
            if let Some(data) = container.get::<T>() {
                return Some(data);
            }
        }

        None
}

如果你只给编译器td类型(td: &TestData)。应用强制,编译器将推断出 T 遵守 T: 'static 绑定,但它不会是您想要的 T (web::Data<TestData>)。