Skip to content

Commit 21be67a

Browse files
authored
refactor: move Request and RequestBuilder structs to common_utils crate (#2145)
1 parent a7a3f4f commit 21be67a

File tree

7 files changed

+227
-213
lines changed

7 files changed

+227
-213
lines changed

Cargo.lock

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/common_utils/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@ diesel = "2.1.0"
1919
error-stack = "0.3.1"
2020
futures = { version = "0.3.28", optional = true }
2121
hex = "0.4.3"
22+
http = "0.2.9"
2223
md5 = "0.7.0"
2324
nanoid = "0.4.0"
2425
once_cell = "1.18.0"
2526
quick-xml = { version = "0.28.2", features = ["serialize"] }
2627
rand = "0.8.5"
2728
regex = "1.8.4"
29+
reqwest = { version = "0.11.18", features = ["json", "native-tls", "gzip", "multipart"] }
2830
ring = { version = "0.16.20", features = ["std"] }
2931
serde = { version = "1.0.163", features = ["derive"] }
3032
serde_json = "1.0.96"
3133
serde_urlencoded = "0.7.1"
3234
signal-hook = { version = "0.3.15", optional = true }
35+
strum = { version = "0.24.1", features = ["derive"] }
3336
thiserror = "1.0.40"
3437
time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
3538
tokio = { version = "1.28.2", features = ["macros", "rt-multi-thread"], optional = true }

crates/common_utils/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub mod errors;
99
pub mod ext_traits;
1010
pub mod fp_utils;
1111
pub mod pii;
12+
#[allow(missing_docs)] // Todo: add docs
13+
pub mod request;
1214
#[cfg(feature = "signals")]
1315
pub mod signals;
1416
pub mod validation;

crates/common_utils/src/request.rs

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
use masking::{Maskable, Secret};
2+
#[cfg(feature = "logs")]
3+
use router_env::logger;
4+
use serde::{Deserialize, Serialize};
5+
6+
use crate::errors;
7+
8+
pub type Headers = std::collections::HashSet<(String, Maskable<String>)>;
9+
10+
#[derive(
11+
Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, strum::Display, strum::EnumString,
12+
)]
13+
#[serde(rename_all = "UPPERCASE")]
14+
#[strum(serialize_all = "UPPERCASE")]
15+
pub enum Method {
16+
Get,
17+
Post,
18+
Put,
19+
Delete,
20+
}
21+
22+
#[derive(Deserialize, Serialize, Debug)]
23+
pub enum ContentType {
24+
Json,
25+
FormUrlEncoded,
26+
FormData,
27+
}
28+
29+
fn default_request_headers() -> [(String, Maskable<String>); 1] {
30+
use http::header;
31+
32+
[(header::VIA.to_string(), "HyperSwitch".to_string().into())]
33+
}
34+
35+
#[derive(Debug)]
36+
pub struct Request {
37+
pub url: String,
38+
pub headers: Headers,
39+
pub payload: Option<Secret<String>>,
40+
pub method: Method,
41+
pub content_type: Option<ContentType>,
42+
pub certificate: Option<String>,
43+
pub certificate_key: Option<String>,
44+
pub form_data: Option<reqwest::multipart::Form>,
45+
}
46+
47+
impl Request {
48+
pub fn new(method: Method, url: &str) -> Self {
49+
Self {
50+
method,
51+
url: String::from(url),
52+
headers: std::collections::HashSet::new(),
53+
payload: None,
54+
content_type: None,
55+
certificate: None,
56+
certificate_key: None,
57+
form_data: None,
58+
}
59+
}
60+
61+
pub fn set_body(&mut self, body: String) {
62+
self.payload = Some(body.into());
63+
}
64+
65+
pub fn add_default_headers(&mut self) {
66+
self.headers.extend(default_request_headers());
67+
}
68+
69+
pub fn add_header(&mut self, header: &str, value: Maskable<String>) {
70+
self.headers.insert((String::from(header), value));
71+
}
72+
73+
pub fn add_content_type(&mut self, content_type: ContentType) {
74+
self.content_type = Some(content_type);
75+
}
76+
77+
pub fn add_certificate(&mut self, certificate: Option<String>) {
78+
self.certificate = certificate;
79+
}
80+
81+
pub fn add_certificate_key(&mut self, certificate_key: Option<String>) {
82+
self.certificate = certificate_key;
83+
}
84+
85+
pub fn set_form_data(&mut self, form_data: reqwest::multipart::Form) {
86+
self.form_data = Some(form_data);
87+
}
88+
}
89+
90+
#[derive(Debug)]
91+
pub struct RequestBuilder {
92+
pub url: String,
93+
pub headers: Headers,
94+
pub payload: Option<Secret<String>>,
95+
pub method: Method,
96+
pub content_type: Option<ContentType>,
97+
pub certificate: Option<String>,
98+
pub certificate_key: Option<String>,
99+
pub form_data: Option<reqwest::multipart::Form>,
100+
}
101+
102+
impl RequestBuilder {
103+
pub fn new() -> Self {
104+
Self {
105+
method: Method::Get,
106+
url: String::with_capacity(1024),
107+
headers: std::collections::HashSet::new(),
108+
payload: None,
109+
content_type: None,
110+
certificate: None,
111+
certificate_key: None,
112+
form_data: None,
113+
}
114+
}
115+
116+
pub fn url(mut self, url: &str) -> Self {
117+
self.url = url.into();
118+
self
119+
}
120+
121+
pub fn method(mut self, method: Method) -> Self {
122+
self.method = method;
123+
self
124+
}
125+
126+
pub fn attach_default_headers(mut self) -> Self {
127+
self.headers.extend(default_request_headers());
128+
self
129+
}
130+
131+
pub fn header(mut self, header: &str, value: &str) -> Self {
132+
self.headers.insert((header.into(), value.into()));
133+
self
134+
}
135+
136+
pub fn headers(mut self, headers: Vec<(String, Maskable<String>)>) -> Self {
137+
let mut h = headers.into_iter().map(|(h, v)| (h, v));
138+
self.headers.extend(&mut h);
139+
self
140+
}
141+
142+
pub fn form_data(mut self, form_data: Option<reqwest::multipart::Form>) -> Self {
143+
self.form_data = form_data;
144+
self
145+
}
146+
147+
pub fn body(mut self, option_body: Option<RequestBody>) -> Self {
148+
self.payload = option_body.map(RequestBody::get_inner_value);
149+
self
150+
}
151+
152+
pub fn content_type(mut self, content_type: ContentType) -> Self {
153+
self.content_type = Some(content_type);
154+
self
155+
}
156+
157+
pub fn add_certificate(mut self, certificate: Option<String>) -> Self {
158+
self.certificate = certificate;
159+
self
160+
}
161+
162+
pub fn add_certificate_key(mut self, certificate_key: Option<String>) -> Self {
163+
self.certificate_key = certificate_key;
164+
self
165+
}
166+
167+
pub fn build(self) -> Request {
168+
Request {
169+
method: self.method,
170+
url: self.url,
171+
headers: self.headers,
172+
payload: self.payload,
173+
content_type: self.content_type,
174+
certificate: self.certificate,
175+
certificate_key: self.certificate_key,
176+
form_data: self.form_data,
177+
}
178+
}
179+
}
180+
181+
impl Default for RequestBuilder {
182+
fn default() -> Self {
183+
Self::new()
184+
}
185+
}
186+
187+
#[derive(Clone, Debug)]
188+
pub struct RequestBody(Secret<String>);
189+
190+
impl RequestBody {
191+
pub fn log_and_get_request_body<T, F>(
192+
body: T,
193+
encoder: F,
194+
) -> errors::CustomResult<Self, errors::ParsingError>
195+
where
196+
F: FnOnce(T) -> errors::CustomResult<String, errors::ParsingError>,
197+
T: std::fmt::Debug,
198+
{
199+
#[cfg(feature = "logs")]
200+
logger::info!(connector_request_body=?body);
201+
Ok(Self(Secret::new(encoder(body)?)))
202+
}
203+
pub fn get_inner_value(request_body: Self) -> Secret<String> {
204+
request_body.0
205+
}
206+
}

