summaryrefslogtreecommitdiff
path: root/service.lua
diff options
context:
space:
mode:
Diffstat (limited to 'service.lua')
-rw-r--r--service.lua60
1 files changed, 60 insertions, 0 deletions
diff --git a/service.lua b/service.lua
new file mode 100644
index 0000000..70a3374
--- /dev/null
+++ b/service.lua
@@ -0,0 +1,60 @@
+local http_rq = require 'http.request'
+local json = require 'json'
+local lmdb = require 'lmdb'
+
+local M = {}
+
+local db
+local function get_db()
+ if db then
+ return db
+ end
+ db = assert(lmdb.open("data/cache.mdb", {nosubdir = true, mapsize = 2^20}))
+ return db
+end
+
+function M.lookup(domain)
+ if not domain:match "^[%w_%-%.]+$" then
+ return nil, "invalid service name!"
+ end
+ domain = domain:gsub('%.+', ".")
+
+ local db = get_db()
+
+ local txn = db:txn_begin()
+ if txn then
+ local cache = txn:open()
+ if cache[domain] then
+ local sv = json.decode(cache[domain])
+ if os.time() <= sv.expires then
+ txn:commit()
+ return sv
+ end
+ end
+ txn:commit()
+ end
+
+ local meta_uri = "https://"..domain.."/.well-known/citrons/auth"
+ local rq = http_rq.new_from_uri(meta_uri)
+ local headers, stream = rq:go(8)
+ if not headers then return nil, stream end
+ if headers:get ":status" ~= "200" then
+ return nil, "HTTP error: "..headers:get ":status"
+ end
+ local data, err = stream:get_body_chars(4096, 4)
+ if not data then return nil, err end
+ local ok, result = pcall(json.decode, data)
+ if not ok then return nil, "could not decode JSON" end
+
+ local txn = db:txn_begin(true)
+ if txn then
+ local cache = txn:open()
+ result.expires = os.time() + (result.ttl or 300)
+ cache[domain] = json.encode(result)
+ pcall(txn.commit, txn)
+ end
+
+ return result
+end
+
+return M