如何在Actix-web 3.3.2版本中正确实现类似SayHi的简单中间件
Actix-web 3.3.2 版本可用的 SayHi 中间件实现
核心改动说明
原有文档示例是针对更早的Actix-web 2.x版本编写,3.x版本中Transform trait新增了第二个泛型参数用于指定请求类型,补上该参数即可解决编译报错。
完整可运行代码
1. Cargo.toml 依赖配置
[dependencies] actix-web = "3.3.2" actix-service = "1.0.6" futures = "0.3"
2. 中间件实现代码
use std::pin::Pin; use std::task::{Context, Poll}; use actix_service::{Service, Transform}; use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error}; use futures::future::{ok, Ready}; use futures::Future; pub struct SayHi; // 补全Transform的第二个泛型参数ServiceRequest即可解决模板参数缺失报错 impl<S, B> Transform<S, ServiceRequest> for SayHi where S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Request = ServiceRequest; type Response = ServiceResponse<B>; type Error = Error; type InitError = (); type Transform = SayHiMiddleware<S>; type Future = Ready<Result<Self::Transform, Self::InitError>>; fn new_transform(&self, service: S) -> Self::Future { ok(SayHiMiddleware { service }) } } pub struct SayHiMiddleware<S> { service: S, } impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S> where S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Request = ServiceRequest; type Response = ServiceResponse<B>; type Error = Error; type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.poll_ready(cx) } fn call(&mut self, req: ServiceRequest) -> Self::Future { println!("Hi from start. You requested: {}", req.path()); let fut = self.service.call(req); Box::pin(async move { let res = fut.await?; println!("Hi from response"); Ok(res) }) } }
3. 中间件挂载示例
use actix_web::{App, HttpServer, web}; async fn index() -> &'static str { "Hello World" } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // 挂载自定义中间件 .wrap(SayHi) .route("/", web::get().to(index)) }) .bind(("127.0.0.1", 8080))? .run() .await }
运行服务后访问本地8080端口即可在控制台看到中间件打印的日志。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

