From 894b27f32e129d996a64e3ffe1c3c4b3bfafef80 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Wed, 5 Jun 2024 11:15:42 -0700 Subject: [PATCH] fix(*): support mime type structured syntax suffix --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/filter.rs | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50ae54d..0343edc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "once_cell" version = "1.18.0" @@ -70,6 +76,7 @@ name = "proxy-wasm-rust-response-transformer" version = "0.1.0" dependencies = [ "log", + "mime", "proxy-wasm", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 74cdb15..c36dab4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ proxy-wasm = "0.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = "0.4" +mime = "0.3.17" diff --git a/src/filter.rs b/src/filter.rs index 5ac48fe..681dc65 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -19,7 +19,17 @@ proxy_wasm::main! {{ const CONTENT_LENGTH: &str = "content-length"; const CONTENT_TYPE: &str = "content-type"; -const JSON_CONTENT_TYPE: &str = "application/json"; + +fn is_json_mime_type>(ct: T) -> bool { + let Ok(mt) = ct.as_ref().parse::() else { + return false; + }; + + matches!( + (mt.type_(), mt.subtype(), mt.suffix()), + (mime::APPLICATION, mime::JSON, _) | (mime::APPLICATION, _, Some(mime::JSON)) + ) +} struct ResponseTransformerRoot { config: Option>, @@ -132,7 +142,7 @@ impl HttpContext for ResponseTransformerHttp { impl ResponseTransformerHttp { fn is_json_response(&self) -> bool { self.get_http_response_header(CONTENT_TYPE) - .map_or(false, |ct| ct.eq_ignore_ascii_case(JSON_CONTENT_TYPE)) + .map_or(false, is_json_mime_type) } fn transform_headers(&self, tx: &Headers) { @@ -267,3 +277,24 @@ impl ResponseTransformerHttp { self.set_http_response_body(0, body.len(), body.as_slice()); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_json_mime_type_detection() { + assert!(is_json_mime_type("application/json")); + assert!(is_json_mime_type("APPLICATION/json")); + assert!(is_json_mime_type("APPLICATION/JSON")); + assert!(is_json_mime_type("application/JSON")); + assert!(is_json_mime_type("application/json; charset=utf-8")); + assert!(is_json_mime_type("application/problem+json")); + assert!(is_json_mime_type("application/problem+JSON")); + assert!(is_json_mime_type("application/problem+json; charset=utf-8")); + + assert!(!is_json_mime_type("text/plain")); + assert!(!is_json_mime_type("application/not-json")); + assert!(!is_json_mime_type("nope/json")); + } +}