use crate::*;
use crate::client::*;
use crate::method::*;
use crate::response::*;
pub struct Request<'body>
{
pub(crate) method: Method,
pub(crate) url: Option<String>,
pub(crate) headers: Option<CurlList>,
pub(crate) redirect_limit: Option<usize>,
pub(crate) request_body: Option<Box<dyn std::io::Read + 'body>>,
pub(crate) proxy: Option<Proxy>,
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Proxy
{
Host(String),
UnixSocket(String),
}
pub(crate) struct CurlList
{
pub(crate) headers: *mut sys::curl_slist,
}
impl Drop for CurlList
{
fn drop(&mut self)
{
unsafe
{
sys::curl_slist_free_all(self.headers);
}
}
}
impl<'body> Request<'body>
{
pub fn new(method: Method, url: String) -> Request<'body>
{
Request
{
method,
url: Some(url),
headers: Some( CurlList{ headers: std::ptr::null_mut() } ),
redirect_limit: Some(10),
request_body: None,
proxy: None,
}
}
pub fn get(url: String) -> Self
{
Self::new(Method::GET, url)
}
pub fn post(url: String) -> Self
{
Self::new(Method::POST, url)
}
pub fn put(url: String) -> Self
{
Self::new(Method::PUT, url)
}
pub fn set_content_length(&mut self, l: u64)
{
self.set_header(crate::header::CONTENT_LENGTH, format!("{}",l));
}
pub fn content_length(mut self, l: u64) -> Self
{
self.set_content_length(l);
self
}
pub fn set_proxy(&mut self, proxy: impl Into<Option<Proxy>>)
{
self.proxy = proxy.into();
}
pub fn proxy(mut self, proxy: impl Into<Option<Proxy>>) -> Self
{
self.proxy = proxy.into();
self
}
pub fn set_header<K,V>(&mut self, k: K, v: V)
where K: AsRef<[u8]>, V: AsRef<[u8]>
{
let k = k.as_ref();
let v = v.as_ref();
let mut h: Vec<u8> = Vec::with_capacity(k.len() + 2 + v.len() + 1);
h.extend_from_slice(k);
h.extend_from_slice(b": ");
h.extend_from_slice(v);
h.push(b'\0');
unsafe
{
let l = sys::curl_slist_append(self.headers.as_ref().unwrap().headers, h.as_ptr() as *const _);
assert!(!l.is_null());
self.headers.as_mut().unwrap().headers = l;
}
}
pub fn header<K,V>(mut self, k: K, v: V)
-> Self
where K: AsRef<[u8]>, V: AsRef<[u8]>
{
self.set_header(k,v);
self
}
pub fn set_body<R: 'body>(&mut self, r: R)
where R: std::io::Read + 'body
{
self.request_body = Some(Box::new(r));
}
pub fn body<'b, R: 'b>(self, r: R)
-> Request<'b>
where R: std::io::Read + 'b
{
let request_body = Some(Box::new(r) as Box<dyn std::io::Read>);
let Request
{
method,
url,
headers,
redirect_limit,
proxy,
..
} = self;
Request
{
method: method,
url: url,
headers: headers,
redirect_limit: redirect_limit,
request_body,
proxy,
}
}
pub fn send(self) -> Result<Response>
{
Client::new()
.execute(self)
}
pub fn set_redirect_limit(&mut self, n: Option<usize>) -> &mut Self
{
self.redirect_limit = n;
self
}
pub fn redirect_limit(mut self, n: Option<usize>) -> Self
{
self.set_redirect_limit(n);
self
}
}