|
|
Reading and writing bodies is limited to payloads of size 1MB or smaller. For larger payloads, see Streaming Bodies.
|
To access the body in both the request and the response, transform the RequestState or ResponseState to a body state by calling the method into_body_state() and awaiting it:
let body_state = request_state.into_body_state().await;
|
|
The previous .await introduces a cancellation point. During a request, a Flow Cancellation might cause the .await to never resume.
|
If the original state was already transformed into a header state, transform the state into a body state by calling the same function, for example:
let headers_state = request_state.into_headers_state().await;
let body_state = headers_state.into_body_state().await;
After calling into_body_state(), access and manipulate the headers by calling the functions of the BodyHandler trait.
pub trait BodyHandler {
fn body(&self) -> Vec<u8>;
fn set_body(&self, body: &[u8]) -> Result<(), BodyError>;
}
Because Envoy uses the same buffer to share data from the headers and the body, the policy cannot access the headers and the body at the same time. If the policy must read both:
-
Read the headers and save the necessary values in a variable.
-
Read the body.
You can read the headers and then the body in both the response and request. However, you cannot modify headers after reading the body. Complete all header modification before reading the body, for example:
async fn request_filter(request_state: RequestState) {
let headers_state = request_state.into_headers_state().await;
let headers_handler = headers_state.handler();
let agent = headers_handler.header("User-Agent").unwrap_or_else(|| "Undefined".to_string());
// Removing old content length header before manipulating body
headers_handler.remove_header("content-length");
let body_state = headers_state.into_body_state().await;
let body_handler = body_state.handler();
let body = body_handler.body();
logger::info!("User: {agent} sent: {}", String::from_utf8_lossy(body.as_slice()));
let new_body = "new body".as_bytes();
match body_handler.set_body(&new_body) {
Ok(_) => logger::info!("Body updated"),
Err(e) => logger::info!("Unable to set body. Reason: {e:?}),
}
}
|
|
This code removes the content-length header. This is required to modify the body.
|
BodyHandler::set_body() method returns a Result<(), BodyError> object. Body updating might fail due to:
-
BodyError::BodyNotSent: The current HTTP Flow doesn’t have a body (for example, GET request).
-
BodyError::ExceededBodySize: The new body exceeds the maximum body buffer size supported by Envoy.