// This file was originally based on // . // // Copyright (C) 2022 Timothée Haudebourg et al. // Licensed under either the Apache License, Version 2.0; or the MIT License. // See for details. // // Heavily modified by anna to use nyanoblog's own Structured Header // parser and accept the `application/activity+json` MIME type as proper JSON-LD. use mime::Mime; use reqwest::header::HeaderValue; use std::str::FromStr; use crate::util::header::{Item, ParseHeader, ParseOptions}; /// Helper structure for parsing the `Content-Type` header for JSON-LD. pub struct ContentType { mime: Mime, profile: Option, } impl ContentType { pub fn from_header(value: &HeaderValue) -> Option { let item = Item::parse_from_header(value, ParseOptions::rfc8941()).ok()?; let mime = Mime::from_str(item.as_token()?).ok()?; let profile = item .param("profile") .and_then(|profile| profile.as_string_or_token()); Some(ContentType { mime, profile }) } pub fn is_json_ld(&self) -> bool { [ "application/activity+json", "application/ld+json", "application/json", ] .contains(&self.mime.as_ref()) } pub fn is_proper_json_ld(&self) -> bool { ["application/activity+json", "application/ld+json"].contains(&self.mime.as_ref()) } pub fn mime(&self) -> &Mime { &self.mime } pub fn into_mime(self) -> Mime { self.mime } pub fn profile(&self) -> Option<&str> { self.profile.as_deref() } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_content_type_1() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json;profile=http://www.w3.org/ns/json-ld#expanded", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_2() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json; profile=http://www.w3.org/ns/json-ld#expanded", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_3() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json; profile=http://www.w3.org/ns/json-ld#expanded; q=1", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_4() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json; profile=\"http://www.w3.org/ns/json-ld#expanded\"; q=1", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_5() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json; profile=\"http://www.w3.org/ns/json-ld#expanded\"", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_6() { let content_type = ContentType::from_header( &HeaderValue::from_str( "application/ld+json;profile=\"http://www.w3.org/ns/json-ld#expanded\"; q=1", ) .unwrap(), ) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#expanded") ); } #[test] fn parse_content_type_7() { let content_type = ContentType::from_header(&HeaderValue::from_str("application/ld+json; profile=\"http://www.w3.org/ns/json-ld#flattened http://www.w3.org/ns/json-ld#compacted\"; q=1").unwrap()).unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); assert_eq!( content_type.profile(), Some("http://www.w3.org/ns/json-ld#flattened http://www.w3.org/ns/json-ld#compacted") ); } #[test] fn parse_content_type_8() { let content_type = ContentType::from_header(&HeaderValue::from_str("application/ld+json").unwrap()) .unwrap(); assert_eq!(*content_type.mime(), "application/ld+json"); } #[test] fn is_proper_json_ld() { let content_type = ContentType::from_header(&HeaderValue::from_str("application/ld+json").unwrap()) .unwrap(); assert!(content_type.is_json_ld()); assert!(content_type.is_proper_json_ld()); let content_type = ContentType::from_header(&HeaderValue::from_str("application/activity+json").unwrap()) .unwrap(); assert!(content_type.is_json_ld()); assert!(content_type.is_proper_json_ld()); } #[test] fn is_json_ld() { let content_type = ContentType::from_header(&HeaderValue::from_str("application/json").unwrap()).unwrap(); assert!(content_type.is_json_ld()); assert!(!content_type.is_proper_json_ld()); } #[test] fn is_not_json_ld() { let content_type = ContentType::from_header(&HeaderValue::from_str("application/xml").unwrap()).unwrap(); assert!(!content_type.is_json_ld()); assert!(!content_type.is_proper_json_ld()); } }