diff options
Diffstat (limited to 'service.lua')
-rw-r--r-- | service.lua | 60 |
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 |