simple_request/
request.rs

1use hyper::body::Bytes;
2#[cfg(feature = "basic-auth")]
3use hyper::header::HeaderValue;
4pub use http_body_util::Full;
5
6#[cfg(feature = "basic-auth")]
7use crate::Error;
8
9#[derive(Debug)]
10pub struct Request {
11  pub(crate) request: hyper::Request<Full<Bytes>>,
12  pub(crate) response_size_limit: Option<usize>,
13}
14
15impl Request {
16  #[cfg(feature = "basic-auth")]
17  fn username_password_from_uri(&self) -> Result<(String, String), Error> {
18    if let Some(authority) = self.request.uri().authority() {
19      let authority = authority.as_str();
20      if authority.contains('@') {
21        // Decode the username and password from the URI
22        let mut userpass = authority.split('@').next().unwrap().to_string();
23
24        let mut userpass_iter = userpass.split(':');
25        let username = userpass_iter.next().unwrap().to_string();
26        let password = userpass_iter.next().map_or_else(String::new, str::to_string);
27        zeroize::Zeroize::zeroize(&mut userpass);
28
29        return Ok((username, password));
30      }
31    }
32    Err(Error::InvalidUri)
33  }
34
35  #[cfg(feature = "basic-auth")]
36  pub fn basic_auth(&mut self, username: &str, password: &str) {
37    use zeroize::Zeroize;
38    use base64ct::{Encoding, Base64};
39
40    let mut formatted = format!("{username}:{password}");
41    let mut encoded = Base64::encode_string(formatted.as_bytes());
42    formatted.zeroize();
43    self.request.headers_mut().insert(
44      hyper::header::AUTHORIZATION,
45      HeaderValue::from_str(&format!("Basic {encoded}"))
46        .expect("couldn't form header from base64-encoded string"),
47    );
48    encoded.zeroize();
49  }
50
51  #[cfg(feature = "basic-auth")]
52  pub fn basic_auth_from_uri(&mut self) -> Result<(), Error> {
53    let (mut username, mut password) = self.username_password_from_uri()?;
54    self.basic_auth(&username, &password);
55
56    use zeroize::Zeroize;
57    username.zeroize();
58    password.zeroize();
59
60    Ok(())
61  }
62
63  #[cfg(feature = "basic-auth")]
64  pub fn with_basic_auth(&mut self) {
65    let _ = self.basic_auth_from_uri();
66  }
67
68  /// Set a size limit for the response.
69  ///
70  /// This may be exceeded by a single HTTP frame and accordingly isn't perfect.
71  pub fn set_response_size_limit(&mut self, response_size_limit: Option<usize>) {
72    self.response_size_limit = response_size_limit;
73  }
74}
75
76impl From<hyper::Request<Full<Bytes>>> for Request {
77  fn from(request: hyper::Request<Full<Bytes>>) -> Request {
78    Request { request, response_size_limit: None }
79  }
80}