Merge pull request #91199 from GrammAcc/http-redirects

Make HTTPRequest 301 and 302 Redirects Standards-Compliant
This commit is contained in:
Rémi Verschelde 2026-01-09 15:00:43 +01:00
commit 42e3baaf4b
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 34 additions and 0 deletions

View file

@ -209,6 +209,26 @@ void HTTPRequest::cancel_request() {
requesting = false;
}
bool HTTPRequest::_is_content_header(const String &p_header) const {
return (p_header.begins_with("content-type:") || p_header.begins_with("content-length:") || p_header.begins_with("content-location:") || p_header.begins_with("content-encoding:") ||
p_header.begins_with("transfer-encoding:") || p_header.begins_with("connection:") || p_header.begins_with("authorization:"));
}
bool HTTPRequest::_is_method_safe() const {
return (method == HTTPClient::METHOD_GET || method == HTTPClient::METHOD_HEAD || method == HTTPClient::METHOD_OPTIONS || method == HTTPClient::METHOD_TRACE);
}
Error HTTPRequest::_get_redirect_headers(Vector<String> *r_headers) {
for (const String &E : headers) {
const String h = E.to_lower();
// We strip content headers when changing a redirect to GET.
if (!_is_content_header(h)) {
r_headers->push_back(E);
}
}
return OK;
}
bool HTTPRequest::_handle_response(bool *ret_value) {
if (!client->has_response()) {
_defer_done(RESULT_NO_RESPONSE, 0, PackedStringArray(), PackedByteArray());
@ -268,6 +288,16 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
final_body_size.set(0);
redirections = new_redirs;
*ret_value = false;
if (!_is_method_safe()) {
// 301, 302, and 303 are changed to GET for unsafe methods.
// See: https://www.rfc-editor.org/rfc/rfc9110#section-15.4-3.1
method = HTTPClient::METHOD_GET;
// Content headers should be dropped if changing method.
// See: https://www.rfc-editor.org/rfc/rfc9110#section-15.4-6.2.1
Vector<String> req_headers;
_get_redirect_headers(&req_headers);
headers = req_headers;
}
return true;
}
}

View file

@ -102,6 +102,10 @@ private:
void _redirect_request(const String &p_new_url);
bool _is_content_header(const String &p_header) const;
bool _is_method_safe() const;
Error _get_redirect_headers(Vector<String> *r_headers);
bool _handle_response(bool *ret_value);
Error _parse_url(const String &p_url);