POST to GET rewrite using a Base64-encoded querystring

To allow caching of POST requests, consider rewriting them as GET requests at the edge.

VCL

Use this solution in your VCL service (click RUN below to test this solution or clone it to make changes):

Compute@Edge

Use this solution in your Compute@Edge service:

  1. Rust
#[fastly::main]
fn main(mut req: Request) -> Result<Response, Error> {
log_fastly::init_simple("my_log", log::LevelFilter::Info);
// Make any desired changes to the client request
req.set_header(header::HOST, "httpbin.org");
let content_length: usize = get_req_content_length(&req);
if content_length > MAX_BODY_CONVERT_SIZE || content_length == 0 {
// Body is too big or content length is 0, not converting will be performed
return Ok(req.send(BACKEND_NAME)?);
}
// Get the base64 encoded body string
let body_encoded64 = base64::encode_config(&req.take_body_bytes(), base64::URL_SAFE_NO_PAD);
// Appened the post data as a query parameter
req.get_url_mut()
.query_pairs_mut()
.append_pair("postdata", &body_encoded64);
// Change method of request parts to HTTP GET
req.set_method("GET");
log::info!("new_req URL is {}", req.get_url());
// Send the request to backend
Ok(req.send(BACKEND_NAME)?)
}
/// Get content length of body of the request
fn get_req_content_length(req: &Request) -> usize {
match req.get_header(header::CONTENT_LENGTH) {
Some(value) => {
if let Ok(cl_str) = value.to_str() {
cl_str.parse().unwrap_or(0)
} else {
0
}
}
None => 0,
}
}