From e5596a15e0141045ba81d8a085cacc8cf0401715 Mon Sep 17 00:00:00 2001
From: Maaz Ahmed <maaz.a@subcom.tech>
Date: Fri, 29 Dec 2023 05:38:38 +0000
Subject: [PATCH] feat: query_raw method that returns a raw response

Instead of returning deserialized data, this method returns reqwest::Response, giving the user more control.
---
 Cargo.lock    |  8 ++++----
 Cargo.toml    |  2 +-
 src/lib.rs    | 30 +++++++++++++++++++++++++-----
 src/result.rs | 18 ++++++++++++++----
 tests/api.rs  |  8 ++++++++
 5 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7cefca4..c7466bb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -617,9 +617,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.6.4"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "mime"
@@ -842,9 +842,9 @@ dependencies = [
 
 [[package]]
 name = "prometheus-http-query"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7849dd7319357e220886589ea0a0760ff138cde2eedfbbfd2708caee0b15dfc"
+checksum = "5064f9bd466079eb96e7e8a920506c26053a040ee0a388c8f8e9280a50f5599a"
 dependencies = [
  "enum-as-inner",
  "mime",
diff --git a/Cargo.toml b/Cargo.toml
index 6a75abc..a9e4422 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 enum-as-inner = "0.6.0"
-prometheus-http-query = "0.8.0"
+prometheus-http-query = "0.8.1"
 reqwest = "0.11.22"
 url = "2.5.0"
 serde = { version = "1.0.193", optional = true }
diff --git a/src/lib.rs b/src/lib.rs
index 1318329..0be306e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -12,7 +12,7 @@ use std::fmt::Display;
 use prometheus_http_query::Client;
 use query::{ops::Operable, IntoQuery};
 use reqwest::header::HeaderValue;
-use result::{IntoQryResult, QryResult};
+use result::{IntoResult, QryResult, RawResult};
 use seal::Sealed;
 use url::Url;
 
@@ -86,8 +86,28 @@ impl QueryManager {
             builder = builder.timeout(*timeout);
         }
         match self.method {
-            Method::Get => builder.get().await.into_qry_result(),
-            Method::Post => builder.post().await.into_qry_result(),
+            Method::Get => builder.get().await.into_result(),
+            Method::Post => builder.post().await.into_result(),
+        }
+    }
+
+    /// Send a query to the Prometheus server and retreive raw response ([`reqwest::Response`])
+    ///
+    /// This method accepts any type that implements the `IntoQuery` trait.
+    /// The trait is implemented for `&str`, `String`, `&String`, and __mquery's__
+    /// internal types such as [`query::Metric`], [`query::Scalar`] and others that result
+    /// from the query builder API.
+    pub async fn query_raw<Q: IntoQuery>(&self, query: Q) -> RawResult {
+        let mut builder = self.client.query(query.into_query().as_ref());
+        if let Some((name, val)) = self.auth.get_header() {
+            builder = builder.header(name, val);
+        }
+        if let Some(timeout) = self.timeout.as_ref() {
+            builder = builder.timeout(*timeout);
+        }
+        match self.method {
+            Method::Get => builder.get_raw().await.into_result(),
+            Method::Post => builder.post_raw().await.into_result(),
         }
     }
 
@@ -146,8 +166,8 @@ impl QueryManager {
             builder = builder.timeout(*timeout);
         }
         match self.method {
-            Method::Get => builder.get().await.into_qry_result(),
-            Method::Post => builder.post().await.into_qry_result(),
+            Method::Get => builder.get().await.into_result(),
+            Method::Post => builder.post().await.into_result(),
         }
     }
 }
diff --git a/src/result.rs b/src/result.rs
index 56b25ea..6849333 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -11,14 +11,24 @@ use prometheus_http_query::{error, response};
 use std::fmt::{self, Display};
 
 pub type QryResult = std::result::Result<Data, Error>;
+pub type RawResult = std::result::Result<reqwest::Response, Error>;
 
 /// Internal trait used for converting the `prometheus-http-query` crate's query result into the internal result type
-pub(crate) trait IntoQryResult {
-    fn into_qry_result(self) -> QryResult;
+pub(crate) trait IntoResult {
+    type Result;
+    fn into_result(self) -> Self::Result;
 }
 
-impl IntoQryResult for Result<response::PromqlResult, error::Error> {
-    fn into_qry_result(self) -> QryResult {
+impl IntoResult for Result<response::PromqlResult, error::Error> {
+    type Result = QryResult;
+    fn into_result(self) -> Self::Result {
+        self.map(|r| r.into()).map_err(|e| e.into())
+    }
+}
+
+impl IntoResult for Result<reqwest::Response, error::Error> {
+    type Result = RawResult;
+    fn into_result(self) -> Self::Result {
         self.map(|r| r.into()).map_err(|e| e.into())
     }
 }
diff --git a/tests/api.rs b/tests/api.rs
index da2fe67..a11d853 100644
--- a/tests/api.rs
+++ b/tests/api.rs
@@ -41,6 +41,14 @@ async fn multi_queries() {
     assert!(res.len() == 2);
 }
 
+#[tokio::test]
+async fn raw_response() {
+    QueryManager::new(utils::URL.parse().unwrap())
+        .query_raw("metric")
+        .await
+        .unwrap();
+}
+
 fn get_url_token() -> (String, String) {
     dotenv::dotenv().expect("No .env file found in working dir");
     (
-- 
GitLab