2025-2-6-后端FAQ
FAQ[常见问题]
Middleware
使用Rust开发 Actix 需要使用中间件
中间件处理有两个步骤。 1.中间件初始化,中间件工厂被调用 链中的下一个服务作为参数。 中间件的调用方法通过正常请求被调用。
1 | use std::future::{ready, Ready}; |
这里出现了一些比较高级的技巧
middleware factory 中间件工厂
首先是
1 | where |
这个 where 字句实现了类型约束:
S 必须是一个实现了 Service trait 的类型,且该服务处理的是 ServiceRequest 类型的请求,返回的是 ServiceResponse<B> 类型的响应,错误类型是 Error。
这是一个生命周期约束,表明 S::Future 的生命周期是 'static,即返回的 Future 不会持有任何短生命周期的引用。
这是一个生命周期约束,表明响应体的类型 B 必须是 'static,即 B 的生命周期是静态的,不依赖于任何局部变量或临时引用。
下面代码继续,定义了类型关联。(太高级了)
1 | type Response = ServiceResponse<B>; |
以上内容
Response 类型指定了中间件工厂将会返回的响应类型
ServiceResponse<B>。它表示的是中间件最终生成的响应
Error 类型指定了服务中可能出现的错误类型:通用类型
InitError 类型表示初始化中间件时可能发生的错误类型
- 这里使用
()作为初始化错误类型,表示初始化时没有错误
Transform 类型指定了中间件的类型
SayHiMiddleware<S>。即这个中间件会处理请求,类型参数S表示它会接收一个服务,并且是ServiceRequest类型的请求和ServiceResponse<B>类型的响应。
Future 类型表示中间件工厂的异步执行结果
Ready,意味着这个返回值是一个立即完成的Future,它包装了一个Result<Self::Transform, Self::InitError>。这表示中间件的创建过程是同步的,不会进行复杂的异步操作。
new_transform 方法是 Transform trait 的一部分,用于创建一个新的中间件实例
1 | fn new_transform(&self, service: S) -> Self::Future { |
new_transform 方法是 Transform trait 的一部分,用于创建一个新的中间件实例。
参数解析:S 类型的 service 参数,这个 service 是下游的服务,即处理请求的实际服务。
返回类型解析:该方法返回一个 Self::Future 类型的 Future,即一个 Ready 类型的 Future,它表示异步操作完成并立即返回
ready(Ok(SayHiMiddleware { service }))
ready是一个将结果包装成已完成的Future的辅助函数。在这里,我们返回了一个SayHiMiddleware<S>中间件,它包含了下游服务service,并且包装在一个Ok结果中,表示没有错误。
1 | pub struct SayHiMiddleware<S> { |
SayHiMiddleware<S> 是一个结构体,接收 S 类型的参数。(S 为下游服务类型)
1 | impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S> |
这是 SayHiMiddleware<S> 的 Service<ServiceRequest> trait 的实现。
定义了如何将请求传递给下游服务。具体来说,Service 是一个 trait,它定义了如何处理 ServiceRequest,并返回一个 ServiceResponse<B>
1 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { |
这是 Service<ServiceRequest> trait 中的方法
作用是让中间件知道下游服务是否可以处理请求,用来检查服务是否准备好接收请求。
方法会调用下游服务 self.service.poll_ready(cx),这表示如果下游服务准备好了(也就是说可以开始处理请求)
那么 SayHiMiddleware 也可以开始处理请求。
第二个方法
1 | fn call(&mut self, req: ServiceRequest) -> Self::Future { |
call 是处理请求的核心方法,它会将一个 ServiceRequest 请求交给中间件来处理
req 是传入的请求,它是一个 ServiceRequest 类型的值,表示需要处理的 HTTP 请求
println!("Hi! Handling a request!") 这一行会在每次请求被中间件处理时输出 “Hi! Handling a request!”,表示中间件正在处理请求。这个可以作为日志记录,帮助你跟踪请求的流转。
最后,self.service.call(req) 调用下游服务的 call 方法,把请求传递给下游服务进行处理。下游服务通常会返回一个 ServiceResponse 类型的响应
1 | where |
1 | fn call(&self, req: ServiceRequest) -> Self::Future { |
简易的中间件
适用于小型任务
1 | async fn my_middleware( |