You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
6.4 KiB
Rust

// This file was originally based on
// <https://github.com/timothee-haudebourg/json-ld/blob/0.12.1/core/src/loader/reqwest/content_type.rs>.
//
// Copyright (C) 2022 Timothée Haudebourg et al.
// Licensed under either the Apache License, Version 2.0; or the MIT License.
// See <https://github.com/timothee-haudebourg/json-ld/tree/0.12.1> for details.
//
// Heavily modified by anna <owo@fef.moe> 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<String>,
}
impl ContentType {
pub fn from_header(value: &HeaderValue) -> Option<ContentType> {
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());
}
}