131 lines
3.4 KiB
Rust
131 lines
3.4 KiB
Rust
use common::ron_api;
|
|
use gloo::net::http::{Request, RequestBuilder};
|
|
use serde::{de::DeserializeOwned, Serialize};
|
|
use thiserror::Error;
|
|
|
|
use crate::toast::{self, Level};
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum Error {
|
|
#[error("Gloo error: {0}")]
|
|
Gloo(#[from] gloo::net::Error),
|
|
|
|
#[error("RON Spanned error: {0}")]
|
|
Ron(#[from] ron::error::SpannedError),
|
|
|
|
#[error("HTTP error: {0}")]
|
|
Http(String),
|
|
|
|
#[error("Unknown error: {0}")]
|
|
Other(String),
|
|
}
|
|
|
|
type Result<T> = std::result::Result<T, Error>;
|
|
|
|
const CONTENT_TYPE: &str = "Content-Type";
|
|
const CONTENT_TYPE_RON: &str = "application/ron";
|
|
|
|
async fn req_with_body<T, U>(
|
|
api_name: &str,
|
|
body: U,
|
|
method_fn: fn(&str) -> RequestBuilder,
|
|
) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: Serialize,
|
|
{
|
|
let url = format!("/ron-api/{}", api_name);
|
|
let request_builder = method_fn(&url).header(CONTENT_TYPE, CONTENT_TYPE_RON);
|
|
send_req(request_builder.body(ron_api::to_string(body))?).await
|
|
}
|
|
|
|
async fn req_with_params<'a, T, U, V>(
|
|
api_name: &str,
|
|
params: U,
|
|
method_fn: fn(&str) -> RequestBuilder,
|
|
) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: IntoIterator<Item = (&'a str, V)>,
|
|
V: AsRef<str>,
|
|
{
|
|
let url = format!("/ron-api/{}", api_name);
|
|
let request_builder = method_fn(&url)
|
|
.header(CONTENT_TYPE, CONTENT_TYPE_RON)
|
|
.query(params);
|
|
send_req(request_builder.build()?).await
|
|
}
|
|
|
|
async fn send_req<T>(request: Request) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
{
|
|
match request.send().await {
|
|
Err(error) => {
|
|
toast::show(Level::Info, &format!("Internal server error: {}", error));
|
|
Err(Error::Gloo(error))
|
|
}
|
|
Ok(response) => {
|
|
if !response.ok() {
|
|
toast::show(
|
|
Level::Info,
|
|
&format!("HTTP error: {}", response.status_text()),
|
|
);
|
|
Err(Error::Http(response.status_text()))
|
|
} else {
|
|
// Ok(())
|
|
Ok(ron::de::from_bytes::<T>(&response.binary().await?)?)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn put<T, U>(api_name: &str, body: U) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: Serialize,
|
|
{
|
|
req_with_body(api_name, body, Request::put).await
|
|
}
|
|
|
|
pub async fn post<T, U>(api_name: &str, body: U) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: Serialize,
|
|
{
|
|
req_with_body(api_name, body, Request::post).await
|
|
}
|
|
|
|
pub async fn delete<T, U>(api_name: &str, body: U) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: Serialize,
|
|
{
|
|
req_with_body(api_name, body, Request::delete).await
|
|
}
|
|
|
|
pub async fn get<'a, T, U, V>(api_name: &str, params: U) -> Result<T>
|
|
where
|
|
T: DeserializeOwned,
|
|
U: IntoIterator<Item = (&'a str, V)>,
|
|
V: AsRef<str>,
|
|
{
|
|
req_with_params(api_name, params, Request::get).await
|
|
}
|
|
|
|
// pub async fn api_request_get<T>(api_name: &str, params: QueryParams) -> Result<T, String>
|
|
// where
|
|
// T: DeserializeOwned,
|
|
// {
|
|
// match Request::get(&format!("/ron-api/recipe/{}?{}", api_name, params))
|
|
// .header("Content-Type", "application/ron")
|
|
// .send()
|
|
// .await
|
|
// {
|
|
// Err(error) => {
|
|
// toast::show(Level::Info, &format!("Internal server error: {}", error));
|
|
// Err(error.to_string())
|
|
// }
|
|
// Ok(response) => Ok(ron::de::from_bytes::<T>(&response.binary().await.unwrap()).unwrap()),
|
|
// }
|
|
// }
|