use crate::error::Result;
use crate::response::Response;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum Method {
#[default]
Get,
Post,
Put,
Patch,
Delete,
Head,
Options,
}
impl Method {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Get => "GET",
Self::Post => "POST",
Self::Put => "PUT",
Self::Patch => "PATCH",
Self::Delete => "DELETE",
Self::Head => "HEAD",
Self::Options => "OPTIONS",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Redirect {
#[default]
Follow,
Manual,
}
#[derive(Debug, Clone)]
pub struct Request {
pub(crate) method: Method,
pub(crate) url: String,
pub(crate) headers: Vec<(String, String)>,
pub(crate) cookies: Vec<(String, String)>,
pub(crate) form: Option<Vec<(String, String)>>,
pub(crate) redirect: Redirect,
}
impl Request {
#[must_use]
pub fn builder(url: impl Into<String>) -> RequestBuilder {
RequestBuilder {
inner: Request {
method: Method::Get,
url: url.into(),
headers: Vec::new(),
cookies: Vec::new(),
form: None,
redirect: Redirect::Follow,
},
}
}
pub(crate) fn cookie_header(&self) -> Option<String> {
if self.cookies.is_empty() {
return None;
}
Some(
self.cookies
.iter()
.map(|(k, v)| format!("{k}={v}"))
.collect::<Vec<_>>()
.join("; "),
)
}
#[cfg(target_arch = "wasm32")]
pub(crate) fn has_content_type(&self) -> bool {
self.headers
.iter()
.any(|(key, _)| key.eq_ignore_ascii_case("content-type"))
}
}
pub struct RequestBuilder {
inner: Request,
}
impl RequestBuilder {
#[must_use]
pub fn method(mut self, method: Method) -> Self {
self.inner.method = method;
self
}
#[must_use]
pub fn post(self) -> Self {
self.method(Method::Post)
}
#[must_use]
pub fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.inner.headers.push((key.into(), value.into()));
self
}
#[must_use]
pub fn cookie(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.inner.cookies.push((key.into(), value.into()));
self
}
#[must_use]
pub fn form(mut self, body: Vec<(String, String)>) -> Self {
self.inner.form = Some(body);
self
}
#[must_use]
pub fn redirect(mut self, redirect: Redirect) -> Self {
self.inner.redirect = redirect;
self
}
#[must_use]
pub fn build(self) -> Request {
self.inner
}
pub async fn send(self) -> Result<Response> {
crate::send(self.build()).await
}
}