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.

107 lines
3.3 KiB
Rust

// This file was originally based on
// <https://github.com/timothee-haudebourg/json-ld/blob/0.12.1/core/src/loader/reqwest/link.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 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<String>,
typ: Option<String>,
}
impl Link {
pub fn from_header(value: &HeaderValue) -> Option<Self> {
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> {
Link::from_header(&HeaderValue::from_str(header_value).unwrap())
}
#[test]
fn parse_link_1() {
let link = mklink(
"<http://www.example.org/context>; 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(
"<http://www.example.org/context>; 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("<http://www.example.org/context>").unwrap();
assert_eq!(link.href(), "http://www.example.org/context")
}
#[test]
fn is_proper_json_ld() {
let link = mklink(
"<http://www.example.org/context>; rel=\"context\"; type=\"application/ld+json\"",
)
.unwrap();
assert!(link.is_proper_json_ld());
let link = mklink(
"<http://www.example.org/context>; rel=\"context\"; type=\"application/activity+json\"",
)
.unwrap();
assert!(link.is_proper_json_ld());
let link =
mklink("<http://www.example.org/context>; rel=\"context\"; type=\"application/json\"")
.unwrap();
assert!(!link.is_proper_json_ld());
}
}