HttpService has several limitations:
- The only supported HTTP methods are GET and POST. Many web services require the use of other methods such as PUT, PATCH, or DELETE
- Response headers are not exposed. Sometimes response headers contain information needed for further requests.
- Response status code and reason phrase are not exposed. They are useful for determining why requests are rejected by the server.
- When sending a POST request, content types are restricted to a whitelist of mime types. The user should be allowed to specify arbitrary content types as there is no security risk and no reason to constrain them
I propose the following method be added to HttpService:
YieldFunction table HttpService:RequestAsync(table requestOptions)
The method would take a Lua table as a parameter and return a Lua table to represent the response. Note that this method would not error for 4xx or 5xx error codes, but it would error if it is unable to send the HTTP request or unable to get a response from the server. Here are the formats for the request table and the response table:
HttpRequest
string Method = "GET" // defaults to GET
string Url
dictionary<string, string> Headers
string Body
HttpResponse
bool Success // true if StatusCode is 2xx
int StatusCode
string ReasonPhrase
string Body
dictionary<string, string> Headers
Basic usage:
local requestOptions = {
Url = "https://www.google.com/robots.txt"
}
local response = HttpService:RequestAsync(request)
if response.Success then
print(response.Body)
else
warn(string.format("Request failed with a status code of %d", response.StatusCode))
end
More advanced usage:
local requestOptions = {
Url = "https://api.example.com/v1/login",
Body = string.format("username=Shedletsky&password=hunter2",
Headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
}
local response = game:GetService("HttpService"):RequestAsync(requestOptions)
if response.Success and response.StatusCode == 200 then
console.log(response.Headers["Set-Cookie"])
end
Any unknown fields in the requestOptions table will cause an error to be thrown, making it easy to find typos. A field being invalid (e.g. requestOptions.Url is not a string) will also cause an error to be thrown.
Headers will follow the same blacklist restrictions as HttpService:GetAsync and HttpService:PostAsync do.
The method must be valid according to RFC 2616, meaning it cannot contain spaces, control characters, etc. An error will be thrown if the method isn’t valid.
token = 1*<any CHAR except CTLs or separators>
CTL = <any US-ASCII control character
(octets 0 - 31) and DEL (127)>
separators = "(" | ")" | "<" | ">" | "@"
| "," | ";" | ":" | "\" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
SP = <US-ASCII SP, space (32)>
HT = <US-ASCII HT, horizontal-tab (9)>