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 bothbash
andzsh
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
andzsh
shell. To avoid globbing by shell:either escape characters putting reverse slash (
\
) (don't forget about escaping?
forzsh
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" "-"