Skip to content

Commit d1f7c12

Browse files
authored
fix: use --data-urlencode for form-urlencoded curl snippets (#315)
| 🚥 Resolves CX-2935 | | :------------------- | ## 🧰 Changes Curl snippets for `application/x-www-form-urlencoded` endpoints were using `--data` instead of `--data-urlencode`. This meant values with special characters (spaces, ampersands, etc.) would break when copy-paste and execute in a terminal. The old code only checked if the param **name** needed encoding and picked the flag based on that, while ignoring the value. The fix: always use `--data-urlencode` for form-urlencoded params. It behaves identically to `--data` when there's nothing to encode, so no downside. Note that the form data values are never pre-encoded though, since `oas-to-har` just calls `String()` on them. This only affects the code snippet shown to developers, the "Try It" executor uses `fetch-har` with `URLSearchParams` which already encodes correctly. ## 🧬 QA & Testing Find an endpoint with `application/x-www-form-urlencoded` content type, check that the curl snippet uses `--data-urlencode` instead of `--data` ### Correct Example ```zsh curl --request POST \ --url https://httpbin.org/anything \ --header 'content-type: application/x-www-form-urlencoded' \ --data-urlencode 'foo=bar' \ --data-urlencode 'query=hello world' \ --data-urlencode 'filter=status=active&type=user' ``` ```json { "args": {}, "data": "", "files": {}, "form": { "filter": "status=active&type=user", "foo": "bar", "query": "hello world" }, "headers": { "Accept": "*/*", "Content-Length": "62", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "curl/8.7.1", "X-Amzn-Trace-Id": "Root=1-69942c21-2119bf28086765883dfaa673" }, "json": null, "method": "POST", "origin": "1.1.1.1", "url": "https://httpbin.org/anything" } ``` ### Incorrect Example ```zsh curl --request POST \ --url https://httpbin.org/anything \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'foo=bar' \ --data 'query=hello world' \ --data 'filter=status=active&type=user' ``` ```json { "args": {}, "data": "", "files": {}, "form": { "filter": "status=active", "foo": "bar", "query": "hello world", "type": "user" }, "headers": { "Accept": "*/*", "Content-Length": "56", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "curl/8.7.1", "X-Amzn-Trace-Id": "Root=1-69942d09-4ad6930b09907b011e840bec" }, "json": null, "method": "POST", "origin": "1.1.1.1", "url": "https://httpbin.org/anything" } ```
1 parent ae49e9f commit d1f7c12

7 files changed

Lines changed: 27 additions & 9 deletions

File tree

src/targets/shell/curl/client.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ runCustomFixtures({
8888
options: {},
8989
expected: 'urlencode.sh',
9090
},
91+
{
92+
it: 'should use --data-urlencode for form-urlencoded params with special characters in values',
93+
input: {
94+
...applicationFormEncoded.log.entries[0].request,
95+
postData: {
96+
mimeType: 'application/x-www-form-urlencoded',
97+
params: [
98+
{ name: 'query', value: 'hello world' },
99+
{ name: 'filter', value: 'status=active&type=user' },
100+
],
101+
},
102+
} as Request,
103+
options: {},
104+
expected: 'urlencode-values.sh',
105+
},
91106
{
92107
it: 'should send JSON-encoded data with single quotes within a HEREDOC',
93108
input: {

src/targets/shell/curl/client.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,9 @@ export const curl: Client<CurlOptions> = {
138138
case 'application/x-www-form-urlencoded':
139139
if (postData.params) {
140140
postData.params.forEach(param => {
141-
const unencoded = param.name;
142141
const encoded = encodeURIComponent(param.name);
143-
const needsEncoding = encoded !== unencoded;
144-
const name = needsEncoding ? encoded : unencoded;
145-
const flag = binary ? '--data-binary' : needsEncoding ? '--data-urlencode' : arg('data');
142+
const name = encoded !== param.name ? encoded : param.name;
143+
const flag = binary ? '--data-binary' : '--data-urlencode';
146144
push(`${flag} ${quote(`${name}=${param.value}`)}`);
147145
});
148146
} else {
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
curl --request POST \
22
--url https://httpbin.org/anything \
33
--header 'content-type: application/x-www-form-urlencoded' \
4-
--data foo=bar \
5-
--data hello=world
4+
--data-urlencode foo=bar \
5+
--data-urlencode hello=world

src/targets/shell/curl/fixtures/custom-indentation.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ curl --request POST \
33
@--header 'accept: application/json' \
44
@--header 'content-type: application/x-www-form-urlencoded' \
55
@--cookie 'foo=bar; bar=baz' \
6-
@--data foo=bar
6+
@--data-urlencode foo=bar

src/targets/shell/curl/fixtures/full.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ curl --request POST \
33
--header 'accept: application/json' \
44
--header 'content-type: application/x-www-form-urlencoded' \
55
--cookie 'foo=bar; bar=baz' \
6-
--data foo=bar
6+
--data-urlencode foo=bar
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
curl -X POST 'https://httpbin.org/anything?foo=bar&foo=baz&baz=abc&key=value' -H 'accept: application/json' -H 'content-type: application/x-www-form-urlencoded' -b 'foo=bar; bar=baz' -d foo=bar
1+
curl -X POST 'https://httpbin.org/anything?foo=bar&foo=baz&baz=abc&key=value' -H 'accept: application/json' -H 'content-type: application/x-www-form-urlencoded' -b 'foo=bar; bar=baz' --data-urlencode foo=bar
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
curl --request POST \
2+
--url https://httpbin.org/anything \
3+
--header 'content-type: application/x-www-form-urlencoded' \
4+
--data-urlencode 'query=hello world' \
5+
--data-urlencode 'filter=status=active&type=user'

0 commit comments

Comments
 (0)