1use anyhow::{Context, Result};
2use relay_lib::prelude::Address;
3use reqwest::blocking::Response;
4use serde::Serialize;
5
6use crate::{
7 cache::CacheManager, sign::sign_request, sinks::progress::ProgressSink, storage::Storage,
8};
9
10pub fn get_signed<R: Serialize>(
11 progress: &mut dyn ProgressSink,
12 storage: &mut Storage,
13 cache: &mut CacheManager,
14 address: &Address,
15 endpoint: &str,
16 payload: R,
17) -> Result<Response> {
18 let agent_record = cache
19 .records
20 .agent(&mut cache.agents, address.agent())
21 .context("Failed to get agent record from cache")?;
22
23 let identity = storage.root.get_identity(address).unwrap_or_else(|| {
24 progress.abort(&format!("Identity not found: {}", address));
25 });
26
27 let request = sign_request(
28 &address.canonical(),
29 payload,
30 &agent_record,
31 &identity.signing_key(),
32 )
33 .context("Failed to sign signed request")?;
34
35 let resp = reqwest::blocking::Client::new()
36 .get(
37 cache
38 .agents
39 .url(address.agent())
40 .context("Failed to get agent URL from cache")?
41 .join(endpoint)
42 .context("Failed to construct messages URL")?,
43 )
44 .json(&request)
45 .send()
46 .context("Failed to send signed request")?;
47
48 if resp.status().as_u16() == 401 {
49 progress.abort("Unauthorized. Identity may have expired or been revoked.");
50 }
51
52 if resp.status().as_u16() == 403 {
53 progress.abort("Forbidden. Identity may not have permission to perform this action.");
54 }
55
56 Ok(resp)
57}
58
59pub fn post_signed<R: Serialize>(
60 progress: &mut dyn ProgressSink,
61 storage: &mut Storage,
62 cache: &mut CacheManager,
63 address: &Address,
64 endpoint: &str,
65 payload: R,
66) -> Result<Response> {
67 let agent_record = cache
68 .records
69 .agent(&mut cache.agents, address.agent())
70 .context("Failed to get agent record from cache")?;
71
72 let identity = storage.root.get_identity(address).unwrap_or_else(|| {
73 progress.abort(&format!("Identity not found: {}", address));
74 });
75
76 let request = sign_request(
77 &address.canonical(),
78 payload,
79 &agent_record,
80 &identity.signing_key(),
81 )
82 .context("Failed to sign signed request")?;
83
84 let resp = reqwest::blocking::Client::new()
85 .post(
86 cache
87 .agents
88 .url(address.agent())
89 .context("Failed to get agent URL from cache")?
90 .join(endpoint)
91 .context("Failed to construct messages URL")?,
92 )
93 .json(&request)
94 .send()
95 .context("Failed to send signed request")?;
96
97 if resp.status().as_u16() == 401 {
98 progress.abort("Unauthorized. Identity may have expired or been revoked.");
99 }
100
101 if resp.status().as_u16() == 403 {
102 progress.abort("Forbidden. Identity may not have permission to perform this action.");
103 }
104
105 Ok(resp)
106}