Skip to content

Commit b6e1afd

Browse files
committed
curl: add --url-query
This option adds a piece of data, usually a name + value pair, to the end of the URL query part. The syntax is identical to that used for --data-urlencode with one extension: If the argument starts with a '+' (plus), the rest of the string is provided as-is unencoded. This allows users to "build" query parts with options and URL encoding even when not doing GET requests, which the already provided option -G (--get) is limited to. This idea was born in a Twitter thread. Closes #9691
1 parent 43232b5 commit b6e1afd

8 files changed

+70
-4
lines changed

docs/cmdline-opts/Makefile.inc

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ DPAGES = \
265265
unix-socket.d \
266266
upload-file.d \
267267
url.d \
268+
url-query.d \
268269
use-ascii.d \
269270
user-agent.d \
270271
user.d \

docs/cmdline-opts/url-query.d

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
2+
SPDX-License-Identifier: curl
3+
Long: url-query
4+
Arg: <data>
5+
Help: Add a URL query part
6+
Protocols: all
7+
See-also: data-urlencode get
8+
Added: 7.87.0
9+
Category: http post upload
10+
Example: --url-query name=val $URL
11+
Example: --url-query =encodethis http://example.net/foo
12+
Example: --url-query name@file $URL
13+
Example: --url-query @fileonly $URL
14+
Example: --url-query "+name=%20foo" $URL
15+
Multi: append
16+
---
17+
This option adds a piece of data, usually a name + value pair, to the end of
18+
the URL query part. The syntax is identical to that used for --data-urlencode
19+
with one extension:
20+
21+
If the argument starts with a '+' (plus), the rest of the string is provided
22+
as-is unencoded.
23+
24+
The query part of a URL is the one following the question mark on the right
25+
end.

docs/options-in-versions

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@
251251
--unix-socket 7.40.0
252252
--upload-file (-T) 4.0
253253
--url 7.5
254+
--url-query 7.87.0
254255
--use-ascii (-B) 5.0
255256
--user (-u) 4.0
256257
--user-agent (-A) 4.5.1

src/tool_cfgable.c

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ static void free_config_fields(struct OperationConfig *config)
5858
curl_slist_free_all(config->cookiefiles);
5959

6060
Curl_safefree(config->postfields);
61+
Curl_safefree(config->query);
6162
Curl_safefree(config->referer);
6263

6364
Curl_safefree(config->headerfile);

src/tool_cfgable.h

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct OperationConfig {
7070
char *postfields;
7171
curl_off_t postfieldsize;
7272
char *referer;
73+
char *query;
7374
long timeout_ms;
7475
long connecttimeout_ms;
7576
long maxredirs;

src/tool_getparam.c

+35-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "tool_paramhlp.h"
4242
#include "tool_parsecfg.h"
4343
#include "tool_main.h"
44+
#include "dynbuf.h"
4445

4546
#include "memdebug.h" /* keep this as LAST include */
4647

@@ -233,6 +234,7 @@ static const struct LongShort aliases[]= {
233234
{"db", "data-binary", ARG_STRING},
234235
{"de", "data-urlencode", ARG_STRING},
235236
{"df", "json", ARG_STRING},
237+
{"dg", "url-query", ARG_STRING},
236238
{"D", "dump-header", ARG_FILENAME},
237239
{"e", "referer", ARG_STRING},
238240
{"E", "cert", ARG_FILENAME},
@@ -1567,7 +1569,39 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
15671569
size_t size = 0;
15681570
bool raw_mode = (subletter == 'r');
15691571

1570-
if(subletter == 'e') { /* --data-urlencode */
1572+
if(subletter == 'g') { /* --url-query */
1573+
#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
1574+
char *query;
1575+
struct curlx_dynbuf dyn;
1576+
curlx_dyn_init(&dyn, MAX_QUERY_LEN);
1577+
1578+
if(*nextarg == '+') {
1579+
/* use without encoding */
1580+
query = strdup(&nextarg[1]);
1581+
if(!query)
1582+
return PARAM_NO_MEM;
1583+
}
1584+
else {
1585+
err = data_urlencode(global, nextarg, &query, &size);
1586+
if(err)
1587+
return err;
1588+
}
1589+
1590+
if(config->query) {
1591+
CURLcode result =
1592+
curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
1593+
free(query);
1594+
if(result)
1595+
return PARAM_NO_MEM;
1596+
free(config->query);
1597+
config->query = curlx_dyn_ptr(&dyn);
1598+
}
1599+
else
1600+
config->query = query;
1601+
1602+
break; /* this is not a POST argument at all */
1603+
}
1604+
else if(subletter == 'e') { /* --data-urlencode */
15711605
err = data_urlencode(global, nextarg, &postdata, &size);
15721606
if(err)
15731607
return err;

src/tool_listhelp.c

+3
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,9 @@ const struct helptxt helptext[] = {
756756
{" --url <url>",
757757
"URL to work with",
758758
CURLHELP_CURL},
759+
{" --url-query <data>",
760+
"Add a URL query part",
761+
CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
759762
{"-B, --use-ascii",
760763
"Use ASCII/text transfer",
761764
CURLHELP_MISC},

src/tool_operate.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1189,14 +1189,14 @@ static CURLcode single_transfer(struct GlobalConfig *global,
11891189
global->isatty = orig_isatty;
11901190
}
11911191

1192-
if(httpgetfields) {
1192+
if(httpgetfields || config->query) {
1193+
char *q = httpgetfields ? httpgetfields : config->query;
11931194
CURLU *uh = curl_url();
11941195
if(uh) {
11951196
char *updated;
11961197
if(curl_url_set(uh, CURLUPART_URL, per->this_url,
11971198
CURLU_GUESS_SCHEME) ||
1198-
curl_url_set(uh, CURLUPART_QUERY, httpgetfields,
1199-
CURLU_APPENDQUERY) ||
1199+
curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) ||
12001200
curl_url_get(uh, CURLUPART_URL, &updated, CURLU_GUESS_SCHEME)) {
12011201
curl_url_cleanup(uh);
12021202
result = CURLE_OUT_OF_MEMORY;

0 commit comments

Comments
 (0)