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( |