atrium-identity 0.1.9

Resolver library for decentralized identities in atproto using DIDs and handles
Documentation
use super::DidResolver;
use crate::error::{Error, Result};
use atrium_api::did_doc::DidDocument;
use atrium_api::types::string::Did;
use atrium_common::resolver::Resolver;
use atrium_xrpc::HttpClient;
use atrium_xrpc::http::{Request, Uri, header::ACCEPT};
use std::sync::Arc;

const DID_WEB_PREFIX: &str = "did:web:";

#[derive(Clone, Debug)]
pub struct WebDidResolverConfig<T> {
    pub http_client: Arc<T>,
}

pub struct WebDidResolver<T> {
    http_client: Arc<T>,
}

impl<T> WebDidResolver<T> {
    pub fn new(config: WebDidResolverConfig<T>) -> Self {
        Self { http_client: config.http_client }
    }
}

impl<T> Resolver for WebDidResolver<T>
where
    T: HttpClient + Send + Sync + 'static,
{
    type Input = Did;
    type Output = DidDocument;
    type Error = Error;

    async fn resolve(&self, did: &Self::Input) -> Result<Self::Output> {
        let document_url = format!(
            "https://{}/.well-known/did.json",
            did.as_str()
                .strip_prefix(DID_WEB_PREFIX)
                .ok_or_else(|| Error::Did(did.as_str().to_string()))?
        )
        .parse::<Uri>()?;
        let res = self
            .http_client
            .send_http(
                Request::builder()
                    .header(ACCEPT, "application/did+ld+json,application/json")
                    .uri(document_url)
                    .body(Vec::new())?,
            )
            .await
            .map_err(Error::HttpClient)?;
        if res.status().is_success() {
            Ok(serde_json::from_slice(res.body())?)
        } else {
            Err(Error::HttpStatus(res.status()))
        }
    }
}

impl<T> DidResolver for WebDidResolver<T> where T: HttpClient + Send + Sync + 'static {}