Initial commit
Commit
a9d5b52133
@ -0,0 +1,3 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
authors = ["Baptiste Gelez <baptiste@gelez.xyz>"]
|
||||
name = "webfinger"
|
||||
version = "0.1.0"
|
||||
[dependencies]
|
||||
reqwest = "0.8"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
@ -0,0 +1,86 @@
|
||||
extern crate reqwest;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
|
||||
use reqwest::{Client, header::{Accept, qitem}, mime::Mime};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Webfinger {
|
||||
subject: String,
|
||||
aliases: Vec<String>,
|
||||
links: Vec<Link>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Link {
|
||||
rel: String,
|
||||
href: String,
|
||||
#[serde(rename="type")]
|
||||
mime_type: Option<String>
|
||||
}
|
||||
|
||||
pub enum WebfingerError {
|
||||
HttpError,
|
||||
ParseError,
|
||||
JsonError
|
||||
}
|
||||
|
||||
pub fn url_for_acct(acct: String) -> Result<String, WebfingerError> {
|
||||
acct.split("@")
|
||||
.last()
|
||||
.ok_or(WebfingerError::ParseError)
|
||||
.map(|instance| format!("https://{}/.well-known/webfinger?resource=acct:{}", instance, acct))
|
||||
}
|
||||
|
||||
pub fn resolve(acct: String) -> Result<Webfinger, WebfingerError> {
|
||||
let url = url_for_acct(acct)?;
|
||||
Client::new()
|
||||
.get(&url[..])
|
||||
.header(Accept(vec![qitem("application/jrd+json".parse::<Mime>().unwrap())]))
|
||||
.send()
|
||||
.map_err(|_| WebfingerError::HttpError)
|
||||
.and_then(|mut r| r.text().map_err(|_| WebfingerError::HttpError))
|
||||
.and_then(|res| serde_json::from_str(&res[..]).map_err(|_| WebfingerError::JsonError))
|
||||
}
|
||||
|
||||
pub enum ResolverError {
|
||||
InvalidResource,
|
||||
WrongInstance,
|
||||
NotFound
|
||||
}
|
||||
|
||||
pub trait Resolver<R> {
|
||||
fn instance_domain<'a>() -> &'a str;
|
||||
fn find(acct: String, resource_repo: R) -> Result<Webfinger, ResolverError>;
|
||||
|
||||
fn endpoint(resource: String, resource_repo: R) -> Result<Webfinger, ResolverError> {
|
||||
let mut parsed_query = resource.splitn(2, ":");
|
||||
parsed_query.next()
|
||||
.ok_or(ResolverError::InvalidResource)
|
||||
.and_then(|res_type| {
|
||||
if res_type == "acct" {
|
||||
parsed_query.next().ok_or(ResolverError::InvalidResource)
|
||||
} else {
|
||||
Err(ResolverError::InvalidResource)
|
||||
}
|
||||
})
|
||||
.and_then(|res| {
|
||||
let mut parsed_res = res.split("@");
|
||||
parsed_res.next()
|
||||
.ok_or(ResolverError::InvalidResource)
|
||||
.and_then(|user| {
|
||||
parsed_res.next()
|
||||
.ok_or(ResolverError::InvalidResource)
|
||||
.and_then(|res_domain| {
|
||||
if res_domain == Self::instance_domain() {
|
||||
Self::find(user.to_string(), resource_repo)
|
||||
} else {
|
||||
Err(ResolverError::WrongInstance)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren