use std::collections::HashMap; use std::error::Error; use clap::Parser; #[macro_use] extern crate rocket; use reqwest::StatusCode; use rocket::{Request, Response}; use rocket::serde::json::Json; mod cohost_account; mod webfinger; use cohost_account::{CohostAccount, COHOST_ACCOUNT_API_URL}; use webfinger::CohostWebfingerResource; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { /// The base URL for the northbound instance #[clap(short, long, required = true)] domain: String, /// The base URL for the northbound instance #[clap(short, long, default_value_t = default_base_url() )] base_url: String, } fn default_base_url() -> String { "/.well-known/webfinger".into() } static ARGS: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { Args::parse() }); #[get("/?")] async fn webfinger_route(params: HashMap) -> Option> { if params.len() != 1 { eprintln!("Too may or too few parameters. Expected 1, got {}", params.len()); return None; } if let Some(param) = params.iter().next() { let url = format!("{}{}", COHOST_ACCOUNT_API_URL, param.0); eprintln!("making request to {}", url); match reqwest::get(url).await { Ok(v) => match v.status() { StatusCode::OK => { return Some(Json(CohostWebfingerResource::new(param.0.as_str(), &ARGS.domain))); }, // TODO NORA: Handle possible redirects s => { eprintln!("Didn't receive status code 200 for Cohost project '{}'; got {:?} instead.", param.0, s); return None; } }, Err(e) => { eprintln!("Error making request to Cohost for project '{}': {:?}", param.0, e); return None; } }; } None } #[rocket::main] async fn main() -> Result<(), Box> { // Set up the global config once_cell::sync::Lazy::force(&ARGS); let _rocket = rocket::build() .mount(&ARGS.base_url, routes![webfinger_route]) .ignite().await?.launch().await?; Ok(()) }