// 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 iref::{IriRef, IriRefBuf}; use reqwest::header::HeaderValue; use std::str::FromStr; use crate::util::header::{Item, ParseHeader, ParseOptions}; pub struct Link { href: IriRefBuf, rel: Option, typ: Option, } impl Link { pub fn from_header(value: &HeaderValue) -> Option { let item = Item::parse_from_header(value, ParseOptions::link_header()).ok()?; let href = IriRefBuf::from_str(item.as_url()?).ok()?; let rel = item.param("rel").and_then(|rel| rel.as_string()); let typ = item.param("type").and_then(|typ| typ.as_string()); Some(Link { href, rel, typ }) } pub fn href(&self) -> IriRef { self.href.as_iri_ref() } pub fn rel(&self) -> Option<&str> { self.rel.as_deref() } pub fn typ(&self) -> Option<&str> { self.typ.as_deref() } pub fn is_proper_json_ld(&self) -> bool { self.typ() .filter(|t| ["application/activity+json", "application/ld+json"].contains(t)) .is_some() } } #[cfg(test)] mod tests { use super::*; fn mklink(header_value: &'static str) -> Option { Link::from_header(&HeaderValue::from_str(header_value).unwrap()) } #[test] fn parse_link_1() { let link = mklink( "; rel=\"context\"; type=\"application/ld+json\"", ) .unwrap(); assert_eq!(link.href(), "http://www.example.org/context"); assert_eq!(link.rel(), Some("context")); assert_eq!(link.typ(), Some("application/ld+json")) } #[test] fn parse_link_2() { let link = mklink( "; rel = \"context\" ; type=\"application/ld+json\" ; foo=\"bar\"", ) .unwrap(); assert_eq!(link.href(), "http://www.example.org/context"); assert_eq!(link.rel(), Some("context")); assert_eq!(link.typ(), Some("application/ld+json")) } #[test] fn parse_link_3() { let link = mklink("").unwrap(); assert_eq!(link.href(), "http://www.example.org/context") } #[test] fn is_proper_json_ld() { let link = mklink( "; rel=\"context\"; type=\"application/ld+json\"", ) .unwrap(); assert!(link.is_proper_json_ld()); let link = mklink( "; rel=\"context\"; type=\"application/activity+json\"", ) .unwrap(); assert!(link.is_proper_json_ld()); let link = mklink("; rel=\"context\"; type=\"application/json\"") .unwrap(); assert!(!link.is_proper_json_ld()); } }