brawl_api/http/
request.rs

1//! Contains the `Request` class, used for building requests to the API.
2
3use reqwest::blocking::{
4    RequestBuilder
5};
6
7#[cfg(feature = "async")]
8use reqwest::{
9    RequestBuilder as ARequestBuilder
10};
11
12use reqwest::{
13    header::{
14        HeaderMap,
15        USER_AGENT, AUTHORIZATION, CONTENT_TYPE, CONTENT_LENGTH,
16        HeaderValue,
17    },
18    Url,
19    Method,
20};
21use crate::error::{Result, Error};
22use crate::http::Client;
23use crate::constants::USER_AGENT as B_API_USER_AGENT;
24
25
26/// A struct representing a request to some endpoint.
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct Request<'a> {
29
30    /// The body of the request. (Note that this is rarely, if ever, used in this lib.)
31    pub body: Option<&'a [u8]>,
32
33    /// The headers of the request.
34    pub headers: Option<HeaderMap>,
35
36    /// The endpoint (e.g. /players/%23sometag).
37    pub endpoint: String,
38
39    /// The method (GET/POST/...). Defaults to GET
40    pub method: Method,
41}
42
43impl<'a> Default for Request<'a> {
44    /// Returns a default `Request` instance, with initial values.
45    ///
46    /// # Examples
47    ///
48    /// ```rust
49    /// use brawl_api::http::request::Request;
50    /// use reqwest::Method;
51    ///
52    /// assert_eq!(
53    ///     Request::default(),
54    ///     Request {
55    ///         body: None,
56    ///         headers: None,
57    ///         endpoint: String::from(""),
58    ///         method: Method::GET,
59    ///     }
60    /// )
61    /// ```
62    fn default() -> Request<'a> {
63        Request {
64            body: None,
65            headers: None,
66            endpoint: String::from(""),
67            method: Method::GET,
68        }
69    }
70}
71
72// (Credits to Serenity lib for the useful HTTP bases)
73impl<'a> Request<'a> {
74    /// (For sync usage) Creates a (blocking) [`RequestBuilder`] (`reqwest` crate) instance.
75    ///
76    /// [`RequestBuilder`]: https://docs.rs/reqwest/*/reqwest/blocking/struct.RequestBuilder.html
77    pub fn build(&'a self, client: &Client) -> Result<RequestBuilder> {
78        let Request {
79            body,
80            headers: ref r_headers,
81            endpoint: ref r_endpoint,
82            ref method,
83        } = *self;
84
85        let mut builder = client.inner.request(
86            method.clone(),
87            Url::parse(r_endpoint).map_err(Error::Url)?,
88        );
89
90        if let Some(ref bytes) = body {  // body was provided
91            let b_vec = Vec::from(*bytes);
92            builder = builder.body(b_vec);
93        }
94
95        let key = &client.auth_key;
96
97        let key = if key.starts_with("Bearer ") {
98            key.clone()
99        } else {
100            format!("Bearer {}", key)
101        };
102
103        let mut headers = HeaderMap::with_capacity(3);
104        headers.insert(USER_AGENT, HeaderValue::from_static(&B_API_USER_AGENT));
105        headers.insert(AUTHORIZATION,
106                       HeaderValue::from_str(&key).map_err(Error::Authorization)?);
107        headers.insert(CONTENT_TYPE, HeaderValue::from_static(&"application/json"));
108        headers.insert(CONTENT_LENGTH, HeaderValue::from_static(&"0"));
109
110        if let Some(ref r_headers) = r_headers {
111            headers.extend(r_headers.clone());
112        }
113
114        builder = builder.headers(headers);
115
116        Ok(builder)
117    }
118
119    /// (For async usage) Creates a (non-blocking) [`RequestBuilder`] (`reqwest` crate) instance.
120    ///
121    /// [`RequestBuilder`]: https://docs.rs/reqwest/*/reqwest/struct.RequestBuilder.html
122    #[cfg(feature = "async")]
123    pub fn a_build(&'a self, client: &Client) -> Result<ARequestBuilder> {
124        let Request {
125            body,
126            headers: ref r_headers,
127            endpoint: ref r_endpoint,
128            ref method,
129        } = *self;
130
131        let mut builder = client.a_inner.request(
132            method.clone(),
133            Url::parse(r_endpoint).map_err(Error::Url)?,
134        );
135
136        if let Some(ref bytes) = body {  // body was provided
137            let b_vec = Vec::from(*bytes);
138            builder = builder.body(b_vec);
139        }
140
141        let key = &client.auth_key;
142
143        let key = if key.starts_with("Bearer ") {
144            key.clone()
145        } else {
146            format!("Bearer {}", key)  // add "Bearer " if missing.
147        };
148
149        let mut headers = HeaderMap::with_capacity(3);
150        headers.insert(USER_AGENT, HeaderValue::from_static(&B_API_USER_AGENT));
151        headers.insert(AUTHORIZATION,
152                       HeaderValue::from_str(&key).map_err(Error::Authorization)?);
153        headers.insert(CONTENT_TYPE, HeaderValue::from_static(&"application/json"));
154        headers.insert(CONTENT_LENGTH, HeaderValue::from_static(&"0"));
155
156        if let Some(ref r_headers) = r_headers {
157            headers.extend(r_headers.clone());
158        }
159
160        builder = builder.headers(headers);
161
162        Ok(builder)
163    }
164}