diff --git a/lib/http.lua b/lib/http.lua new file mode 100644 index 0000000..cf48735 --- /dev/null +++ b/lib/http.lua @@ -0,0 +1,15 @@ +local httpExists, socketHttp = pcall(require, "socket.http") +local ltn12Exists, ltn12 = pcall(require, "ltn12") + +local http = {} + +function http.request() + error("Please install `luasocket` to use HTTP features.", 2) +end + +if httpExists and ltn12Exists then + http.request = socketHttp.request + http.tableSink = ltn12.sink.table +end + +return http \ No newline at end of file diff --git a/lib/instances/Game.lua b/lib/instances/Game.lua index 3ebc945..9ef6820 100644 --- a/lib/instances/Game.lua +++ b/lib/instances/Game.lua @@ -1,3 +1,4 @@ +local http = import("../http") local BaseInstance = import("./BaseInstance") local AnalyticsService = import("./AnalyticsService") @@ -27,7 +28,7 @@ function Game:init(instance) CoreGui:new().Parent = instance CorePackages:new().Parent = instance GuiService:new().Parent = instance - HttpService:new().Parent = instance + HttpService:new(http).Parent = instance LocalizationService:new().Parent = instance NotificationService:new().Parent = instance Players:new().Parent = instance diff --git a/lib/instances/HttpService.lua b/lib/instances/HttpService.lua index 3601a79..0c33da2 100644 --- a/lib/instances/HttpService.lua +++ b/lib/instances/HttpService.lua @@ -1,14 +1,83 @@ -local BaseInstance = import("./BaseInstance") -local json = import("../json") - -local HttpService = BaseInstance:extend("HttpService") - -function HttpService.prototype:JSONEncode(input) - return json.encode(input) -end - -function HttpService.prototype:JSONDecode(input) - return json.decode(input) -end - +local BaseInstance = import("./BaseInstance") +local json = import("../json") + +local HttpService = BaseInstance:extend("HttpService") + +function HttpService:init(instance, httpImpl) + local internalInstance = getmetatable(instance).instance + internalInstance.httpImpl = httpImpl +end + +function HttpService.prototype:JSONEncode(input) + return json.encode(input) +end + +function HttpService.prototype:JSONDecode(input) + return json.decode(input) +end + +function HttpService.prototype:RequestAsync(options) + local internalInstance = getmetatable(self).instance + local httpImpl = internalInstance.httpImpl + + if type(options) ~= "table" then + error(("Bad argument #1 to RequestAsync: expected table, found %s"):format(type(options)), 2) + end + + local url = options.Url + local method = options.Method + local headers = options.Headers + local body = options.body + + if type(url) ~= "string" then + error(("Option `Url` must be a string, but it was a %s"):format(type(url)), 2) + end + + if method ~= nil and type(method) ~= "string" then + error(("Option `Method` must be a string or nil, but it was a %s"):format(type(url)), 2) + end + + if headers ~= nil and type(headers) ~= "table" then + error(("Option `Headers` must be a table or nil, but it was a %s"):format(type(url)), 2) + end + + if body ~= nil and type(body) ~= "string" then + error(("Option `Body` must be a string or nil, but it was a %s"):format(type(url)), 2) + end + + if headers == nil then + headers = {} + end + + if body ~= nil then + headers["Content-Length"] = #body + end + + local responseBody = {} + + local _, statusCode, responseHeaders = httpImpl.request({ + url = url, + sink = httpImpl.tableSink(responseBody), + method = method, + headers = headers, + source = body, + }) + + return { + Success = statusCode >= 200 and statusCode <= 399, + StatusCode = statusCode, + StatusMessage = "uhhh", + Headers = responseHeaders, + Body = table.concat(responseBody), + } +end + +function HttpService.prototype:GetAsync() + error("GetAsync is not implemented by Lemur -- use RequestAsync instead.", 2) +end + +function HttpService.prototype:PostAsync() + error("PostAsync is not implemented by Lemur -- use RequestAsync instead.", 2) +end + return HttpService \ No newline at end of file diff --git a/lib/instances/HttpService_spec.lua b/lib/instances/HttpService_spec.lua index 52ce55a..508c56a 100644 --- a/lib/instances/HttpService_spec.lua +++ b/lib/instances/HttpService_spec.lua @@ -18,4 +18,23 @@ describe("instances.HttpService", function() assert.are.same(instance:JSONDecode("[1,true]"), { 1, true }) end) + + it("should send HTTP requests", function() + local httpImpl = { + request = function() + return 1, 200, {} + end, + tableSink = function() + return {} + end, + } + + local instance = HttpService:new(httpImpl) + + local response = instance:RequestAsync({ + Url = "https://google.com/", + }) + + print(response.Body) + end) end) \ No newline at end of file