Intro to Lua and Openresty, Part 9: HTTP clients
In Part 8 of this series, we used lua to read from the Postgres database.
In this post, we’re going to cover the basics of HTTP clients in lua.
Rationale / Goals
Throughout this series, we’ve often used HTTP requests as part of running tests on the code in the exercise, but we’ve always used curl
and the shell. In our demo, we’re going to run many thousands of messages through the system at a time, and to do so, we’re going to need to generate requests that are easily verifiable as being unique.
httpclient
We’ll use the httpclient
library for these examples.
GET / POST
If you are following along in the code, we are here.
Here is our code:
= require("cjson")
cjson = require("httpclient").new()
hc = hc:post('http://127.0.0.1:8000/',
resp .encode({ hello = "world" }),
cjson{content_type = 'application/json'})
= hc:get('http://127.0.0.1:8000/list')
getr if resp.code == 200 then
print("success!")
end
print(resp.body)
print(resp.code)
print(resp.headers)
print(resp.status_line)
print(resp.err)
print(getr.body)
print(getr.code)
print(getr.headers)
print(getr.status_line)
print(getr.err)
and our Dockerfile
:
FROM openresty/openresty:alpine-fat
RUN apk add --update openssl-dev git
RUN /usr/local/openresty/luajit/bin/luarocks install luasocket
RUN /usr/local/openresty/luajit/bin/luarocks install luasec
RUN /usr/local/openresty/luajit/bin/luarocks install lua-cjson
RUN /usr/local/openresty/luajit/bin/luarocks install httpclient
ADD get-post.lua /src/get-post.lua
WORKDIR /src/
ENTRYPOINT /usr/local/openresty/luajit/bin/luajit
CMD ["get-post.lua"]
Batch POST
If you are following along in the code, we are here.
We want to generate “load” on our system. Our system takes a message via POST request and “processes” it. Let’s write a script to generate POST requests in a loop:
local cjson = require('cjson')
local cli = require('cliargs')
local hc = require('httpclient').new()
--
local default_url = 'http://127.0.0.1:8000'
local date_fmt = '%m-%d-%Y--%H-%M-%S'
--
-- cli args, parsing, and help docs
:option('--limit=NUMBER', 'max number of posts to send', 100)
cli:option('--url=HTTP_URL', 'URL to POST messages to', default_url)
cli:flag('--list', 'hit the list endpoint to retrieve the latest posts', false)
cli--
-- auto-gen some JSON to send as a post/message
= function ()
generate_post return { hello = world, now = os.date(date_fmt)}
end
-- where msg is some {}
= function (url, msg)
send_post return hc:post(url,
.encode(msg),
cjson{content_type = 'application/json'})
end
-- hit the /list endpoint to retrieve the latest posts
= function (url)
get_posts return hc:get(url)
end
-- our primary loop
= function (url, limit)
batch_send while (limit > 0)
do
= generate_post()
msg = send_post(url, msg)
res if res.code == 200 then
print('POST success! ' .. res.body)
else
print('non-200 return! ' .. res.code .. ' ' .. res.err)
end
= limit-1
limit end
end
--
-- MAIN
--
local args, err = cli:parse()
-- if there's an error in parsing (or --help), print it!
if err then
print(err)
os.exit(0)
end
--
print('Let us post a bunch of messages to the service:')
= math.random(0, args.limit)
i print('We will print ' .. i .. ' messages this time..')
(args.url, i)
batch_send
if args.list then
print('Let us retrieve the top posts saved/written to the service:')
= get_posts(args.url .. '/list').body
posts print(posts)
end
Dockerfile
FROM openresty/openresty:alpine-fat
RUN apk add --update openssl-dev git
RUN /usr/local/openresty/luajit/bin/luarocks install luasocket
RUN /usr/local/openresty/luajit/bin/luarocks install luasec
RUN /usr/local/openresty/luajit/bin/luarocks install lua-cjson
RUN /usr/local/openresty/luajit/bin/luarocks install httpclient
RUN /usr/local/openresty/luajit/bin/luarocks install lua_cliargs
ADD batch-posts.lua /src/batch-posts.lua
WORKDIR /src/
ENTRYPOINT /usr/local/openresty/luajit/bin/luajit
CMD ["batch-posts.lua"]
Makefile
MAX ?= 1000
build:
docker build --tag=load:11 --rm=true .
run:
docker run --rm -it --net host --entrypoint /usr/local/openresty/luajit/bin/luajit load:11 batch-posts.lua --limit $(MAX)
dev:
docker run --rm -it --net host -v `pwd`/batch-posts.lua:/src/batch-posts.lua --entrypoint /usr/local/openresty/luajit/bin/luajit load:11 batch-posts.lua --list
shell:
docker run --rm -it --net host -v `pwd`/batch-posts.lua:/src/batch-posts.lua --entrypoint /bin/sh load:11
help:
docker run --rm -it --entrypoint /usr/local/openresty/luajit/bin/luajit load:11 batch-posts.lua --help