gpt4 book ai didi

rust - 如何在 actix-web 1.0 中间件中读取请求的主体?

转载 作者:行者123 更新时间:2023-11-29 07:59:17 27 4
gpt4 key购买 nike

我想在 actix-web 1.0 的中间件中读出正文。我正在使用 wrap_fn 的闭包式中间件。

我的基本设置是这样的:

let mut server = HttpServer::new(move || {
ActixApp::new()
.wrap_fn(|req, srv| {
srv.call(req).map(|res| {
let req_ = res.request();
let body = req_.magical_body_read_function();
dbg!(body);
res
})
})
});

我需要那个magical_body_read_function(),遗憾的是它不存在。

我通过阅读示例和使用 take_payload() 拼凑了一些看起来可以工作的东西,但遗憾的是它没有工作:

let mut server = HttpServer::new(move || {
ActixApp::new()
.wrap_fn(|req, srv| {
srv.call(req).map(|res| {
let req_ = res.request();
req_.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.and_then(|bytes| {
info!("request body: {:?}", bytes);
});
res
})
})
});

给我

error[E0599]: no method named `fold` found for type `actix_http::payload::Payload<()>` in the current scope    --> src/main.rs:209:26
| 209 | .fold(BytesMut::new(), move |mut body, chunk| {
| ^^^^
|
= note: the method `fold` exists but the following trait bounds were not satisfied:
`&mut actix_http::payload::Payload<()> : std::iter::Iterator`

然后我尝试了一种使用完整中间件的方法:

pub struct Logging;

impl<S, B> Transform<S> for Logging
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 = LoggingMiddleware<S>;
type Future = FutureResult<Self::Transform, Self::InitError>;

fn new_transform(&self, service: S) -> Self::Future {
ok(LoggingMiddleware { service })
}
}

pub struct LoggingMiddleware<S> {
service: S,
}

impl<S, B> Service for LoggingMiddleware<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 = Box<dyn Future<Item = Self::Response, Error = Self::Error>>;

fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}

fn call(&mut self, req: ServiceRequest) -> Self::Future {
Box::new(self.service.call(req).and_then(|res| {
let req_ = res.request();
req_.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.and_then(|bytes| {
info!("request body: {:?}", bytes);
});
Ok(res)
}))
}
}

遗憾的是,这也导致了看起来非常相似的错误:

error[E0599]: no method named `fold` found for type `actix_http::payload::Payload<()>` in the current scope
--> src/main.rs:204:18
|
204 | .fold(BytesMut::new(), move |mut body, chunk| {
| ^^^^
|
= note: the method `fold` exists but the following trait bounds were not satisfied:
`&mut actix_http::payload::Payload<()> : futures::stream::Stream`
`&mut actix_http::payload::Payload<()> : std::iter::Iterator`
`actix_http::payload::Payload<()> : futures::stream::Stream`

最佳答案

在 actix-web Gitter channel 的优秀人员的帮助下,我找到了这个我也制作的解决方案 a PR为。

完整的解决方案是:

pub struct Logging;

impl<S: 'static, B> Transform<S> for Logging
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 = LoggingMiddleware<S>;
type Future = FutureResult<Self::Transform, Self::InitError>;

fn new_transform(&self, service: S) -> Self::Future {
ok(LoggingMiddleware {
service: Rc::new(RefCell::new(service)),
})
}
}

pub struct LoggingMiddleware<S> {
// This is special: We need this to avoid lifetime issues.
service: Rc<RefCell<S>>,
}

impl<S, B> Service for LoggingMiddleware<S>
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>
+ 'static,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error>>;

fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}

fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let mut svc = self.service.clone();

Box::new(
req.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.map_err(|e| e.into())
.and_then(move |bytes| {
println!("request body: {:?}", bytes);
svc.call(req).and_then(|res| Ok(res))
}),
)
}
}

关于rust - 如何在 actix-web 1.0 中间件中读取请求的主体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57870379/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com