Check validity of inputs using a non-crypto hash

Block or identify syntactically invalid requests at the edge by using a hash function of your choice.

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
const BACKEND_NAME: &str = "httpbin.org";
#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
log_fastly::init_simple("my_log", log::LevelFilter::Info);
fastly::log::set_panic_endpoint("my_log")?;
if let Some((id, expected_crc_str)) = get_product_id_and_crc32(req.get_path()) {
// Calculate CRC-32/BZIP2, which is used by Fastly VCL function digest.hash_crc32()
let mut crc32_bzip2 = Crc::<u32>::new(0x04c11db7, 32, 0xffffffff, 0xffffffff, false);
let crc_u32 = crc32_bzip2.update(id.as_bytes());
// Get first two bytes of CRC32 hash value to a string
let crc_bytes_vec = (crc_u32 as u16).to_le_bytes();
let calculated_crc_str = format!("{:02x}{:02x}", crc_bytes_vec[0], crc_bytes_vec[1]);
if expected_crc_str != &calculated_crc_str {
log::info!(
"Block Request, crc is {}, expecting {}",
calculated_crc_str,
expected_crc_str
);
let resp_block = Response::from_status(StatusCode::BAD_REQUEST)
.with_body("Not a valid product code\n");
return Ok(resp_block);
}
log::info!("Passed checksum based on CRC32 hash");
}
// Send request to backend
let resp = req.send(BACKEND_NAME)?;
Ok(resp)
}
/// Get product ID and CRC string from URL path
fn get_product_id_and_crc32(url: &str) -> Option<(&str, &str)> {
let id_crc_cap = Regex::new(r"^/products/(\d+)(....)$")
.unwrap()
.captures(url)?;
let id = id_crc_cap.get(1)?.as_str();
let crc = id_crc_cap.get(2)?.as_str();
Some((id, crc))
}