Examples
Simple Examples
Hello, World!
return "Hello, World!"
The simplest example. This simply returns "Hello, world!" as plaintext.
If you return just a string, it'll be treated as the body of the response.
Returning JSON
return { hello = "world" }
If you return just a table, it'll be treated as the body of the response, being encoded as JSON automatically.
Setting HTTP Response Headers
return "Ok", {["X-Clacks-Overhead"] = "GNU Terry Pratchett"}
A table returned after any value that can be treated as a body, will be treated as a map of headers to be applied to the response.
Returning HTML
To return HTML, set a content-type header.
return "<h1>Helo, World!</h1>", {["Content-Type"] = "text/html"}
Making an Outgoing HTTP Request
local response = http.request{ url = 'https://httpbin.org/get' }
return response.body
Counter
For each request, this gets the current count from storage, increments it, and writes it back to storage, returning the current count in a json object.
-- get the current count
local count = storage.count or 0
-- increment the count
count = count + 1
-- persist the updated count
storage.count = count
-- log the count
print("count: " .. count)
-- return JSON to the caller
return {count=count}
Note: This example is simplified to show how storage works. It has a race
condition if two executions try to update the count at the same time, one can
get lost. See the "SVG Hit Counter" example for how to protect against this.
Larger Examples
SVG Hit Counter
This implements a simple hit counter as an SVG image.
lock.acquire("count")
local count = (storage.count or 0) + 1
storage.count = count
lock.release("count")
return string.format([===[
<svg width="200" height="80" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="200" height="80" fill="#222"/>
<rect x="10" y="10" width="180" height="60" fill="#000"/>
<text x="100" y="55" font-family="monospace" font-size="40" fill="#00CC00" text-anchor="middle">%06i</text>
</svg>]===], count), {
["Content-Type"] = "image/svg+xml"
}
Parsing an HTML Page
Bodge includes the htmlparser library.
This example fetches the kernel.org homepage and parses out the latest kernel version that has been published.
local htmlparser = require("htmlparser")
local response = http.request{ url = "https://www.kernel.org/" }
local document = htmlparser.parse(response.body)
local found_elements = document:select("#latest_link a")
local latest_kernel_link = found_elements[1]
local latest_kernel_version = latest_kernel_link:getcontent()
return latest_kernel_version
Though, in this instance, it would be easier to just use their json list instead.
Down Service Watcher
This is a simple script that will alert you if any of the HTTP services go down.
local service_endpoints = {
homepage = {
name = "Bodge Homepage",
url = "https://bodge.app/"
},
triggers = {
name = "Bodge HTTP Triggers",
url = "https://status.bodge.link/"
}
}
--------------------------------------------------------------------------------
local results = {}
for id, service in pairs(service_endpoints) do
local status, resp = pcall(http.request, { url = service.url })
local isup = "true"
local result
if status and resp.statuscode == 200 then
result = { up = true }
else
result = { up = false, status = type(resp) == table and resp.statuscode or tostring(resp) }
isup = "false"
end
local skey = "isup_" .. id
local wasup = storage[skey]
if wasup ~= isup then
if isup == "true" then
alert.email{
subject = "Service Recovered: " .. tostring(service.name),
text = ""
}
else
alert.email{
subject = "Service Down: " .. tostring(service.name),
text = "Status: " .. tostring(result.status)
}
end
end
results[id] = result
storage[skey] = isup
end
return results