From d964f1befc86c5271f1f941f6ca75075743ba9c6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 9 Nov 2024 14:57:55 +0100 Subject: [PATCH] `nodeinfo`: Split off `Content-Type` parameters before checking the MIME type --- acrate-nodeinfo/src/lib.rs | 44 ++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/acrate-nodeinfo/src/lib.rs b/acrate-nodeinfo/src/lib.rs index 48579dd..728bd38 100644 --- a/acrate-nodeinfo/src/lib.rs +++ b/acrate-nodeinfo/src/lib.rs @@ -2,6 +2,7 @@ //! //! [RFC 6415]: https://datatracker.ietf.org/doc/html/rfc6415 +use reqwest::header::HeaderValue; use serde::{Serialize, Deserialize}; /// A [host-meta document]. @@ -60,15 +61,21 @@ impl HostMetaDocument { .await .map_err(Request)?; - log::trace!("Checking headers of the response..."); - response + log::trace!("Checking `Content-Type` of the response..."); + let content_type = response .headers() .get(reqwest::header::CONTENT_TYPE) - .ok_or(ContentTypeMissing)? - .eq("application/json") - .then_some(()) + .ok_or(ContentTypeMissing)?; + + log::trace!("Extracting MIME type from the `Content-Type` header..."); + let mime_type = extract_mime_from_content_type(content_type) .ok_or(ContentTypeInvalid)?; + log::trace!("Ensuring MIME type of `{mime_type}` is acceptable for JRD parsing..."); + if mime_type != "application/json" { + return Err(ContentTypeInvalid) + } + log::trace!("Attempting to parse response as JSON..."); let data = response.json::() .await @@ -107,15 +114,21 @@ impl HostMetaDocument { .await .map_err(Request)?; - log::trace!("Checking headers of the response..."); - response + log::trace!("Checking `Content-Type` of the response..."); + let content_type = response .headers() .get(reqwest::header::CONTENT_TYPE) - .ok_or(ContentTypeMissing)? - .eq("application/xrd+json") - .then_some(()) + .ok_or(ContentTypeMissing)?; + + log::trace!("Extracting MIME type from the `Content-Type` header..."); + let mime_type = extract_mime_from_content_type(content_type) .ok_or(ContentTypeInvalid)?; + log::trace!("Ensuring MIME type of `{mime_type}` is acceptable for JRD parsing..."); + if mime_type != "application/xrd+xml" { + return Err(ContentTypeInvalid) + } + log::trace!("Attempting to parse response as text..."); let data = response.text() .await @@ -302,4 +315,13 @@ pub enum HostMetaGetJRDError { ContentTypeInvalid, /// The document failed to be parsed as JSON by [`reqwest`]. Parse(reqwest::Error), -} \ No newline at end of file +} + +/// Extract the MIME type from the value of the `Content-Type` header. +fn extract_mime_from_content_type(value: &HeaderValue) -> Option { + let value = value.to_str().ok()?; + match value.split_once("; ") { + None => Some(value.to_string()), + Some((mime, _)) => Some(mime.to_string()), + } +}