···
fn xrpc_url(&self, method: &str) -> String {
26
-
format!("{}/xrpc/{}", self.base_url.trim_end_matches('/'), method)
26
+
let base = self.base_url.trim_end_matches('/');
27
+
// Add https:// if no protocol is present
28
+
let base_with_protocol = if base.starts_with("http://") || base.starts_with("https://") {
31
+
format!("https://{}", base)
33
+
format!("{}/xrpc/{}", base_with_protocol, method)
async fn post_json<TReq: Serialize, TRes: DeserializeOwned>(
···
return Err(anyhow!("{}: {}", status, body));
Ok(res.json::<TRes>().await?)
59
+
async fn post<TReq: Serialize>(
63
+
bearer: Option<&str>,
65
+
let url = self.xrpc_url(method);
66
+
let client = reqwest::Client::new();
67
+
let mut reqb = client
69
+
.header(reqwest::header::CONTENT_TYPE, "application/json");
70
+
if let Some(token) = bearer {
71
+
reqb = reqb.header(reqwest::header::AUTHORIZATION, format!("Bearer {}", token));
73
+
let res = reqb.json(req).send().await?;
74
+
let status = res.status();
75
+
if !status.is_success() {
76
+
let body = res.text().await.unwrap_or_default();
77
+
return Err(anyhow!("{}: {}", status, body));
pub async fn get_json<TRes: DeserializeOwned>(
···
297
+
// Method-less ServiceAuth tokens must expire within 60 seconds per AT Protocol spec
269
-
("exp", (chrono::Utc::now().timestamp() + 600).to_string()),
300
+
("exp", (chrono::Utc::now().timestamp() + 60).to_string()),
let sa: GetSARes = pds_client
···
description: item.value.description,
379
+
spindle: item.value.spindle,
···
424
+
// Method-less ServiceAuth tokens must expire within 60 seconds per AT Protocol spec
394
-
("exp", (chrono::Utc::now().timestamp() + 600).to_string()),
427
+
("exp", (chrono::Utc::now().timestamp() + 60).to_string()),
let sa: GetSARes = pds_client
···
1028
-
let _: serde_json::Value = self
1029
-
.post_json("sh.tangled.repo.addSecret", &body, Some(&sa))
1061
+
self.post("sh.tangled.repo.addSecret", &body, Some(&sa))
pub async fn remove_repo_secret(
···
let body = Req { repo: repo_at, key };
1048
-
let _: serde_json::Value = self
1049
-
.post_json("sh.tangled.repo.removeSecret", &body, Some(&sa))
1079
+
self.post("sh.tangled.repo.removeSecret", &body, Some(&sa))
async fn service_auth_token(&self, pds_base: &str, access_jwt: &str) -> Result<String> {
1057
-
.trim_end_matches('/')
1084
+
let base_trimmed = self.base_url.trim_end_matches('/');
1085
+
let host = base_trimmed
.strip_prefix("https://")
1059
-
.or_else(|| self.base_url.trim_end_matches('/').strip_prefix("http://"))
1060
-
.ok_or_else(|| anyhow!("invalid base_url"))?;
1087
+
.or_else(|| base_trimmed.strip_prefix("http://"))
1088
+
.unwrap_or(base_trimmed); // If no protocol, use the URL as-is
let audience = format!("did:web:{}", host);
let pds = TangledClient::new(pds_base);
1095
+
// Method-less ServiceAuth tokens must expire within 60 seconds per AT Protocol spec
1069
-
("exp", (chrono::Utc::now().timestamp() + 600).to_string()),
1098
+
("exp", (chrono::Utc::now().timestamp() + 60).to_string()),
···
pub description: Option<String>,
1360
+
pub spindle: Option<String>,
#[derive(Debug, Clone, Serialize, Deserialize)]