use activitypub_federation::{ config::Data, fetch::webfinger::{build_webfinger_response, extract_webfinger_name}, }; use axum::{Json, extract::Query, http::StatusCode, response::IntoResponse}; use serde::Deserialize; use crate::{error::AppError, server::routes::users::get_user::read_user, state::AppHandle}; #[derive(Deserialize)] pub struct WebfingerQuery { resource: String, } pub async fn webfinger( Query(query): Query, data: Data, ) -> Result { let name = extract_webfinger_name(&query.resource, &data)?; if let Some(db_user) = read_user(name, &data).await? { Ok(( StatusCode::OK, Json(build_webfinger_response( query.resource, db_user.ap_id.into_inner(), )), ) .into_response()) } else { Ok((StatusCode::NOT_FOUND, "").into_response()) } } #[cfg(test)] mod tests { use axum::{ body::Body, http::{Request, StatusCode}, }; use sqlx::PgPool; use stack_up::Services; use tower::ServiceExt; use crate::{ server::{self, test_config}, state::AppState, }; #[sqlx::test] async fn webfinger_ok(pool: PgPool) { let services = Services { postgres: pool }; let state = AppState::create(services, &test_config()).await.unwrap(); let app = server::router(state); let response = app .oneshot( Request::builder() .uri("/.well-known/webfinger?resource=acct:sellershut@localhost") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); } #[sqlx::test] async fn webfinger_err(pool: PgPool) { let services = Services { postgres: pool }; let state = AppState::create(services, &test_config()).await.unwrap(); let app = server::router(state); let response = app .oneshot( Request::builder() .uri("/.well-known/webfinger?resource=acct:sst@localhost") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::NOT_FOUND); } }