Skip to main content

atrium_identity/handle/
appview_resolver.rs

1use super::HandleResolver;
2use crate::error::{Error, Result};
3use atrium_api::com::atproto::identity::resolve_handle;
4use atrium_api::types::string::{Did, Handle};
5use atrium_common::resolver::Resolver;
6use atrium_xrpc::HttpClient;
7use atrium_xrpc::http::uri::Builder;
8use atrium_xrpc::http::{Request, Uri};
9use std::sync::Arc;
10
11#[derive(Clone, Debug)]
12pub struct AppViewHandleResolverConfig<T> {
13    pub service_url: String,
14    pub http_client: Arc<T>,
15}
16
17pub struct AppViewHandleResolver<T> {
18    service_url: String,
19    http_client: Arc<T>,
20}
21
22impl<T> AppViewHandleResolver<T> {
23    pub fn new(config: AppViewHandleResolverConfig<T>) -> Self {
24        Self { service_url: config.service_url, http_client: config.http_client }
25    }
26}
27
28impl<T> Resolver for AppViewHandleResolver<T>
29where
30    T: HttpClient + Send + Sync + 'static,
31{
32    type Input = Handle;
33    type Output = Did;
34    type Error = Error;
35
36    async fn resolve(&self, handle: &Self::Input) -> Result<Self::Output> {
37        let uri = Builder::from(self.service_url.parse::<Uri>()?)
38            .path_and_query(format!(
39                "/xrpc/com.atproto.identity.resolveHandle?{}",
40                serde_html_form::to_string(resolve_handle::ParametersData {
41                    handle: handle.clone(),
42                })?
43            ))
44            .build()?;
45        // TODO: no-cache?
46        let res = self
47            .http_client
48            .send_http(Request::builder().uri(uri).body(Vec::new())?)
49            .await
50            .map_err(Error::HttpClient)?;
51        if res.status().is_success() {
52            Ok(serde_json::from_slice::<resolve_handle::OutputData>(res.body())?.did)
53        } else {
54            Err(Error::HttpStatus(res.status()))
55        }
56    }
57}
58
59impl<T> HandleResolver for AppViewHandleResolver<T> where T: HttpClient + Send + Sync + 'static {}