Skip to content

Commit b7c0257

Browse files
committed
fix: urlencode fields when content-type is application/x-www-form-urlencoded (fixes #24)
1 parent e5a7ea6 commit b7c0257

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

src/plugins/http/mod.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use async_trait::async_trait;
44
use ctor::ctor;
55
use rand::seq::SliceRandom;
66
use reqwest::{
7-
header::{HeaderMap, HeaderName, HeaderValue},
7+
header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE, COOKIE, USER_AGENT},
88
multipart, redirect, Client, Method, RequestBuilder, Response,
99
};
1010
use url::Url;
@@ -150,12 +150,12 @@ impl HTTP {
150150
&self,
151151
creds: &Credentials,
152152
csrf: Option<csrf::Token>,
153-
mut request: RequestBuilder,
153+
mut builder: RequestBuilder,
154154
) -> RequestBuilder {
155155
let mut do_body = true;
156156
if self.strategy == Strategy::BasicAuth {
157157
// set basic authentication data
158-
request = request.basic_auth(&creds.username, Some(&creds.password));
158+
builder = builder.basic_auth(&creds.username, Some(&creds.password));
159159
} else if self.strategy == Strategy::Form {
160160
// set form data
161161
let fields = payload::parse_fields(self.payload.as_ref(), creds).unwrap();
@@ -170,7 +170,7 @@ impl HTTP {
170170
form = form.text(token.name.clone(), token.value.clone());
171171
}
172172

173-
request = request.multipart(form);
173+
builder = builder.multipart(form);
174174

175175
// we already added the --http-body value as fields
176176
do_body = false;
@@ -179,35 +179,41 @@ impl HTTP {
179179
// do we have any fields left to add?
180180
if do_body && self.payload.is_some() {
181181
if method_requires_payload(&self.method) {
182-
// add as body
183-
let mut body = payload::parse_body(self.payload.as_ref(), creds).unwrap();
182+
// check if we have to urlencode fields
183+
if self.headers.get(CONTENT_TYPE).unwrap() == "application/x-www-form-urlencoded" {
184+
let mut form_fields =
185+
payload::parse_fields(self.payload.as_ref(), creds).unwrap();
184186

185-
// handle csrf
186-
if let Some(token) = csrf.as_ref() {
187-
body.push_str(&format!("&{}={}", token.name, token.value));
188-
}
187+
// handle csrf
188+
if let Some(token) = csrf.as_ref() {
189+
form_fields.push((token.name.to_owned(), token.value.to_owned()));
190+
}
189191

190-
// log::info!("http.body={}", &body);
191-
request = request.body(body);
192-
// check if Content-Type is set already, if not set default (tnx to @zip609)
193-
if !self.headers.contains_key("Content-Type") {
194-
request = request.header("Content-Type", "application/x-www-form-urlencoded");
192+
builder = builder.form(&form_fields);
193+
} else {
194+
// add as raw body
195+
let mut body = payload::parse_body(self.payload.as_ref(), creds).unwrap();
196+
// handle csrf
197+
if let Some(token) = csrf.as_ref() {
198+
body.push_str(&format!("&{}={}", token.name, token.value));
199+
}
200+
builder = builder.body(body);
195201
}
196202
} else {
197203
// add as query string
198-
let mut query = payload::parse_fields(self.payload.as_ref(), creds).unwrap();
204+
let mut query_fields = payload::parse_fields(self.payload.as_ref(), creds).unwrap();
199205

200206
// handle csrf
201207
if let Some(token) = csrf.as_ref() {
202-
query.push((token.name.clone(), token.value.clone()));
208+
query_fields.push((token.name.clone(), token.value.clone()));
203209
}
204210

205211
// log::info!("http.query={:?}", &query);
206-
request = request.query(&query);
212+
builder = builder.query(&query_fields);
207213
}
208214
}
209215

210-
request
216+
builder
211217
}
212218

213219
async fn is_success(&self, response: Response) -> Option<Success> {
@@ -216,7 +222,7 @@ impl HTTP {
216222
return None;
217223
}
218224

219-
let content_type = if let Some(ctype) = response.headers().get("content-type") {
225+
let content_type = if let Some(ctype) = response.headers().get(CONTENT_TYPE) {
220226
ctype
221227
.to_str()
222228
.unwrap()
@@ -259,7 +265,7 @@ impl HTTP {
259265

260266
if self.random_ua {
261267
headers.append(
262-
"User-Agent",
268+
USER_AGENT,
263269
HeaderValue::from_str(ua::USER_AGENTS.choose(&mut rand::thread_rng()).unwrap())
264270
.unwrap(),
265271
);
@@ -305,7 +311,7 @@ impl HTTP {
305311
if let Some(token) = token.as_ref() {
306312
// set session cookie for CSRF
307313
if !token.cookie.is_empty() {
308-
headers.append("Cookie", HeaderValue::from_str(&token.cookie).unwrap());
314+
headers.append(COOKIE, HeaderValue::from_str(&token.cookie).unwrap());
309315
}
310316
}
311317

@@ -323,12 +329,11 @@ impl HTTP {
323329

324330
// setup body
325331
request = self.setup_request_body(creds, csrf_token, request);
326-
327332
// execute
328333
match request.send().await {
329334
Err(e) => Err(e.to_string()),
330335
Ok(res) => {
331-
let cookie = if let Some(cookie) = res.headers().get("cookie") {
336+
let cookie = if let Some(cookie) = res.headers().get(COOKIE) {
332337
cookie.to_str().unwrap().to_owned()
333338
} else {
334339
"".to_owned()
@@ -447,6 +452,14 @@ impl Plugin for HTTP {
447452
);
448453
}
449454

455+
// check if Content-Type is set already, if not set default (tnx to @zip609)
456+
if !self.headers.contains_key("Content-Type") {
457+
self.headers.insert(
458+
CONTENT_TYPE,
459+
HeaderValue::from_static("application/x-www-form-urlencoded"),
460+
);
461+
}
462+
450463
// check that a payload was provided if needed
451464
if method_requires_payload(&self.method) && opts.http.http_payload.is_none() {
452465
return Err(format!(

0 commit comments

Comments
 (0)