Stress Testing with cURL

There are plenty of tools for stress testing, read RapidAPI, paw, SoapUI, Postman, rest-assured, JMeter and so on! I’m sure they are amazing, however that’s all big and heavy, slow, sometimes paid tools!

If all you need is just simple (or not, depending on what you want) stress testing, cURL is your hidden gem! cURL works pretty much everywhere, and even Windows has curl installed out of the box!

To remind, to issue a simple cURL request, just issue it like curl http://localhost/path1.

A bit more

What if you need to test path1, path2 and path3? Easy:

curl http://localhost/path{1,2,3}

that will issue:

http://localhost/path1
http://localhost/path2
http://localhost/path3

that can be also replaced with curl http://localhost/path[1-3] to the same effect, i.e. you can use ranges!

Ranges can be mixed i.e.

curl http://localhost/path{1,2,3}/subpath[1-3]

will issue

http://localhost/path1/subpath1
http://localhost/path1/subpath2
http://localhost/path1/subpath3
http://localhost/path2/subpath1
http://localhost/path2/subpath2
http://localhost/path2/subpath3
http://localhost/path3/subpath1
http://localhost/path3/subpath2
http://localhost/path3/subpath3

you can also use letters i.e. http://localhost/path-[a-z] will issue queries from http://localhost/path-a to http://localhost/path-z (26 requests total).

That is already cool!

All the requests are executed sequentially so if that’s ok with you (and most of the times it is) you should be fine.

Serious offense

Ok, what about a parallel load? xargs will come to rescue! Specifically the multi-threaded version. As you should know, xargs (stands for extended arguments) allows to fork execution from an input to an execution per line. Combined with seq you can start an offensive 😜seq can generate input you want (numbers only) i.e. seq 1 5 will produce 5 lines:

1
2
3
4
5

then piping this into xargs allows 5 executions i.e. seq 1 5 | xargs -I{} curl http://localhost/path{} will invoke sequentially:

http://localhost/path1
http://localhost/path2
http://localhost/path3
http://localhost/path4
http://localhost/path5

but passing -P will allow you to paralellise requests! So this is how you issue 500 requests with 5 always going in parallel:

seq 1 500 | xargs -P5 -I{} curl http://localhost/path{}

If you need to absolutely exhaust the target, pass a higher number into -P, or to max it out pass 0 as parallelism. From official man pages:

If max-procs is 0, xargs will run as many processes as possible at a time.

You do lose some ability of more powerful cURL ranges, especially with characters, as seq only produces numbers. However even this can be fixed.

seq supports -f switch allowing you to pass a custom format string, however that’s not very useful because you are already formatting with xargs (-I{})

You can do even better - generate a lot of word permutations! Take crunch for example (may need to install it i.e. apt install crunch) and generate words 5 character length:

crunch 5 5 -o 5words.txt

The file is quite large (67mb) and takes a few seconds to generate, hence we save it locally. Then take this “dictionary” as an input of a stress test:

cat 5words.txt | xargs -n1 -P5 -I{} curl http://localhost/words/{}

That will issue 11881376 (11 million!) requests in parallel! More than enough if you ask me.

So is there a need for a dedicated stress tool? I don’t think so.

PowerShell Friends

1..10 | % -Parallel { curl http://localhost/path$_ }

1..10 is a “range operator”, equivalent to seq 1 10 (at least something is shorter in PS ;)

% is an alias for Foreach-Object which can run in parallel mode optionally.

-Parallel flag is only available in PowerShell 7 and higher. One can use -ThrottleLimit parameter to further limit number of parallel “threads”, otherwise it’s unlimited (equivalent to xargs-P)

Ranges in PowerShell can also do letters, but it’s not obvious - [char]'a'..[char]'z' will produce

a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z

You can do a reverse range by doing 5..1 which produces

5
4
3
2
1

Thanks! You can always email me or use contact form for more questions/comments etc.