use http::header::{HeaderValue, AUTHORIZATION, CONTENT_TYPE};
use http::{Method, Uri};
use oauth_credentials::Token;
use serde::de;
use crate::response::{RawResponseFuture, ResponseFuture};
use crate::traits::HttpService;
pub trait RawRequest: oauth::Request {
const METHOD: Method;
const URI: &'static str;
fn send_raw<C, T, S, B>(
&self,
token: &Token<C, T>,
http: &mut S,
) -> RawResponseFuture<S::Future>
where
C: AsRef<str>,
T: AsRef<str>,
S: HttpService<B>,
B: From<Vec<u8>>,
{
let req = prepare_request(&Self::METHOD, Self::URI, self, token.as_ref());
RawResponseFuture::new(req.map(Into::into), http)
}
}
pub trait Request: RawRequest {
type Data: de::DeserializeOwned;
fn send<C, T, S, B>(
&self,
token: &Token<C, T>,
http: &mut S,
) -> ResponseFuture<Self::Data, S::Future>
where
C: AsRef<str>,
T: AsRef<str>,
S: HttpService<B>,
B: From<Vec<u8>>,
{
self.send_raw(token, http).into()
}
}
fn prepare_request<R>(
method: &Method,
uri: &'static str,
req: &R,
token: Token<&str, &str>,
) -> http::Request<Vec<u8>>
where
R: oauth::Request + ?Sized,
{
let form = method == Method::POST;
let mut oauth = oauth::Builder::new(token.client(), oauth::HmacSha1);
oauth.token(token.token());
let authorization = oauth.build(method.as_str(), uri, req);
let http = http::Request::builder()
.method(method)
.header(AUTHORIZATION, authorization);
if form {
let data = oauth::to_form_urlencoded(req).into_bytes();
http.uri(Uri::from_static(uri))
.header(
CONTENT_TYPE,
HeaderValue::from_static("application/x-www-form-urlencoded"),
)
.body(data)
.unwrap()
} else {
let uri = oauth::to_uri_query(uri.to_owned(), req);
http.uri(uri).body(Vec::default()).unwrap()
}
}