aoss_curl/
lib.rs

1use anyhow::Result;
2use aws_credential_types::Credentials;
3use http_body_util::combinators::BoxBody;
4use http_body_util::BodyExt;
5use hyper::body::Bytes;
6use hyper::{Method, Request, Response};
7use hyper_rustls::HttpsConnectorBuilder;
8use hyper_util::client::legacy::Client as HttpClient;
9use hyper_util::rt::TokioExecutor;
10use std::time::SystemTime;
11
12use crate::config::{get_default_credentials, get_default_region};
13use crate::error::Error;
14use crate::error::Error::{BuildRequestError, ReadResponseError, SendRequestError};
15use crate::sigv4::sign_request;
16
17mod config;
18pub mod error;
19mod sigv4;
20
21/// Client for requesting to Amazon OpenSearch Service with SigV4
22pub struct Client {
23    uri: String,
24    method: Method,
25    body: String,
26    region: Option<String>,
27    profile: Option<String>,
28    home: Option<String>,
29}
30
31impl Client {
32    pub fn new(
33        uri: &str,
34        method: &Method,
35        body: &str,
36        region: Option<String>,
37        profile: Option<String>,
38        home: Option<String>,
39    ) -> Self {
40        Self {
41            uri: String::from(uri),
42            method: method.clone(),
43            body: String::from(body),
44            region,
45            profile,
46            home,
47        }
48    }
49
50    /// Request to Amazon OpenSearch Service with SigV4
51    pub async fn request(
52        &self,
53        credentials: Option<Credentials>,
54    ) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
55        let credentials = match credentials {
56            Some(r) => r,
57            None => get_default_credentials().await?,
58        };
59
60        let region = match self.region.clone() {
61            Some(r) => r,
62            None => get_default_region(self.profile.clone(), self.home.clone()).await?,
63        };
64
65        let mut request = Request::builder()
66            .header("Content-Type", "application/json")
67            .uri(self.uri.clone())
68            .method(self.method.clone())
69            .body(self.body.clone())
70            .map_err(BuildRequestError)?;
71
72        sign_request(SystemTime::now(), &region, "es", credentials, &mut request).await?;
73
74        let connector = HttpsConnectorBuilder::new()
75            .with_webpki_roots()
76            .https_only()
77            .enable_http1()
78            .build();
79
80        let response = HttpClient::builder(TokioExecutor::new())
81            .build(connector)
82            .request(request)
83            .await
84            .map_err(SendRequestError)?
85            .map(|i| i.map_err(ReadResponseError).boxed());
86
87        Ok(response)
88    }
89}