Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Web] Always return -1 as body length in HTTPClientWeb #79846

Merged
merged 1 commit into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/classes/HTTPClient.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<description>
Returns the response's body length.
[b]Note:[/b] Some Web servers may not send a body length. In this case, the value returned will be [code]-1[/code]. If using chunked transfer encoding, the body length will also be [code]-1[/code].
[b]Note:[/b] This function always returns [code]-1[/code] on the Web platform due to browsers limitations.
</description>
</method>
<method name="get_response_code" qualifiers="const">
Expand Down
10 changes: 9 additions & 1 deletion platform/web/http_client_web.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,15 @@ Error HTTPClientWeb::get_response_headers(List<String> *r_response) {
}

int64_t HTTPClientWeb::get_response_body_length() const {
return godot_js_fetch_body_length_get(js_id);
// Body length cannot be consistently retrieved from the web.
// Reading the "content-length" value will return a meaningless value when the response is compressed,
// as reading will return uncompressed chunks in any case, resulting in a mismatch between the detected
// body size and the actual size returned by repeatedly calling read_response_body_chunk.
// Additionally, while "content-length" is considered a safe CORS header, "content-encoding" is not,
// so using the "content-encoding" to decide if "content-length" is meaningful is not an option either.
// We simply must accept the fact that browsers are awful when it comes to networking APIs.
// See GH-47597, and GH-79327.
return -1;
}

PackedByteArray HTTPClientWeb::read_response_body_chunk() {
Expand Down
1 change: 0 additions & 1 deletion platform/web/http_client_web.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ extern int godot_js_fetch_read_headers(int p_id, void (*parse_callback)(int p_si
extern int godot_js_fetch_read_chunk(int p_id, uint8_t *p_buf, int p_buf_size);
extern void godot_js_fetch_free(int p_id);
extern godot_js_fetch_state_t godot_js_fetch_state_get(int p_id);
extern int godot_js_fetch_body_length_get(int p_id);
extern int godot_js_fetch_http_status_get(int p_id);
extern int godot_js_fetch_is_chunked(int p_id);

Expand Down
15 changes: 0 additions & 15 deletions platform/web/js/libs/library_godot_fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,17 @@ const GodotFetch = {
return;
}
let chunked = false;
let bodySize = -1;
response.headers.forEach(function (value, header) {
const v = value.toLowerCase().trim();
const h = header.toLowerCase().trim();
if (h === 'transfer-encoding' && v === 'chunked') {
chunked = true;
}
if (h === 'content-length') {
bodySize = parseInt(v, 10);
}
});
obj.status = response.status;
obj.response = response;
obj.reader = response.body.getReader();
obj.chunked = chunked;
obj.bodySize = bodySize;
},

onerror: function (id, err) {
Expand All @@ -87,7 +82,6 @@ const GodotFetch = {
reading: false,
status: 0,
chunks: [],
bodySize: -1,
};
const id = IDHandler.add(obj);
const init = {
Expand Down Expand Up @@ -224,15 +218,6 @@ const GodotFetch = {
return p_buf_size - to_read;
},

godot_js_fetch_body_length_get__sig: 'ii',
godot_js_fetch_body_length_get: function (p_id) {
const obj = IDHandler.get(p_id);
if (!obj || !obj.response) {
return -1;
}
return obj.bodySize;
},

godot_js_fetch_is_chunked__sig: 'ii',
godot_js_fetch_is_chunked: function (p_id) {
const obj = IDHandler.get(p_id);
Expand Down
Loading