From 258bb29ba21273f58c39b06dc8372a50656fc0ee Mon Sep 17 00:00:00 2001 From: ldm0 Date: Mon, 19 Oct 2026 04:57:24 +0800 Subject: [PATCH] fix(fetch): preserve worker continuation upload bytes --- .../src/domains/fetch/tests/binary_request.rs | 157 ++++++++++++++++-- .../subresource_fetch/pending_fetch.rs | 48 +++--- .../global_scope/content_security_policy.rs | 6 +- .../src/worker/global_scope/fetch.rs | 51 +++--- .../src/worker/global_scope/network_state.rs | 8 +- .../src/worker/global_scope/xhr.rs | 17 +- moli-renderer-v8/src/worker/handle.rs | 6 +- .../src/worker/thread/tests/mod.rs | 4 +- 8 files changed, 217 insertions(+), 80 deletions(-) diff --git a/moli-protocol/src/domains/fetch/tests/binary_request.rs b/moli-protocol/src/domains/fetch/tests/binary_request.rs index 05d8d3bb6e..e4582234e4 100644 --- a/moli-protocol/src/domains/fetch/tests/binary_request.rs +++ b/moli-protocol/src/domains/fetch/tests/binary_request.rs @@ -3,7 +3,14 @@ use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STANDARD}; const BODY: &[u8] = &[0, 255, 195, 40, 128, 65]; +enum RequestScope { + Window, + Worker, + SharedWorker, +} + async fn binary_request_round_trip( + scope: RequestScope, xhr: bool, chained: bool, replacement: Option<&str>, @@ -60,15 +67,49 @@ async fn binary_request_round_trip( id += 1; } } + ctx.process_async(json!({"id":id,"method":"Runtime.enable","sessionId":"SID-1"})) + .await; + ctx.expect_result(id, json!({}), Some("SID-1")); + id += 1; + let api = serde_json::to_string(&api_url).unwrap(); let send = if xhr { - "new Promise((resolve,reject)=>{const x=new XMLHttpRequest();x.open('POST','/echo');x.onload=()=>resolve(JSON.parse(x.responseText));x.onerror=reject;x.send(bytes);})" + format!( + "new Promise((resolve,reject)=>{{const x=new XMLHttpRequest();x.open('POST',{api});x.onload=()=>resolve(JSON.parse(x.responseText));x.onerror=reject;x.send(bytes);}})" + ) } else { - "fetch('/echo',{method:'POST',body:bytes}).then(r=>r.json())" + format!("fetch({api},{{method:'POST',body:bytes}}).then(r=>r.json())") }; - ctx.process_async(json!({"id":id,"method":"Runtime.evaluate","sessionId":"SID-1", - "params":{"expression":format!( - "globalThis.binaryResult=null; const bytes=new Uint8Array({}); {send}.then(v=>globalThis.binaryResult=v); 'scheduled'", - json!(BODY)),"returnByValue":true}})).await; + let bytes = format!("const bytes=new Uint8Array({});", json!(BODY)); + let on_message = + "event => { globalThis.binaryResult=event.data; console.log('binary upload completed'); }"; + let script = match scope { + RequestScope::Window => format!( + "{bytes} {send}.then(value=>{{globalThis.binaryResult=value;console.log('binary upload completed');}});" + ), + RequestScope::Worker => { + let source = + serde_json::to_string(&format!("{bytes} {send}.then(value=>postMessage(value));")) + .unwrap(); + format!( + "globalThis.binaryWorker=new Worker(URL.createObjectURL(new Blob([{source}],{{type:'text/javascript'}}))); binaryWorker.onmessage={on_message};" + ) + } + RequestScope::SharedWorker => { + let source = serde_json::to_string(&format!( + "onconnect=event=>{{const port=event.ports[0];{bytes} {send}.then(value=>port.postMessage(value));}};" + )) + .unwrap(); + format!( + "globalThis.binaryWorker=new SharedWorker(URL.createObjectURL(new Blob([{source}],{{type:'text/javascript'}}))); binaryWorker.port.onmessage={on_message}; binaryWorker.port.start();" + ) + } + }; + ctx.process_async( + json!({"id":id,"method":"Runtime.evaluate","sessionId":"SID-1", + "params":{"expression":format!("globalThis.binaryResult=null; {script} 'scheduled'"), + "returnByValue":true}}), + ) + .await; let response = take_response_by_id(&mut ctx, id); assert_eq!(response["result"]["result"]["value"], "scheduled"); id += 1; @@ -117,6 +158,10 @@ async fn binary_request_round_trip( |messages| { messages.iter().any(|m| { m["method"] == "Network.loadingFinished" && m["params"]["requestId"] == network_id + }) && messages.iter().any(|m| { + m["method"] == "Runtime.consoleAPICalled" + && m["sessionId"] == "SID-1" + && m["params"]["args"][0]["value"] == "binary upload completed" }) }, ) @@ -147,35 +192,115 @@ async fn binary_request_round_trip( ) .await; let body = replacement.map_or_else(|| BASE64_STANDARD.encode(BODY), str::to_owned); - ctx.expect_result( - id, - json!({"postData":body,"base64Encoded":replacement.is_none()}), - Some("SID-1"), - ); + if replacement == Some("") { + // Keep the existing Network API contract for an empty upload; the + // server and JavaScript assertions above still require zero bytes. + ctx.expect_error(id, -32000, "No post data available for the request"); + } else { + ctx.expect_result( + id, + json!({"postData":body,"base64Encoded":replacement.is_none()}), + Some("SID-1"), + ); + } server.abort(); } #[tokio::test(flavor = "multi_thread")] async fn fetch_noop_preserves_binary_request_body() { - binary_request_round_trip(false, false, None, false).await; + binary_request_round_trip(RequestScope::Window, false, false, None, false).await; } #[tokio::test(flavor = "multi_thread")] async fn xhr_noop_preserves_binary_request_body() { - binary_request_round_trip(true, false, None, false).await; + binary_request_round_trip(RequestScope::Window, true, false, None, false).await; } #[tokio::test(flavor = "multi_thread")] async fn chained_fetch_noop_preserves_binary_request_body() { - binary_request_round_trip(false, true, None, false).await; + binary_request_round_trip(RequestScope::Window, false, true, None, false).await; } #[tokio::test(flavor = "multi_thread")] async fn chained_fetch_text_override_replaces_binary_request_body() { - binary_request_round_trip(false, true, Some("replacement"), false).await; + binary_request_round_trip( + RequestScope::Window, + false, + true, + Some("replacement"), + false, + ) + .await; } #[tokio::test(flavor = "multi_thread")] async fn paused_fetch_exposes_binary_request_body() { - binary_request_round_trip(false, false, None, true).await; + binary_request_round_trip(RequestScope::Window, false, false, None, true).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn worker_fetch_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, false, false, None, false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn worker_xhr_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, true, false, None, false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_fetch_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, false, true, None, false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_xhr_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, true, true, None, false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_fetch_empty_override_replaces_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, false, true, Some(""), false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_xhr_empty_override_replaces_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, true, true, Some(""), false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_fetch_text_override_replaces_binary_request_body() { + binary_request_round_trip( + RequestScope::Worker, + false, + true, + Some("replacement"), + false, + ) + .await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn chained_worker_xhr_text_override_replaces_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, true, true, Some("replacement"), false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn paused_worker_fetch_exposes_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, false, false, None, true).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn paused_worker_xhr_exposes_binary_request_body() { + binary_request_round_trip(RequestScope::Worker, true, false, None, true).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn shared_worker_fetch_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::SharedWorker, false, false, None, false).await; +} + +#[tokio::test(flavor = "multi_thread")] +async fn shared_worker_xhr_noop_preserves_binary_request_body() { + binary_request_round_trip(RequestScope::SharedWorker, true, false, None, false).await; } diff --git a/moli-renderer-v8/src/script_vm/subresource_fetch/pending_fetch.rs b/moli-renderer-v8/src/script_vm/subresource_fetch/pending_fetch.rs index b3ac1b1fda..56de20d131 100644 --- a/moli-renderer-v8/src/script_vm/subresource_fetch/pending_fetch.rs +++ b/moli-renderer-v8/src/script_vm/subresource_fetch/pending_fetch.rs @@ -85,7 +85,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response, handle_auth_requests, @@ -142,7 +142,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response, handle_auth_requests, @@ -188,7 +188,6 @@ impl ScriptVm { let report_id = target.report_id(); let request_url = url.unwrap_or_else(|| info.url.clone()); let request_method = method.unwrap_or_else(|| info.method.clone()); - let request_body = body.unwrap_or_else(|| info.request_body.clone()); let request_headers = headers.unwrap_or_else(|| info.request_headers.clone()); let continued = self.continue_worker_owned_csp_report( target, @@ -199,7 +198,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url, method: request_method, - body: request_body, + body: info.request_body_bytes.clone(), headers: request_headers, intercept_response: false, handle_auth_requests: false, @@ -559,6 +558,7 @@ impl ScriptVm { initial_network_request_headers, response, } = pending; + // A redirect may have discarded the upload before the auth challenge. if let Some(target) = WorkerOwnedFetchTarget::from_continuation(&pending_fetch.continuation) { let request_headers = original_request_headers; @@ -571,7 +571,9 @@ impl ScriptVm { network_request_handle: pending_fetch.info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: request_body + .as_ref() + .and_then(|_| pending_fetch.info.request_body_bytes.clone()), headers: request_headers.clone(), intercept_response, handle_auth_requests: true, @@ -607,7 +609,9 @@ impl ScriptVm { network_request_handle: pending_fetch.info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: request_body + .as_ref() + .and_then(|_| pending_fetch.info.request_body_bytes.clone()), headers: request_headers.clone(), intercept_response, handle_auth_requests: true, @@ -768,7 +772,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -801,7 +805,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -932,7 +936,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: info.url.clone(), method: info.method.clone(), - body: info.request_body.clone(), + body: info.request_body_bytes.clone(), headers: info.request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -977,7 +981,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: info.url.clone(), method: info.method.clone(), - body: info.request_body.clone(), + body: info.request_body_bytes.clone(), headers: info.request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1022,7 +1026,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: info.url.clone(), method: info.method.clone(), - body: info.request_body.clone(), + body: info.request_body_bytes.clone(), headers: info.request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1179,7 +1183,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1228,7 +1232,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1286,7 +1290,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1335,7 +1339,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1386,7 +1390,7 @@ impl ScriptVm { network_request_handle: info.network_request_handle, url: request_url.clone(), method: request_method.clone(), - body: request_body.clone(), + body: info.request_body_bytes.clone(), headers: request_headers.clone(), intercept_response: false, handle_auth_requests: false, @@ -1602,7 +1606,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -1663,7 +1667,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -1752,7 +1756,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -1783,7 +1787,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -1892,7 +1896,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, @@ -1956,7 +1960,7 @@ impl ScriptVm { network_request_handle: pending.pending.info.network_request_handle, url: pending.request_url, method: pending.request_method, - body: pending.request_body, + body: pending.pending.info.request_body_bytes.clone(), headers: pending.request_headers, intercept_response: false, handle_auth_requests: false, diff --git a/moli-renderer-v8/src/worker/global_scope/content_security_policy.rs b/moli-renderer-v8/src/worker/global_scope/content_security_policy.rs index 6af2d4c782..f125d729c0 100644 --- a/moli-renderer-v8/src/worker/global_scope/content_security_policy.rs +++ b/moli-renderer-v8/src/worker/global_scope/content_security_policy.rs @@ -529,8 +529,8 @@ pub(in crate::worker) fn continue_pending_worker_csp_report( else { return; }; - let request_body = continuation.body.clone(); - let request = match Request::new( + let request_body = request_body_text(&continuation.body); + let request = match Request::new_bytes( &continuation.method, continuation.url.as_str(), continuation.body.clone(), @@ -677,7 +677,7 @@ fn record_worker_content_security_policy_report_failure( request.url, request.method, request.request_headers.clone(), - request_body, + request_body.map(String::into_bytes), SubresourceResourceType::CspReport, message, ); diff --git a/moli-renderer-v8/src/worker/global_scope/fetch.rs b/moli-renderer-v8/src/worker/global_scope/fetch.rs index cf67434508..5743b90512 100644 --- a/moli-renderer-v8/src/worker/global_scope/fetch.rs +++ b/moli-renderer-v8/src/worker/global_scope/fetch.rs @@ -24,7 +24,7 @@ pub(in crate::worker) fn record_worker_subresource_failure( url, method, request_headers, - request_body, + request_body.map(String::into_bytes), resource_type, error_text, ); @@ -37,7 +37,7 @@ pub(in crate::worker) fn record_worker_subresource_failure_with_handle( url: Url, method: String, request_headers: moli_fetch::RequestHeaders, - request_body: Option, + request_body_bytes: Option>, resource_type: SubresourceResourceType, error_text: String, ) { @@ -47,10 +47,11 @@ pub(in crate::worker) fn record_worker_subresource_failure_with_handle( url, method, request_headers, - request_body, + request_body_text(&request_body_bytes), resource_type, error_text, - ); + ) + .with_request_body_bytes(request_body_bytes); if let Some(handle) = request_handle { record = record.with_request_handle(handle); } @@ -77,7 +78,7 @@ pub(in crate::worker) fn record_worker_subresource_success( url, method, request_headers, - request_body, + request_body.map(String::into_bytes), resource_type, None, head, @@ -92,7 +93,7 @@ pub(in crate::worker) fn record_worker_subresource_success_with_handle( url: Url, method: String, request_headers: moli_fetch::RequestHeaders, - request_body: Option, + request_body_bytes: Option>, resource_type: SubresourceResourceType, network_request_headers: Option>, head: ResponseHead, @@ -104,7 +105,7 @@ pub(in crate::worker) fn record_worker_subresource_success_with_handle( url, method, request_headers, - request_body, + request_body_text(&request_body_bytes), resource_type, head.request_cookie_report.clone(), head.redirect_chain @@ -118,6 +119,7 @@ pub(in crate::worker) fn record_worker_subresource_success_with_handle( body, head.cookie_set_reports.clone(), ) + .with_request_body_bytes(request_body_bytes) .with_from_cache(head.from_cache) .with_negotiated_http_version(head.negotiated_http_version) .with_network_request_headers(network_request_headers); @@ -690,7 +692,7 @@ pub(in crate::worker) fn continue_pending_worker_fetch( url: request.url.clone(), method: request.method.clone(), request_headers: request.headers.clone(), - request_body: request.body.clone(), + request_body_bytes: request.body.clone(), initial_network_request_headers, intercept_response: request.intercept_response, handle_auth_requests: request.handle_auth_requests, @@ -726,7 +728,7 @@ pub(in crate::worker) fn continue_pending_worker_fetch( network_partition_key, resolved_url, method, - body.map(|body| body.into_bytes()), + body, headers, request_mode, credentials_mode, @@ -759,7 +761,7 @@ pub(in crate::worker) fn fail_pending_worker_fetch( url: request.url, method: request.method, request_headers: request.headers, - request_body: request.body, + request_body_bytes: request.body, initial_network_request_headers: None, intercept_response: false, handle_auth_requests: false, @@ -823,7 +825,7 @@ pub(in crate::worker) fn fulfill_pending_worker_fetch( url: request.url.clone(), method: request.method.clone(), request_headers: request.headers.clone(), - request_body: request.body.clone(), + request_body_bytes: request.body.clone(), initial_network_request_headers: None, intercept_response: false, handle_auth_requests: false, @@ -1013,7 +1015,7 @@ pub(in crate::worker) fn continue_pending_worker_xhr( url: request.url.clone(), method: request.method.clone(), request_headers: request.headers.clone(), - request_body: request.body.clone(), + request_body_bytes: request.body.clone(), initial_network_request_headers, intercept_response: request.intercept_response, handle_auth_requests: request.handle_auth_requests, @@ -1046,7 +1048,7 @@ pub(in crate::worker) fn continue_pending_worker_xhr( network_partition_key, resolved_url, method, - body.map(|body| body.into_bytes()), + body, headers, credentials_mode, use_cors_preflight, @@ -1076,7 +1078,7 @@ pub(in crate::worker) fn fail_pending_worker_xhr( url: request.url, method: request.method, request_headers: request.headers, - request_body: request.body, + request_body_bytes: request.body, initial_network_request_headers: None, intercept_response: false, handle_auth_requests: false, @@ -1138,7 +1140,7 @@ pub(in crate::worker) fn fulfill_pending_worker_xhr( url: request.url.clone(), method: request.method.clone(), request_headers: request.headers.clone(), - request_body: request.body.clone(), + request_body_bytes: request.body.clone(), initial_network_request_headers: None, intercept_response: false, handle_auth_requests: false, @@ -2260,7 +2262,7 @@ pub(in crate::worker) fn worker_fetch_callback<'s>( websocket_socket_id: None, method, request_headers: headers, - request_body_bytes: request_body.as_ref().map(|body| body.as_bytes().to_vec()), + request_body_bytes: body, request_body, resource_type: SubresourceResourceType::Fetch, request_cookie_report: None, @@ -2467,7 +2469,7 @@ pub(in crate::worker) fn reject_worker_fetches_for_signal<'s>( record.url, record.method, record.request_headers, - record.request_body, + record.request_body_bytes, SubresourceResourceType::Fetch, ABORTED_ERROR_TEXT.to_owned(), ); @@ -2698,7 +2700,7 @@ pub(in crate::worker) fn finish_worker_streaming_fetch( record.url, record.method, record.request_headers, - record.request_body, + record.request_body_bytes, SubresourceResourceType::Fetch, record.initial_network_request_headers, head, @@ -2742,7 +2744,7 @@ pub(in crate::worker) fn record_worker_fetch_failure( record.url.clone(), record.method.clone(), record.request_headers.clone(), - record.request_body.clone(), + record.request_body_bytes.clone(), SubresourceResourceType::Fetch, network_error_text, ); @@ -2763,7 +2765,10 @@ pub(in crate::worker) fn record_worker_fetch_failure( pending.request_url.clone(), pending.request_method.clone(), pending.request_headers.clone(), - pending.request_body.clone(), + pending + .request_body + .as_ref() + .map(|body| body.as_bytes().to_vec()), SubresourceResourceType::Fetch, network_error_text, ); @@ -2877,7 +2882,7 @@ pub(in crate::worker) fn drain_worker_fetch_completion_result( url: record.url.clone(), method: record.method.clone(), request_headers: record.request_headers.clone(), - request_body: record.request_body.clone(), + request_body: request_body_text(&record.request_body_bytes), resource_type: SubresourceResourceType::Fetch, request_cookie_report: response_head.request_cookie_report.clone(), network_request_headers: record.initial_network_request_headers.clone(), @@ -2914,7 +2919,7 @@ pub(in crate::worker) fn drain_worker_fetch_completion_result( final_url: response_head.final_url.clone(), method: record.method.clone(), request_headers: record.request_headers.clone(), - request_body: record.request_body.clone(), + request_body: request_body_text(&record.request_body_bytes), resource_type: SubresourceResourceType::Fetch, request_cookie_report: response_head.request_cookie_report.clone(), network_request_headers: record.initial_network_request_headers.clone(), @@ -3010,7 +3015,7 @@ pub(in crate::worker) fn drain_worker_fetch_completion_result( record.url.clone(), record.method.clone(), record.request_headers.clone(), - record.request_body.clone(), + record.request_body_bytes.clone(), SubresourceResourceType::Fetch, record.initial_network_request_headers.clone(), response_head.clone(), diff --git a/moli-renderer-v8/src/worker/global_scope/network_state.rs b/moli-renderer-v8/src/worker/global_scope/network_state.rs index 42455cc24a..d6e45cbb90 100644 --- a/moli-renderer-v8/src/worker/global_scope/network_state.rs +++ b/moli-renderer-v8/src/worker/global_scope/network_state.rs @@ -113,7 +113,7 @@ pub(in crate::worker) struct PendingWorkerFetchNetworkRecord { pub(in crate::worker) url: Url, pub(in crate::worker) method: String, pub(in crate::worker) request_headers: moli_fetch::RequestHeaders, - pub(in crate::worker) request_body: Option, + pub(in crate::worker) request_body_bytes: Option>, pub(in crate::worker) initial_network_request_headers: Option>, pub(in crate::worker) intercept_response: bool, pub(in crate::worker) handle_auth_requests: bool, @@ -127,7 +127,7 @@ impl PendingWorkerFetchNetworkRecord { let mut request = Request::get_with_url(self.url.clone()) .with_redirect_headers(self.redirect_headers.take()); request.method = std::mem::take(&mut self.method); - request.body = self.request_body.clone().map(String::into_bytes); + request.body = self.request_body_bytes.clone(); request.request_headers = std::mem::take(&mut self.request_headers); for redirect in &head.redirect_chain { request.apply_redirect_status(redirect.status); @@ -135,9 +135,7 @@ impl PendingWorkerFetchNetworkRecord { self.url = head.final_url.clone(); self.method = request.method; self.request_headers = request.request_headers; - if request.body.is_none() { - self.request_body = None; - } + self.request_body_bytes = request.body; } } diff --git a/moli-renderer-v8/src/worker/global_scope/xhr.rs b/moli-renderer-v8/src/worker/global_scope/xhr.rs index 3cba40aba5..59eac243d3 100644 --- a/moli-renderer-v8/src/worker/global_scope/xhr.rs +++ b/moli-renderer-v8/src/worker/global_scope/xhr.rs @@ -238,7 +238,7 @@ pub(in crate::worker) fn worker_xhr_timeout_callback( record.url, record.method, record.request_headers, - record.request_body, + record.request_body_bytes, SubresourceResourceType::Xhr, WORKER_XHR_TIMEOUT_ERROR_TEXT.to_owned(), ); @@ -831,7 +831,7 @@ pub(crate) fn try_worker_xhr_abort_callback( record.url, record.method, record.request_headers, - record.request_body, + record.request_body_bytes, SubresourceResourceType::Xhr, ABORTED_ERROR_TEXT.to_owned(), ); @@ -882,7 +882,7 @@ pub(in crate::worker) fn record_worker_xhr_failure( record.url.clone(), record.method.clone(), record.request_headers.clone(), - record.request_body.clone(), + record.request_body_bytes.clone(), SubresourceResourceType::Xhr, network_error_text, ); @@ -903,7 +903,10 @@ pub(in crate::worker) fn record_worker_xhr_failure( pending.request_url.clone(), pending.request_method.clone(), pending.request_headers.clone(), - pending.request_body.clone(), + pending + .request_body + .as_ref() + .map(|body| body.as_bytes().to_vec()), SubresourceResourceType::Xhr, network_error_text, ); @@ -1026,7 +1029,7 @@ pub(in crate::worker) fn drain_worker_xhr_completion( url: record.url.clone(), method: record.method.clone(), request_headers: record.request_headers.clone(), - request_body: record.request_body.clone(), + request_body: request_body_text(&record.request_body_bytes), resource_type: SubresourceResourceType::Xhr, request_cookie_report: response_head.request_cookie_report.clone(), network_request_headers: record.initial_network_request_headers.clone(), @@ -1064,7 +1067,7 @@ pub(in crate::worker) fn drain_worker_xhr_completion( final_url: response_head.final_url.clone(), method: record.method.clone(), request_headers: record.request_headers.clone(), - request_body: record.request_body.clone(), + request_body: request_body_text(&record.request_body_bytes), resource_type: SubresourceResourceType::Xhr, request_cookie_report: response_head.request_cookie_report.clone(), network_request_headers: record.initial_network_request_headers.clone(), @@ -1121,7 +1124,7 @@ pub(in crate::worker) fn drain_worker_xhr_completion( record.url.clone(), record.method.clone(), record.request_headers.clone(), - record.request_body.clone(), + record.request_body_bytes.clone(), SubresourceResourceType::Xhr, record.initial_network_request_headers.clone(), response_head.clone(), diff --git a/moli-renderer-v8/src/worker/handle.rs b/moli-renderer-v8/src/worker/handle.rs index b2e1d81c24..74bb7d44a0 100644 --- a/moli-renderer-v8/src/worker/handle.rs +++ b/moli-renderer-v8/src/worker/handle.rs @@ -571,7 +571,8 @@ pub(crate) struct WorkerPendingFetchContinue { pub(crate) network_request_handle: Option, pub(crate) url: Url, pub(crate) method: String, - pub(crate) body: Option, + /// Upload bytes after applying explicit overrides, including an empty body. + pub(crate) body: Option>, pub(crate) headers: moli_fetch::RequestHeaders, pub(crate) intercept_response: bool, pub(crate) handle_auth_requests: bool, @@ -586,7 +587,8 @@ pub(crate) struct WorkerPendingXhrContinue { pub(crate) network_request_handle: Option, pub(crate) url: Url, pub(crate) method: String, - pub(crate) body: Option, + /// Upload bytes after applying explicit overrides, including an empty body. + pub(crate) body: Option>, pub(crate) headers: moli_fetch::RequestHeaders, pub(crate) intercept_response: bool, pub(crate) handle_auth_requests: bool, diff --git a/moli-renderer-v8/src/worker/thread/tests/mod.rs b/moli-renderer-v8/src/worker/thread/tests/mod.rs index 0fc1338287..aa55829d57 100644 --- a/moli-renderer-v8/src/worker/thread/tests/mod.rs +++ b/moli-renderer-v8/src/worker/thread/tests/mod.rs @@ -857,7 +857,7 @@ fn pending_worker_fetch_continue( network_request_handle: Some(owner_assigned_request_handle(internal_id)), url: info.url.clone(), method: info.method.clone(), - body: info.request_body.clone(), + body: info.request_body_bytes.clone(), headers: info.request_headers.clone(), intercept_response, handle_auth_requests: false, @@ -878,7 +878,7 @@ fn pending_worker_xhr_continue( network_request_handle: Some(owner_assigned_request_handle(internal_id)), url: info.url.clone(), method: info.method.clone(), - body: info.request_body.clone(), + body: info.request_body_bytes.clone(), headers: info.request_headers.clone(), intercept_response, handle_auth_requests: false,