Maschini

mttp

Feb 24th, 2023 (edited)
765
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.74 KB | None | 0 0
  1. local expect = require "cc.expect"
  2. local expect, field = expect.expect, expect.field
  3.  
  4. local function LOG(...)
  5.    
  6. end
  7.  
  8. local function NewRequest(method, path, payload)
  9.     expect(1, method, "string", "nil")
  10.     expect(2, path, "string", "nil")
  11.     expect(3, payload, "table", "string", "nil")
  12.  
  13.     if type(payload) == "table" then
  14.         payload = textutils.serialiseJSON(payload)
  15.     end
  16.  
  17.     return {
  18.         ["method"] = method or "GET",
  19.         ["path"] = path or "/",
  20.         ["payload"] = payload or {}
  21.     }
  22. end
  23.  
  24. local function ParseRequest(message)
  25.     LOG(message)
  26.     local payload = textutils.unserialiseJSON(message)
  27.     if (payload["method"] == nil or not (payload["method"] == "GET" or payload["method"] == "POST")) then
  28.         return nil, "parsing failed: invalid method"
  29.     end
  30.     if payload["path"] == nil then
  31.         return nil, "parsing failed: missing path"
  32.     end
  33.     return payload, nil
  34. end
  35.  
  36. local function Do(modem, channelId, request)
  37.     expect(1, modem, "table")
  38.     expect(2, channelId, "number")
  39.     expect(3, request, "table")
  40.  
  41.     local TIMEOUT = 0.05
  42.     local returnChannelId = math.random(1, 65535)
  43.     modem.open(returnChannelId)
  44.  
  45.     local req = textutils.serialiseJSON(request)
  46.     modem.transmit(channelId, returnChannelId, req)
  47.     LOG(req)
  48.    
  49.     local timeoutAlarmId = os.setAlarm(os.time() + TIMEOUT)
  50.  
  51.     local event, side_or_id, channel, replyChannel, message, distance
  52.     repeat
  53.         event, side_or_id, channel, replyChannel, message, distance = os.pullEvent()
  54.         LOG(event, side_or_id)
  55.     until (event == "alarm" and side_or_id == timeoutAlarmId) or (event == "modem_message" and channel == returnChannelId)
  56.     modem.close(returnChannelId)
  57.     if event == "alarm" then
  58.         return nil, "timeout"
  59.     end
  60.  
  61.     LOG(event, side_or_id, channel, replyChannel, message, distance)
  62.     local msg = textutils.unserialiseJSON(message)
  63.     return msg["status"], msg["response"], nil
  64. end
  65.  
  66. local function GET(modem, channelId, path)
  67.     local req = NewRequest("GET", path)
  68.     return Do(modem, channelId, req)
  69. end
  70.  
  71. local function POST(modem, channelId, path, body)
  72.     local req = NewRequest("POST", path, body)
  73.     return Do(modem, channelId, req)
  74. end
  75.  
  76. local function validateHandlers(handlers)
  77.     for path, handler in pairs(handlers) do
  78.         if type(path) ~= "string" then
  79.             printError(path)
  80.             return false
  81.         end
  82.  
  83.         field(handlers, path, "function")
  84.     end
  85.  
  86.     return true
  87. end
  88.  
  89. local function handle(handlers, request)
  90.     expect(1, handlers, "table")
  91.     expect(2, request, "table")
  92.  
  93.     local path = request["path"]
  94.  
  95.     local h = handlers[path]
  96.     if h == nil then
  97.         return { status=404 }
  98.     end
  99.  
  100.     local status, response = h(request)
  101.     return {
  102.         status=status,
  103.         response=response
  104.     }
  105. end
  106.  
  107. local function ListenAndServe(modem, channelId, handlers)
  108.     expect(1, modem, "table")
  109.     expect(2, channelId, "number")
  110.     expect(3, handlers, "table")
  111.     if not validateHandlers(handlers) then
  112.         printError("handlers are invalid")
  113.         return
  114.     end
  115.  
  116.     modem.open(channelId)
  117.     while true do
  118.         local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
  119.         if channel == channelId then
  120.             local req, err = ParseRequest(message)
  121.             if err == nil then
  122.                 local response = handle(handlers, req)
  123.                 modem.transmit(replyChannel, channelId, textutils.serialiseJSON(response))
  124.                 LOG("handeled:", message)
  125.             else
  126.                 printError(err)
  127.             end
  128.         end
  129.     end
  130. end
  131.  
  132. return {
  133.     get = GET,
  134.     post = POST,
  135.     serve = ListenAndServe,
  136. }
Advertisement
Add Comment
Please, Sign In to add comment