crates/router/src/services/api.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ use actix_web::{body, HttpRequest, HttpResponse, Responder, ResponseError};
1414
use api_models::enums::CaptureMethod;
1515
pub use client::{proxy_bypass_urls, ApiClient, MockApiClient, ProxyClient};
1616
use common_utils::errors::ReportSwitchExt;
17+
pub use common_utils::request::{ContentType, Method, Request, RequestBuilder};
1718
use error_stack::{report, IntoReport, Report, ResultExt};
1819
use masking::{ExposeOptionInterface, PeekInterface};
1920
use router_env::{instrument, tracing, Tag};
2021
use serde::Serialize;
2122
use serde_json::json;
2223

23-
use self::request::{ContentType, HeaderExt, RequestBuilderExt};
24-
pub use self::request::{Method, Request, RequestBuilder};
24+
use self::request::{HeaderExt, RequestBuilderExt};
2525
use crate::{
2626
configs::settings::{Connectors, Settings},
2727
consts,
@@ -1229,9 +1229,9 @@ pub fn build_redirection_form(
12291229
f.method='POST';
12301230
i.name = 'authentication_response';
12311231
i.value = JSON.stringify(payload);
1232-
f.appendChild(i);
1232+
f.appendChild(i);
12331233
f.body = JSON.stringify(payload);
1234-
document.body.appendChild(f);
1234+
document.body.appendChild(f);
12351235
f.submit();
12361236
}}
12371237
}});

0 commit comments

Comments
 (0)