mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2026-10-20 22:42:28 +00:00
Relax supported HTTP verbs
There's some really awkward duplication in the HTTP API right now, where
the Lua code reimplements the validation the Java implementation
provides, in order to throw errors at the right level.
In this particular case, our Lua validation was stricter than the Java,
only permitting a known set of verbs. This commit:
- Makes the Java-side validation a little stricter, to only allow verbs
matching [A-Z_-]{1,32}. This is strictly much stricter than what the
HTTP spec allows, but I think makes sense as a restriction.
- Update the Lua wrapper to match this logic, rather than being
stricter.
Fixes #2501.
This commit is contained in:
@@ -103,10 +103,7 @@ public class HTTPAPI implements ILuaAPI {
|
||||
if (requestMethod == null) {
|
||||
httpMethod = postBody == null ? HttpMethod.GET : HttpMethod.POST;
|
||||
} else {
|
||||
httpMethod = HttpMethod.valueOf(requestMethod.toUpperCase(Locale.ROOT));
|
||||
if (httpMethod == null || requestMethod.equalsIgnoreCase("CONNECT")) {
|
||||
throw new LuaException("Unsupported HTTP method");
|
||||
}
|
||||
httpMethod = getMethod(requestMethod.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -174,9 +171,27 @@ public class HTTPAPI implements ILuaAPI {
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpMethod getMethod(String method) throws LuaException {
|
||||
// Reject CONNECT outright, as that requires the ability to read indefinitely.
|
||||
if (method.equals("CONNECT")) throw new LuaException("Unsupported HTTP method");
|
||||
|
||||
// The HTTP specification allows the method to be any token[^1], which is all non-control/separator
|
||||
// characters[^2]. However, we limit ourselves to a more reasonable subset. The allowed characters match
|
||||
// what NGINX does[^3].
|
||||
// [^1] https://www.rfc-editor.org/info/rfc2616/#section-5.1.1
|
||||
// [^2] https://www.rfc-editor.org/info/rfc2616/#section-2.2
|
||||
// [^3]: https://github.com/nginx/nginx/blob/5f54125dde0d144476155d8964f6ec3d449f578d/src/http/ngx_http_parse.c#L283-L285
|
||||
if (method.isEmpty() || method.length() > 32 ||
|
||||
!method.chars().allMatch(c -> (c >= 'A' && c <= 'Z') || c == '_' || c == '-')) {
|
||||
throw new LuaException("Invalid HTTP method");
|
||||
}
|
||||
|
||||
return HttpMethod.valueOf(method);
|
||||
}
|
||||
|
||||
private HttpHeaders getHeaders(Map<?, ?> headerTable) throws LuaException {
|
||||
HttpHeaders headers = new DefaultHttpHeaders();
|
||||
for (Map.Entry<?, ?> entry : headerTable.entrySet()) {
|
||||
for (var entry : headerTable.entrySet()) {
|
||||
var value = entry.getValue();
|
||||
if (entry.getKey() instanceof String && value instanceof String) {
|
||||
try {
|
||||
|
||||
@@ -14,12 +14,6 @@ local expect = dofile("rom/modules/main/cc/expect.lua").expect
|
||||
local native = http
|
||||
local nativeHTTPRequest = http.request
|
||||
|
||||
local methods = {
|
||||
GET = true, POST = true, HEAD = true,
|
||||
OPTIONS = true, PUT = true, DELETE = true,
|
||||
PATCH = true, TRACE = true,
|
||||
}
|
||||
|
||||
local function check_key(options, key, ty, opt)
|
||||
local value = options[key]
|
||||
local valueTy = type(value)
|
||||
@@ -41,8 +35,13 @@ local function check_request_options(options, body)
|
||||
check_key(options, "redirect", "boolean", true)
|
||||
check_key(options, "timeout", "number", true)
|
||||
|
||||
if options.method and not methods[options.method] then
|
||||
error("Unsupported HTTP method", 3)
|
||||
check_key(options, "method", "string", true)
|
||||
if options.method then
|
||||
local method = options.method:upper()
|
||||
if method == "CONNECT" then error("Unsupported HTTP method", 3) end
|
||||
if method == "" or #method > 32 or method:find("[^A-Z_-]") then
|
||||
error("Invalid HTTP method", 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -90,6 +89,7 @@ error or connection timeout.
|
||||
@changed 1.105.0 Added support for custom timeouts.
|
||||
@changed 1.109.0 The returned response now reads the body as raw bytes, rather
|
||||
than decoding from UTF-8.
|
||||
@changed 1.121.0 Relax HTTP verb validation to allow anything matching `[A-Z_-]{1,32}`.
|
||||
|
||||
@usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
|
||||
and print the returned page.
|
||||
@@ -144,6 +144,7 @@ error or connection timeout.
|
||||
@changed 1.105.0 Added support for custom timeouts.
|
||||
@changed 1.109.0 The returned response now reads the body as raw bytes, rather
|
||||
than decoding from UTF-8.
|
||||
@changed 1.121.0 Relax HTTP verb validation to allow anything matching `[A-Z_-]{1,32}`.
|
||||
]]
|
||||
function post(_url, _post, _headers, _binary)
|
||||
if type(_url) == "table" then
|
||||
@@ -197,6 +198,7 @@ from above are passed in as fields instead (for instance,
|
||||
@changed 1.105.0 Added support for custom timeouts.
|
||||
@changed 1.109.0 The returned response now reads the body as raw bytes, rather
|
||||
than decoding from UTF-8.
|
||||
@changed 1.121.0 Relax HTTP verb validation to allow anything matching `[A-Z_-]{1,32}`.
|
||||
]]
|
||||
function request(_url, _post, _headers, _binary)
|
||||
local url
|
||||
|
||||
Reference in New Issue
Block a user