mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
fix: support response.url in net.fetch
This commit is contained in:
@@ -102,3 +102,8 @@ duplicates are not merged.
|
||||
// '*/*' ]
|
||||
console.log(response.rawHeaders)
|
||||
```
|
||||
|
||||
#### `response.urlList`
|
||||
|
||||
A `string[]` containing the chain of urls traversed by this request.
|
||||
If the request had no redirects, this array will contain one element.
|
||||
|
||||
@@ -106,11 +106,21 @@ export function fetchWithSession (input: RequestInfo, init: (RequestInit & {bypa
|
||||
}
|
||||
const nullBodyStatus = [101, 204, 205, 304];
|
||||
const body = nullBodyStatus.includes(resp.statusCode) || req.method === 'HEAD' ? null : Readable.toWeb(resp as unknown as Readable) as ReadableStream;
|
||||
type ResponseInitWithUrlList = ResponseInit & { urlList?: URL[] };
|
||||
const urlList = resp.urlList.map((url) => {
|
||||
let parsedURL;
|
||||
try {
|
||||
parsedURL = new URL(url);
|
||||
} catch {
|
||||
}
|
||||
return parsedURL;
|
||||
});
|
||||
const rResp = new Response(body, {
|
||||
headers,
|
||||
status: resp.statusCode,
|
||||
statusText: resp.statusMessage
|
||||
});
|
||||
statusText: resp.statusMessage,
|
||||
urlList
|
||||
} as ResponseInitWithUrlList);
|
||||
(rResp as any).__original_resp = resp;
|
||||
p.resolve(rResp);
|
||||
});
|
||||
|
||||
@@ -98,6 +98,10 @@ class IncomingMessage extends Readable {
|
||||
throw new Error('HTTP trailers are not supported');
|
||||
}
|
||||
|
||||
get urlList () {
|
||||
return this._responseHead.urlList;
|
||||
}
|
||||
|
||||
_storeInternalData (chunk: Buffer | null, resume: (() => void) | null) {
|
||||
// save the network callback for use in _pushInternalData
|
||||
this._resume = resume;
|
||||
@@ -460,7 +464,7 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
}
|
||||
});
|
||||
|
||||
this._urlLoader.on('redirect', (event, redirectInfo, headers) => {
|
||||
this._urlLoader.on('redirect', (event, redirectInfo, responseHead) => {
|
||||
const { statusCode, newMethod, newUrl } = redirectInfo;
|
||||
if (this._redirectPolicy === 'error') {
|
||||
this._die(new Error('Attempted to redirect, but redirect policy was \'error\''));
|
||||
@@ -468,7 +472,7 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
let _followRedirect = false;
|
||||
this._followRedirectCb = () => { _followRedirect = true; };
|
||||
try {
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, headers);
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, responseHead.headers);
|
||||
} finally {
|
||||
this._followRedirectCb = undefined;
|
||||
if (!_followRedirect && !this._aborted) {
|
||||
@@ -481,7 +485,7 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
// though...? Since the redirect will happen regardless.)
|
||||
try {
|
||||
this._followRedirectCb = () => {};
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, headers);
|
||||
this.emit('redirect', statusCode, newMethod, newUrl, responseHead.headers);
|
||||
} finally {
|
||||
this._followRedirectCb = undefined;
|
||||
}
|
||||
|
||||
@@ -140,3 +140,4 @@ build_disable_thin_lto_mac.patch
|
||||
build_add_public_config_simdutf_config.patch
|
||||
revert_code_health_clean_up_stale_macwebcontentsocclusion.patch
|
||||
check_for_unit_to_activate_before_notifying_about_success.patch
|
||||
feat_expose_url_chain_from_urlloader.patch
|
||||
|
||||
38
patches/chromium/feat_expose_url_chain_from_urlloader.patch
Normal file
38
patches/chromium/feat_expose_url_chain_from_urlloader.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Tue, 19 Nov 2024 17:52:08 +0900
|
||||
Subject: feat: expose url chain from urlloader
|
||||
|
||||
The patch adds the url chain to the URLResponseHead struct. This is
|
||||
used to support the Response.url property in the Fetch API.
|
||||
|
||||
Should be upstreamed.
|
||||
|
||||
diff --git a/services/network/public/mojom/url_response_head.mojom b/services/network/public/mojom/url_response_head.mojom
|
||||
index e7390e01f113755613f42d592b36108b703960dc..123636abfd4e8497668356202353cb08a48e99fc 100644
|
||||
--- a/services/network/public/mojom/url_response_head.mojom
|
||||
+++ b/services/network/public/mojom/url_response_head.mojom
|
||||
@@ -53,6 +53,10 @@ struct URLResponseHead {
|
||||
// Actual response headers, as obtained from the network stack.
|
||||
array<HttpRawHeaderPair> raw_response_headers;
|
||||
|
||||
+ // The chain of urls traversed by this request. If the request had no
|
||||
+ // redirects, this vector will contain one element.
|
||||
+ array<url.mojom.Url> url_list;
|
||||
+
|
||||
// The mime type of the response. This may be a derived value.
|
||||
string mime_type;
|
||||
|
||||
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
|
||||
index beb3fe75a654510b60b62ab29380c7ff243bb095..fdf3fc5d7edc902ce7cfd23e5cdd1fa97d744120 100644
|
||||
--- a/services/network/url_loader.cc
|
||||
+++ b/services/network/url_loader.cc
|
||||
@@ -1537,6 +1537,8 @@ mojom::URLResponseHeadPtr URLLoader::BuildResponseHead() const {
|
||||
|
||||
response->load_with_storage_access = ShouldSetLoadWithStorageAccess();
|
||||
|
||||
+ response->url_list = url_request_->url_chain();
|
||||
+
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -47,3 +47,4 @@ build_allow_unbundling_of_node_js_dependencies.patch
|
||||
test_use_static_method_names_in_call_stacks.patch
|
||||
build_use_third_party_simdutf.patch
|
||||
fix_remove_fastapitypedarray_usage.patch
|
||||
feat_undici_support_urllist_initialization_in_response_ctor.patch
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Tue, 19 Nov 2024 17:54:33 +0900
|
||||
Subject: feat(undici): support urlList initialization in Response ctor
|
||||
|
||||
Extends the Response constructor to initialize with urlList array,
|
||||
which will be used to support the url getter.
|
||||
|
||||
Should be upstreamed.
|
||||
|
||||
diff --git a/deps/undici/undici.js b/deps/undici/undici.js
|
||||
index acbece9168787204c1b5d27aa05c6709899d0847..eb4dc9497acb880a2d00fe319d56129d65084719 100644
|
||||
--- a/deps/undici/undici.js
|
||||
+++ b/deps/undici/undici.js
|
||||
@@ -9050,6 +9050,9 @@ var require_response = __commonJS({
|
||||
if ("headers" in init && init.headers != null) {
|
||||
fill(response[kHeaders], init.headers);
|
||||
}
|
||||
+ if ("urlList" in init && init.urlList != null) {
|
||||
+ response[kState].urlList = [...init.urlList];
|
||||
+ }
|
||||
if (body) {
|
||||
if (nullBodyStatus.includes(response.status)) {
|
||||
throw webidl.errors.exception({
|
||||
@@ -9126,6 +9129,11 @@ var require_response = __commonJS({
|
||||
{
|
||||
key: "headers",
|
||||
converter: webidl.converters.HeadersInit
|
||||
+ },
|
||||
+ {
|
||||
+ key: "urlList",
|
||||
+ converter: webidl.converters.any,
|
||||
+ defaultValue: () => []
|
||||
}
|
||||
]);
|
||||
module2.exports = {
|
||||
@@ -125,6 +125,23 @@ struct Converter<net::ReferrerPolicy> {
|
||||
return FromV8WithLowerLookup(isolate, val, Lookup, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<network::mojom::URLResponseHead> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
const network::mojom::URLResponseHead& response_head) {
|
||||
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("statusCode", response_head.headers->response_code());
|
||||
dict.Set("statusMessage", response_head.headers->GetStatusText());
|
||||
dict.Set("httpVersion", response_head.headers->GetHttpVersion());
|
||||
dict.Set("headers", response_head.headers.get());
|
||||
dict.Set("rawHeaders", response_head.raw_response_headers);
|
||||
dict.Set("mimeType", response_head.mime_type);
|
||||
dict.Set("urlList", response_head.url_list);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
} // namespace gin
|
||||
|
||||
namespace electron::api {
|
||||
@@ -739,16 +756,7 @@ void SimpleURLLoaderWrapper::OnComplete(bool success) {
|
||||
void SimpleURLLoaderWrapper::OnResponseStarted(
|
||||
const GURL& final_url,
|
||||
const network::mojom::URLResponseHead& response_head) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
auto dict = gin::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("statusCode", response_head.headers->response_code());
|
||||
dict.Set("statusMessage", response_head.headers->GetStatusText());
|
||||
dict.Set("httpVersion", response_head.headers->GetHttpVersion());
|
||||
dict.Set("headers", response_head.headers.get());
|
||||
dict.Set("rawHeaders", response_head.raw_response_headers);
|
||||
dict.Set("mimeType", response_head.mime_type);
|
||||
Emit("response-started", final_url, dict);
|
||||
Emit("response-started", final_url, response_head);
|
||||
}
|
||||
|
||||
void SimpleURLLoaderWrapper::OnRedirect(
|
||||
@@ -756,7 +764,7 @@ void SimpleURLLoaderWrapper::OnRedirect(
|
||||
const net::RedirectInfo& redirect_info,
|
||||
const network::mojom::URLResponseHead& response_head,
|
||||
std::vector<std::string>* removed_headers) {
|
||||
Emit("redirect", redirect_info, response_head.headers.get());
|
||||
Emit("redirect", redirect_info, response_head);
|
||||
|
||||
if (!loader_)
|
||||
// The redirect was aborted by JS.
|
||||
|
||||
3
typings/internal-ambient.d.ts
vendored
3
typings/internal-ambient.d.ts
vendored
@@ -175,6 +175,7 @@ declare namespace NodeJS {
|
||||
httpVersion: { major: number, minor: number };
|
||||
rawHeaders: { key: string, value: string }[];
|
||||
headers: Record<string, string[]>;
|
||||
urlList: string[];
|
||||
};
|
||||
|
||||
type RedirectInfo = {
|
||||
@@ -194,7 +195,7 @@ declare namespace NodeJS {
|
||||
on(eventName: 'complete', listener: (event: any) => void): this;
|
||||
on(eventName: 'error', listener: (event: any, netErrorString: string) => void): this;
|
||||
on(eventName: 'login', listener: (event: any, authInfo: Electron.AuthInfo, callback: (username?: string, password?: string) => void) => void): this;
|
||||
on(eventName: 'redirect', listener: (event: any, redirectInfo: RedirectInfo, headers: Record<string, string>) => void): this;
|
||||
on(eventName: 'redirect', listener: (event: any, redirectInfo: RedirectInfo, responseHead: ResponseHead) => void): this;
|
||||
on(eventName: 'upload-progress', listener: (event: any, position: number, total: number) => void): this;
|
||||
on(eventName: 'download-progress', listener: (event: any, current: number) => void): this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user