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" "-"