소스 검색

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
Daniel Stenberg 1 년 전
부모
커밋
b6e1afd069
8개의 변경된 파일70개의 추가작업 그리고 4개의 파일을 삭제
  1. 1 0
      docs/cmdline-opts/Makefile.inc
  2. 25 0
      docs/cmdline-opts/url-query.d
  3. 1 0
      docs/options-in-versions
  4. 1 0
      src/tool_cfgable.c
  5. 1 0
      src/tool_cfgable.h
  6. 35 1
      src/tool_getparam.c
  7. 3 0
      src/tool_listhelp.c
  8. 3 3
      src/tool_operate.c

+ 1 - 0
docs/cmdline-opts/Makefile.inc

@@ -265,6 +265,7 @@ DPAGES = \
   unix-socket.d \
   upload-file.d \
   url.d \
+  url-query.d \
   use-ascii.d \
   user-agent.d \
   user.d \

+ 25 - 0
docs/cmdline-opts/url-query.d

@@ -0,0 +1,25 @@
+c: Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: url-query
+Arg: <data>
+Help: Add a URL query part
+Protocols: all
+See-also: data-urlencode get
+Added: 7.87.0
+Category: http post upload
+Example: --url-query name=val $URL
+Example: --url-query =encodethis http://example.net/foo
+Example: --url-query name@file $URL
+Example: --url-query @fileonly $URL
+Example: --url-query "+name=%20foo" $URL
+Multi: append
+---
+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.
+
+The query part of a URL is the one following the question mark on the right
+end.

+ 1 - 0
docs/options-in-versions

@@ -251,6 +251,7 @@
 --unix-socket                        7.40.0
 --upload-file (-T)                   4.0
 --url                                7.5
+--url-query                          7.87.0
 --use-ascii (-B)                     5.0
 --user (-u)                          4.0
 --user-agent (-A)                    4.5.1

+ 1 - 0
src/tool_cfgable.c

@@ -58,6 +58,7 @@ static void free_config_fields(struct OperationConfig *config)
   curl_slist_free_all(config->cookiefiles);
 
   Curl_safefree(config->postfields);
+  Curl_safefree(config->query);
   Curl_safefree(config->referer);
 
   Curl_safefree(config->headerfile);

+ 1 - 0
src/tool_cfgable.h

@@ -70,6 +70,7 @@ struct OperationConfig {
   char *postfields;
   curl_off_t postfieldsize;
   char *referer;
+  char *query;
   long timeout_ms;
   long connecttimeout_ms;
   long maxredirs;

+ 35 - 1
src/tool_getparam.c

@@ -41,6 +41,7 @@
 #include "tool_paramhlp.h"
 #include "tool_parsecfg.h"
 #include "tool_main.h"
+#include "dynbuf.h"
 
 #include "memdebug.h" /* keep this as LAST include */
 
@@ -233,6 +234,7 @@ static const struct LongShort aliases[]= {
   {"db", "data-binary",              ARG_STRING},
   {"de", "data-urlencode",           ARG_STRING},
   {"df", "json",                     ARG_STRING},
+  {"dg", "url-query",                ARG_STRING},
   {"D",  "dump-header",              ARG_FILENAME},
   {"e",  "referer",                  ARG_STRING},
   {"E",  "cert",                     ARG_FILENAME},
@@ -1567,7 +1569,39 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
       size_t size = 0;
       bool raw_mode = (subletter == 'r');
 
-      if(subletter == 'e') { /* --data-urlencode */
+      if(subletter == 'g') { /* --url-query */
+#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
+        char *query;
+        struct curlx_dynbuf dyn;
+        curlx_dyn_init(&dyn, MAX_QUERY_LEN);
+
+        if(*nextarg == '+') {
+          /* use without encoding */
+          query = strdup(&nextarg[1]);
+          if(!query)
+            return PARAM_NO_MEM;
+        }
+        else {
+          err = data_urlencode(global, nextarg, &query, &size);
+          if(err)
+            return err;
+        }
+
+        if(config->query) {
+          CURLcode result =
+            curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
+          free(query);
+          if(result)
+            return PARAM_NO_MEM;
+          free(config->query);
+          config->query = curlx_dyn_ptr(&dyn);
+        }
+        else
+          config->query = query;
+
+        break; /* this is not a POST argument at all */
+      }
+      else if(subletter == 'e') { /* --data-urlencode */
         err = data_urlencode(global, nextarg, &postdata, &size);
         if(err)
           return err;

+ 3 - 0
src/tool_listhelp.c

@@ -756,6 +756,9 @@ const struct helptxt helptext[] = {
   {"    --url <url>",
    "URL to work with",
    CURLHELP_CURL},
+  {"    --url-query <data>",
+   "Add a URL query part",
+   CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
   {"-B, --use-ascii",
    "Use ASCII/text transfer",
    CURLHELP_MISC},

+ 3 - 3
src/tool_operate.c

@@ -1189,14 +1189,14 @@ static CURLcode single_transfer(struct GlobalConfig *global,
           global->isatty = orig_isatty;
         }
 
-        if(httpgetfields) {
+        if(httpgetfields || config->query) {
+          char *q = httpgetfields ? httpgetfields : config->query;
           CURLU *uh = curl_url();
           if(uh) {
             char *updated;
             if(curl_url_set(uh, CURLUPART_URL, per->this_url,
                             CURLU_GUESS_SCHEME) ||
-               curl_url_set(uh, CURLUPART_QUERY, httpgetfields,
-                            CURLU_APPENDQUERY) ||
+               curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) ||
                curl_url_get(uh, CURLUPART_URL, &updated, CURLU_GUESS_SCHEME)) {
               curl_url_cleanup(uh);
               result = CURLE_OUT_OF_MEMORY;