Millet Porridge

English version of https://corvo.myseu.cn

0%

How to use wrk to generate HTTP payloads

a HTTP benchmarking tool

Please refer to wrk in Github

1
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html

What if we want to make some HTTP POST requests.

Here is the Lua script in the repo, which allows the user to create an HTTP POST request.

1
2
3
4
5
6
-- example HTTP POST script which demonstrates setting the
-- HTTP method, body, and adding a header

wrk.method = "POST"
wrk.body = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

I don’t think it’s a good example, and it seems to tell you that you could not modify other parts of the request.

Let’s see counter.lua

This is another Lua script in the repo. Well, I need to make an HTTP POST payload, but it’s for GET.

1
2
3
4
5
6
7
8
counter = 0

request = function()
path = "/" .. counter
wrk.headers["X-Counter"] = counter
counter = counter + 1
return wrk.format(nil, path)
end

One thing is for sure: there is a request function to generate a payload, which means we can override this function to achieve the effect we want.

Deep into source code

The code below is from the src/wrk.lua:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function wrk.init(args)

-- other headers

-- generate the default req payload
local req = wrk.format()
wrk.request = function()
return req
end
end

-- `wrk.format` allow user to generate the request.
function wrk.format(method, path, headers, body)
local method = method or wrk.method
local path = path or wrk.path
local headers = headers or wrk.headers
local body = body or wrk.body
local s = {}

if not headers["Host"] then
headers["Host"] = wrk.headers["Host"]
end

headers["Content-Length"] = body and string.len(body)

s[1] = string.format("%s %s HTTP/1.1", method, path)
for name, value in pairs(headers) do
s[#s+1] = string.format("%s: %s", name, value)
end

s[#s+1] = ""
s[#s+1] = body or ""

return table.concat(s, "\r\n")
end

Dynamically generate the payload

Since we know how wrk builds the request payload, we can create our own request function. It’s more like a generator that creates payload dynamically.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Randomly generate start and amount
request = function()
local path = "/comments"
local start = math.random(1, 30000)
local amount = math.random(10, 30)
local body = "url=xxx1"
.. string.format("&start=%d", start)
.. string.format("&amount=%d", amount)
.. string.format("&parm=%d", xx)

local headers = {}
headers["Content-Type"] = "application/x-www-form-urlencoded"
return wrk.format('POST', path, headers, body)
end

It’s easy to use the Lua script in wrk.

1
2
3
4
./wrk -t4 -c2000 -d30s \
--latency -T5s \
-s scripts/post.lua \
http://127.0.0.1:8888/comments

Hope you will enjoy this small tool.