mirror of
https://github.com/CloudNebulaProject/webfingerd.git
synced 2026-04-10 13:10:41 +00:00
feat: add host-meta endpoint with domain-aware XRD response
This commit is contained in:
parent
697c84accf
commit
7aa5a6738c
3 changed files with 101 additions and 0 deletions
45
src/handler/host_meta.rs
Normal file
45
src/handler/host_meta.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use axum::extract::State;
|
||||
use axum_extra::extract::Host;
|
||||
use axum::http::header;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use sea_orm::*;
|
||||
|
||||
use crate::entity::domains;
|
||||
use crate::error::{AppError, AppResult};
|
||||
use crate::state::AppState;
|
||||
|
||||
async fn host_meta(
|
||||
State(state): State<AppState>,
|
||||
Host(hostname): Host,
|
||||
) -> AppResult<Response> {
|
||||
// Strip port if present
|
||||
let domain = hostname.split(':').next().unwrap_or(&hostname);
|
||||
|
||||
// Check this domain is registered and verified
|
||||
let _domain = domains::Entity::find()
|
||||
.filter(domains::Column::Domain.eq(domain))
|
||||
.filter(domains::Column::Verified.eq(true))
|
||||
.one(&state.db)
|
||||
.await?
|
||||
.ok_or(AppError::NotFound)?;
|
||||
|
||||
let base_url = &state.settings.server.base_url;
|
||||
let xrd = format!(
|
||||
r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link rel="lrdd" type="application/jrd+json" template="{base_url}/.well-known/webfinger?resource={{uri}}" />
|
||||
</XRD>"#
|
||||
);
|
||||
|
||||
Ok((
|
||||
[(header::CONTENT_TYPE, "application/xrd+xml; charset=utf-8")],
|
||||
xrd,
|
||||
)
|
||||
.into_response())
|
||||
}
|
||||
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new().route("/.well-known/host-meta", get(host_meta))
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
mod health;
|
||||
mod host_meta;
|
||||
mod webfinger;
|
||||
|
||||
use axum::Router;
|
||||
|
|
@ -7,6 +8,7 @@ use crate::state::AppState;
|
|||
pub fn router(state: AppState) -> Router {
|
||||
Router::new()
|
||||
.merge(webfinger::router())
|
||||
.merge(host_meta::router())
|
||||
.merge(health::router())
|
||||
.with_state(state)
|
||||
}
|
||||
|
|
|
|||
54
tests/test_host_meta.rs
Normal file
54
tests/test_host_meta.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
mod common;
|
||||
|
||||
use axum_test::TestServer;
|
||||
use webfingerd::handler;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_host_meta_returns_xrd_for_known_domain() {
|
||||
let state = common::test_state().await;
|
||||
|
||||
// Seed a verified domain in DB
|
||||
use sea_orm::ActiveModelTrait;
|
||||
use sea_orm::Set;
|
||||
use webfingerd::entity::domains;
|
||||
|
||||
let domain = domains::ActiveModel {
|
||||
id: Set(uuid::Uuid::new_v4().to_string()),
|
||||
domain: Set("example.com".into()),
|
||||
owner_token_hash: Set("hash".into()),
|
||||
registration_secret: Set("secret".into()),
|
||||
challenge_type: Set("dns-01".into()),
|
||||
challenge_token: Set(None),
|
||||
verified: Set(true),
|
||||
created_at: Set(chrono::Utc::now().naive_utc()),
|
||||
verified_at: Set(Some(chrono::Utc::now().naive_utc())),
|
||||
};
|
||||
domain.insert(&state.db).await.unwrap();
|
||||
|
||||
let app = handler::router(state);
|
||||
let server = TestServer::new(app);
|
||||
|
||||
let response = server
|
||||
.get("/.well-known/host-meta")
|
||||
.add_header("Host", "example.com")
|
||||
.await;
|
||||
|
||||
response.assert_status_ok();
|
||||
let body = response.text();
|
||||
assert!(body.contains("application/jrd+json") || body.contains("XRD"));
|
||||
assert!(body.contains("/.well-known/webfinger"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_host_meta_returns_404_for_unknown_domain() {
|
||||
let state = common::test_state().await;
|
||||
let app = handler::router(state);
|
||||
let server = TestServer::new(app);
|
||||
|
||||
let response = server
|
||||
.get("/.well-known/host-meta")
|
||||
.add_header("Host", "unknown.example.com")
|
||||
.await;
|
||||
|
||||
response.assert_status_not_found();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue