Skip to content

Commit bb6e3c2

Browse files
committed
feat(proxy): add support for x-www-form-urlencoded request payloads
This change inspects headers and uses RequestContent::FormUrlEncoded when required.
1 parent 8ddc861 commit bb6e3c2

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

crates/router/src/core/proxy.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use common_utils::{
99
use error_stack::ResultExt;
1010
use hyperswitch_interfaces::types::Response;
1111
use serde_json::Value;
12+
use std::collections::HashMap;
1213

1314
pub async fn proxy_core(
1415
state: SessionState,
@@ -83,17 +84,60 @@ fn extract_field_from_vault_data(vault_data: &Value, field_name: &str) -> Router
8384
}
8485
}
8586

87+
fn convert_value_to_form_data(value: Value) -> RouterResult<HashMap<String, String>> {
88+
match value {
89+
Value::Object(obj) => {
90+
obj.into_iter()
91+
.map(|(k, v)| {
92+
let val_str = match v {
93+
Value::String(s) => Ok(s),
94+
Value::Number(n) => Ok(n.to_string()),
95+
Value::Bool(b) => Ok(b.to_string()),
96+
Value::Null => Ok(String::new()),
97+
Value::Array(_) | Value::Object(_) => {
98+
serde_json::to_string(&v)
99+
.change_context(errors::ApiErrorResponse::InternalServerError)
100+
.attach_printable("Failed to serialize nested value")
101+
}
102+
}
103+
.map(|s| (k, s))
104+
})
105+
.collect::<Result<HashMap<_, _>, _>>()
106+
}
107+
_ => Err(errors::ApiErrorResponse::InternalServerError)
108+
.attach_printable("Request body must be a JSON object for form-urlencoded conversion"),
109+
}
110+
}
111+
86112
async fn execute_proxy_request(
87113
state: &SessionState,
88114
req_wrapper: &utils::ProxyRequestWrapper,
89115
processed_body: Value,
90116
) -> RouterResult<Response> {
117+
118+
let headers = req_wrapper.get_headers();
119+
let is_form_urlencoded = headers
120+
.iter()
121+
.find(|(key, _)| key.eq_ignore_ascii_case("content-type"))
122+
.map(|(_, value)| {
123+
value.clone().into_inner()
124+
.eq_ignore_ascii_case("application/x-www-form-urlencoded")
125+
})
126+
.unwrap_or(false);
127+
128+
let request_body = if is_form_urlencoded {
129+
convert_value_to_form_data(processed_body)
130+
.map(|form_data| request::RequestContent::FormUrlEncoded(Box::new(form_data)))?
131+
} else {
132+
request::RequestContent::Json(Box::new(processed_body))
133+
};
134+
91135
let request = RequestBuilder::new()
92136
.method(req_wrapper.get_method())
93137
.attach_default_headers()
94138
.headers(req_wrapper.get_headers())
95139
.url(req_wrapper.get_destination_url())
96-
.set_body(request::RequestContent::Json(Box::new(processed_body)))
140+
.set_body(request_body)
97141
.build();
98142

99143
let response = services::call_connector_api(state, request, "proxy")

0 commit comments

Comments
 (0)