http.rs
⎇
Raw
1use std::fmt;
2
3use gloo_net::http::{Request, Response};
4use serde::Serialize;
5use serde::de::DeserializeOwned;
6
7#[derive(Clone)]
8pub struct Error {
9 pub status: u16,
10 pub msg: String,
11}
12
13impl fmt::Display for Error {
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15 f.write_str(&self.msg)
16 }
17}
18
19pub async fn get<T: DeserializeOwned>(path: &str) -> Result<T, Error> {
20 read(path, Request::get(path).send().await).await
21}
22
23/// For the app's device mode. A 401 there means the device was removed, not that a session ended.
24pub async fn get_bearer<T: DeserializeOwned>(path: &str, token: &str) -> Result<T, Error> {
25 let res = Request::get(path)
26 .header("Authorization", &format!("Bearer {token}"))
27 .send()
28 .await;
29 read("", res).await
30}
31
32pub async fn post<T: DeserializeOwned>(path: &str, body: &impl Serialize) -> Result<T, Error> {
33 let req = Request::post(path).json(body).map_err(|e| Error {
34 status: 0,
35 msg: e.to_string(),
36 })?;
37 read(path, req.send().await).await
38}
39
40pub async fn put<T: DeserializeOwned>(path: &str, body: &impl Serialize) -> Result<T, Error> {
41 let req = Request::put(path).json(body).map_err(|e| Error {
42 status: 0,
43 msg: e.to_string(),
44 })?;
45 read(path, req.send().await).await
46}
47
48pub async fn delete(path: &str) -> Result<(), Error> {
49 read(path, Request::delete(path).send().await).await
50}
51
52async fn read<T: DeserializeOwned>(
53 path: &str,
54 res: Result<Response, gloo_net::Error>,
55) -> Result<T, Error> {
56 let res = res.map_err(|e| Error {
57 status: 0,
58 msg: format!("network error: {e}"),
59 })?;
60 // The session has ended. A reload shows the login form.
61 if res.status() == 401
62 && !matches!(path, "" | "/api/login" | "/api/me")
63 && !path.starts_with("/api/guest")
64 {
65 let _ = web_sys::window().unwrap().location().reload();
66 }
67 if !res.ok() {
68 let body = res.text().await.unwrap_or_default();
69 let msg = if body.is_empty() {
70 res.status_text()
71 } else {
72 body
73 };
74 return Err(Error {
75 status: res.status(),
76 msg,
77 });
78 }
79 res.json().await.map_err(|e| Error {
80 status: 0,
81 msg: e.to_string(),
82 })
83}
84