Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local expect = require "cc.expect"
- local expect, field = expect.expect, expect.field
- local function LOG(...)
- end
- local function NewRequest(method, path, payload)
- expect(1, method, "string", "nil")
- expect(2, path, "string", "nil")
- expect(3, payload, "table", "string", "nil")
- if type(payload) == "table" then
- payload = textutils.serialiseJSON(payload)
- end
- return {
- ["method"] = method or "GET",
- ["path"] = path or "/",
- ["payload"] = payload or {}
- }
- end
- local function ParseRequest(message)
- LOG(message)
- local payload = textutils.unserialiseJSON(message)
- if (payload["method"] == nil or not (payload["method"] == "GET" or payload["method"] == "POST")) then
- return nil, "parsing failed: invalid method"
- end
- if payload["path"] == nil then
- return nil, "parsing failed: missing path"
- end
- return payload, nil
- end
- local function Do(modem, channelId, request)
- expect(1, modem, "table")
- expect(2, channelId, "number")
- expect(3, request, "table")
- local TIMEOUT = 0.05
- local returnChannelId = math.random(1, 65535)
- modem.open(returnChannelId)
- local req = textutils.serialiseJSON(request)
- modem.transmit(channelId, returnChannelId, req)
- LOG(req)
- local timeoutAlarmId = os.setAlarm(os.time() + TIMEOUT)
- local event, side_or_id, channel, replyChannel, message, distance
- repeat
- event, side_or_id, channel, replyChannel, message, distance = os.pullEvent()
- LOG(event, side_or_id)
- until (event == "alarm" and side_or_id == timeoutAlarmId) or (event == "modem_message" and channel == returnChannelId)
- modem.close(returnChannelId)
- if event == "alarm" then
- return nil, "timeout"
- end
- LOG(event, side_or_id, channel, replyChannel, message, distance)
- local msg = textutils.unserialiseJSON(message)
- return msg["status"], msg["response"], nil
- end
- local function GET(modem, channelId, path)
- local req = NewRequest("GET", path)
- return Do(modem, channelId, req)
- end
- local function POST(modem, channelId, path, body)
- local req = NewRequest("POST", path, body)
- return Do(modem, channelId, req)
- end
- local function validateHandlers(handlers)
- for path, handler in pairs(handlers) do
- if type(path) ~= "string" then
- printError(path)
- return false
- end
- field(handlers, path, "function")
- end
- return true
- end
- local function handle(handlers, request)
- expect(1, handlers, "table")
- expect(2, request, "table")
- local path = request["path"]
- local h = handlers[path]
- if h == nil then
- return { status=404 }
- end
- local status, response = h(request)
- return {
- status=status,
- response=response
- }
- end
- local function ListenAndServe(modem, channelId, handlers)
- expect(1, modem, "table")
- expect(2, channelId, "number")
- expect(3, handlers, "table")
- if not validateHandlers(handlers) then
- printError("handlers are invalid")
- return
- end
- modem.open(channelId)
- while true do
- local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
- if channel == channelId then
- local req, err = ParseRequest(message)
- if err == nil then
- local response = handle(handlers, req)
- modem.transmit(replyChannel, channelId, textutils.serialiseJSON(response))
- LOG("handeled:", message)
- else
- printError(err)
- end
- end
- end
- end
- return {
- get = GET,
- post = POST,
- serve = ListenAndServe,
- }
Advertisement
Add Comment
Please, Sign In to add comment