Skip to main content

relay_actions/
request.rs

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}