In the documentation it is written:
globbing letters
The curl command line tool supports "globbing" of URLs. It means that you can create ranges and lists using [N-M] and {one,two,three} sequences. The letters used for this ([]{}) are reserved in RFC 3986 and can therefore not legitimately be part of such a URL.
They are however not reserved or special in the WHATWG specification, so globbing can mess up such URLs. Globbing can be turned off for such occasions (using --globoff).
It means that you should do percent-encoding for reserved/special characters (:/?#[]@!$&'()*+,;=) to avoid their special interpretation. To do so you put percent sign (%) and hex value of character in ASCII table. For example:
| Symbol |
Encoded Value |
[ |
%5B |
] |
%5D |
{ |
%7B |
} |
%7D |
curl doesn't expect reserved/special characters in URL and these four symbols are used to generate multiple URLs (globbing operation):
$ curl http://localhost:8080/?TEST[a-c]=1
will equivalent to
$ curl http://localhost:8080/?TESTa=1
$ curl http://localhost:8080/?TESTb=1
$ curl http://localhost:8080/?TESTc=1
and
$ curl http://localhost:8080/?TEST{a,c,e}=1
will equivalent to
$ curl http://localhost:8080/?TESTa=1
$ curl http://localhost:8080/?TESTc=1
$ curl http://localhost:8080/?TESTe=1
If you want to disable globbing operation:
encode them:
$ curl http://localhost:8080/?TEST%5Ba-c%5D=1
$ curl http://localhost:8080/?TEST%7Ba,c,e%7d=1
For zsh (default shell on Mac OS X) you must escape ? as well. Thus for both bash and zsh shells:
$ curl http://localhost:8080/\?TEST%5Ba-c%5D=1
$ curl http://localhost:8080/\?TEST%7Ba,c,e%7d=1
or use -g/--globoff option:
$ curl -g http://localhost:8080/?TEST[a-c]=1
$ curl -g http://localhost:8080/?TEST{a,c,e}=1 # not enough, see note below
☝ In last example there is a caveat: globbing may be done by bash and zsh shell. To avoid globbing by shell:
either escape characters putting reverse slash (\) (don't forget about escaping ? for zsh shell):
$ curl -g http://localhost:8080/\?TEST\[a-c\]=1
$ curl -g http://localhost:8080/\?TEST\{a,c,e\}=1
or put URL in quotes (single or double):
$ curl -g 'http://localhost:8080/?TEST[a-c]=1'
$ curl -g 'http://localhost:8080/?TEST{a,c,e}=1'
☝ Also be aware that empty square brackets ([]) don't lead to globbing in curl:
$ curl 'http://localhost:8080/?TEST[]=1'
will request /?TEST[]=1.
This is not true for empty curly brackets ({}):
$ curl 'http://localhost:8080/?TEST{}=1'
curl: (3) empty string within braces in URL position 29:
http://localhost:8080/?TEST{}=1
^
they must contain at least one string.
P.S. You may test on docker (press Ctrl+C to quit):
$ docker run --rm -p 8080:80 -it nginx
and run curl against it in separate terminal:
$ curl http://localhost:8080/?TEST[a-c]=1
In logs you should see generate URL for request:
172.17.0.1 - - [17/Jan/2023:09:21:53 +0000] "GET /?TESTa=1 HTTP/1.1" 200 615 "-" "curl/7.86.0" "-"
172.17.0.1 - - [17/Jan/2023:09:21:53 +0000] "GET /?TESTb=1 HTTP/1.1" 200 615 "-" "curl/7.86.0" "-"
172.17.0.1 - - [17/Jan/2023:09:21:53 +0000] "GET /?TESTc=1 HTTP/1.1" 200 615 "-" "curl/7.86.0" "-"