1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use reqwest::{Client, Response, StatusCode};
pub use reqwest::{Method, RequestBuilder};
use result::{BestbuyResult, ErrorKind};
use serde::Deserialize;
use serde_json;

pub struct BestbuyClient {
  http: Client,
  token: String,
}

impl BestbuyClient {
  pub fn new(token: &str) -> Self {
    Self::with_http_client(token, Client::new())
  }

  pub fn with_http_client(token: &str, http: Client) -> Self {
    Self {
      token: token.to_owned(),
      http,
    }
  }

  pub fn request(&self, method: Method, path: &str) -> RequestBuilder {
    use reqwest::{header::{qitem, Accept, Authorization, CacheControl, CacheDirective},
                  mime};
    let mut b = self
      .http
      .request(method, &format!("https://marketplace.bestbuy.ca{}", path));
    b.header(Authorization(self.token.clone()))
      .header(CacheControl(vec![CacheDirective::NoCache]))
      .header(Accept(vec![qitem(mime::APPLICATION_JSON)]));
    b
  }
}

pub trait BestbuyResponse {
  fn get_response<T: for<'de> Deserialize<'de>>(&mut self) -> BestbuyResult<T>;
}

impl BestbuyResponse for Response {
  fn get_response<T: for<'de> Deserialize<'de>>(&mut self) -> BestbuyResult<T> {
    let body = self.text()?;

    if self.status() != StatusCode::Ok {
      return Err(ErrorKind::Request(self.url().to_string(), self.status(), body).into());
    }

    match serde_json::from_str(&body) {
      Ok(v) => Ok(v),
      Err(err) => return Err(ErrorKind::Deserialize(err.to_string(), body).into()),
    }
  }
}