use crate::framework::response::ApiResult;
use crate::framework::Environment;
use serde::Serialize;
use std::borrow::Cow;
use url::Url;
pub use http::Method;
pub(crate) use spec::EndpointSpec;
pub enum RequestBody<'a> {
Json(String),
Raw(Vec<u8>),
MultiPart(&'a dyn MultipartBody),
}
pub enum MultipartPart {
Text(String),
Bytes(Vec<u8>),
}
pub trait MultipartBody {
fn parts(&self) -> Vec<(String, MultipartPart)>;
}
pub mod spec {
use super::*;
pub trait EndpointSpec {
const IS_RAW_BODY: bool = false;
type JsonResponse: ApiResult;
type ResponseType;
fn method(&self) -> Method;
fn path(&self) -> String;
#[inline]
fn query(&self) -> Option<String> {
None
}
#[inline]
fn body(&self) -> Option<RequestBody> {
None
}
fn url(&self, environment: &Environment) -> Url {
let mut url = Url::from(environment).join(&self.path()).unwrap();
url.set_query(self.query().as_deref());
url
}
fn content_type(&self) -> Option<Cow<'static, str>> {
match Self::body(self) {
Some(RequestBody::Json(_)) => Some(Cow::Borrowed("application/json")),
Some(RequestBody::Raw(_)) => Some(Cow::Borrowed("application/octet-stream")),
Some(RequestBody::MultiPart(_)) => Some(Cow::Borrowed("multipart/form-data")),
None => None,
}
}
}
}
impl<T: ApiResult, U: EndpointSpec> Endpoint<T> for U {}
pub trait Endpoint<ResultType: ApiResult>: EndpointSpec {}
#[inline]
pub fn serialize_query<Q: Serialize>(q: &Q) -> Option<String> {
serde_urlencoded::to_string(q).ok()
}