I'm positive that a request body/payload in in a certain request (given that it is properly extracted and deserialized into JSON by actix_web) but the Bytes extracted by actix_web are empty. This only occurs when JSON is also extracted.
This is the function signature, in which I expect payload_bytes
to be the byte representation of the request's payload.
#[post("/")]
pub async fn handle_root_request(
event_data: web::Json<stripe::Event>,
payload_bytes: web::Bytes,
request: HttpRequest,
) -> Result<HttpResponse, Error>
However, payload_bytes
comes out as empty within this function.
Minimal Reproducible Example:
use actix_web::*;
#[tokio::main]
async fn main() -> std::io::Result<()> {
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; // override default
//
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 3000);
HttpServer::new(move || App::new().service(example))
.bind(&addr)?
.run()
.await
}
#[post("/")]
pub async fn example(
json_payload: web::Json<serde_json::Value>,
payload_bytes: web::Bytes,
) -> Result<HttpResponse, Error> {
println!("{}", payload_bytes.len());
Ok(HttpResponse::Ok().into())
}
Run curl -X POST -H "Content-Type: application/json" -d '{"message":"hello world"}' http://localhost:3000
and watch the output.
You can extract the request body once and no more.
However, you don't need to - you can just parse JSON from the Bytes
:
#[post("/")]
pub async fn example(
payload_bytes: web::Bytes,
) -> Result<HttpResponse, Error> {
let json_payload = serde_json::from_slice::<serde_json::Value>(&payload_bytes)?;
println!("{}", payload_bytes.len());
Ok(HttpResponse::Ok().into())
}