Мне нужно вставить специальный заголовок X-CRC32
в каждый ответ. Этот заголовок должен содержать контрольную сумму CRC32 тела ответа. Я думаю, что промежуточное ПО - лучший способ сделать это.
Проблема в том, что я не могу получить доступ к байтам тела.
async fn add_crc32_header_middleware(
req: ServiceRequest,
next: Next<impl MessageBody + 'static>,
) -> Result<ServiceResponse<impl MessageBody>, Error> {
let mut res = next.call(req).await?;
let body = res.response().body();
let body_bytes = match body.try_into_bytes() {
Ok(bytes) => bytes,
_ => return Err(actix_web::error::ErrorImATeapot(""))
};
let crc = format!("{:08x}", CRC32.checksum(&body_bytes));
let hdrs = res.headers_mut();
hdrs.insert( HeaderName::from_static("x-crc32"), HeaderValue::from_str(&crc).unwrap());
Ok(res)
}
Вот ошибка:
error[E0507]: cannot move out of `*body` which is behind a shared reference
--> src/main.rs:33:28
|
33 | let body_bytes = match body.try_into_bytes() {
| ^^^^^----------------
| | |
| | `*body` moved due to this method call
| move occurs because `*body` has type `impl MessageBody + 'static`, which does not implement the `Copy` trait
|
note: `try_into_bytes` takes ownership of the receiver `self`, which moves `*body`
код: https://github.com/olekhov/actix-middleware-test/blob/main/src/main.rs
Я думаю, что упускаю некоторые важные понятия. Тело сообщения находится BoxBody
за общей ссылкой, и я не могу понять, как его скопировать или получить доступ к внутреннему типу.
Если вы читаете документацию по ServiceResponse , вы найдете 3 метода, которые могут дать вам доступ к принадлежащему телу: map_body , into_body и into_parts, из которых into_body
явно не то, что вам нужно так как он отбрасывает все остальные данные. Вы можете использовать любой из двух других методов, например, с into_parts
:
async fn add_crc32_header_middleware(
req: ServiceRequest,
next: Next<impl MessageBody + 'static>,
) -> Result<ServiceResponse<impl MessageBody>, Error> {
let res = next.call(req).await?;
let (req, res) = res.into_parts();
let (mut res, body) = res.into_parts();
let body_bytes = match body.try_into_bytes() {
Ok(bytes) => bytes,
_ => return Err(actix_web::error::ErrorImATeapot("teapot")),
};
let crc = format!("{:08x}", CRC32.checksum(&body_bytes));
let hdrs = res.headers_mut();
hdrs.insert(
HeaderName::from_static("x-crc32"),
HeaderValue::from_str(&crc).unwrap(),
);
let res = res.set_body(body_bytes);
Ok(ServiceResponse::new(req, res))
}