@gjsify/fetch 0.3.13 → 0.3.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,153 +1,205 @@
1
1
  import { URL } from "@gjsify/url";
2
2
  import { isIP } from "node:net";
3
+
4
+ //#region src/utils/referrer.ts
5
+ /**
6
+ * @external URL
7
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/URL URL}
8
+ */
9
+ /**
10
+ * @module utils/referrer
11
+ * @private
12
+ */
13
+ /**
14
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#strip-url Referrer Policy §8.4. Strip url for use as a referrer}
15
+ * @param url
16
+ * @param originOnly
17
+ */
3
18
  function stripURLForUseAsAReferrer(url, originOnly = false) {
4
- if (url == null || url === "no-referrer") {
5
- return "no-referrer";
6
- }
7
- const u = new URL(url);
8
- if (/^(about|blob|data):$/.test(u.protocol)) {
9
- return "no-referrer";
10
- }
11
- u.username = "";
12
- u.password = "";
13
- u.hash = "";
14
- if (originOnly) {
15
- u.pathname = "";
16
- u.search = "";
17
- }
18
- return u;
19
+ if (url == null || url === "no-referrer") {
20
+ return "no-referrer";
21
+ }
22
+ const u = new URL(url);
23
+ if (/^(about|blob|data):$/.test(u.protocol)) {
24
+ return "no-referrer";
25
+ }
26
+ u.username = "";
27
+ u.password = "";
28
+ u.hash = "";
29
+ if (originOnly) {
30
+ u.pathname = "";
31
+ u.search = "";
32
+ }
33
+ return u;
19
34
  }
20
- const ReferrerPolicy = /* @__PURE__ */ new Set([
21
- "",
22
- "no-referrer",
23
- "no-referrer-when-downgrade",
24
- "same-origin",
25
- "origin",
26
- "strict-origin",
27
- "origin-when-cross-origin",
28
- "strict-origin-when-cross-origin",
29
- "unsafe-url"
35
+ /**
36
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#enumdef-referrerpolicy enum ReferrerPolicy}
37
+ */
38
+ const ReferrerPolicy = new Set([
39
+ "",
40
+ "no-referrer",
41
+ "no-referrer-when-downgrade",
42
+ "same-origin",
43
+ "origin",
44
+ "strict-origin",
45
+ "origin-when-cross-origin",
46
+ "strict-origin-when-cross-origin",
47
+ "unsafe-url"
30
48
  ]);
49
+ /**
50
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#default-referrer-policy default referrer policy}
51
+ */
31
52
  const DEFAULT_REFERRER_POLICY = "strict-origin-when-cross-origin";
53
+ /**
54
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#referrer-policies Referrer Policy §3. Referrer Policies}
55
+ * @param referrerPolicy
56
+ * @returns referrerPolicy
57
+ */
32
58
  function validateReferrerPolicy(referrerPolicy) {
33
- if (!ReferrerPolicy.has(referrerPolicy)) {
34
- throw new TypeError(`Invalid referrerPolicy: ${referrerPolicy}`);
35
- }
36
- return referrerPolicy;
59
+ if (!ReferrerPolicy.has(referrerPolicy)) {
60
+ throw new TypeError(`Invalid referrerPolicy: ${referrerPolicy}`);
61
+ }
62
+ return referrerPolicy;
37
63
  }
64
+ /**
65
+ * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy Referrer Policy §3.2. Is origin potentially trustworthy?}
66
+ * @param url
67
+ * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy"
68
+ */
38
69
  function isOriginPotentiallyTrustworthy(url) {
39
- if (/^(http|ws)s:$/.test(url.protocol)) {
40
- return true;
41
- }
42
- const hostIp = url.host.replace(/(^\[)|(]$)/g, "");
43
- const hostIPVersion = isIP(hostIp);
44
- if (hostIPVersion === 4 && /^127\./.test(hostIp)) {
45
- return true;
46
- }
47
- if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) {
48
- return true;
49
- }
50
- if (url.host === "localhost" || url.host.endsWith(".localhost")) {
51
- return false;
52
- }
53
- if (url.protocol === "file:") {
54
- return true;
55
- }
56
- return false;
70
+ if (/^(http|ws)s:$/.test(url.protocol)) {
71
+ return true;
72
+ }
73
+ const hostIp = url.host.replace(/(^\[)|(]$)/g, "");
74
+ const hostIPVersion = isIP(hostIp);
75
+ if (hostIPVersion === 4 && /^127\./.test(hostIp)) {
76
+ return true;
77
+ }
78
+ if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) {
79
+ return true;
80
+ }
81
+ if (url.host === "localhost" || url.host.endsWith(".localhost")) {
82
+ return false;
83
+ }
84
+ if (url.protocol === "file:") {
85
+ return true;
86
+ }
87
+ return false;
57
88
  }
89
+ /**
90
+ * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-url-trustworthy Referrer Policy §3.3. Is url potentially trustworthy?}
91
+ * @param url
92
+ * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy"
93
+ */
58
94
  function isUrlPotentiallyTrustworthy(url) {
59
- if (/^about:(blank|srcdoc)$/.test(url.toString())) {
60
- return true;
61
- }
62
- if (typeof url === "string") {
63
- url = new URL(url);
64
- }
65
- if (url.protocol === "data:") {
66
- return true;
67
- }
68
- if (/^(blob|filesystem):$/.test(url.protocol)) {
69
- return true;
70
- }
71
- return isOriginPotentiallyTrustworthy(url);
95
+ if (/^about:(blank|srcdoc)$/.test(url.toString())) {
96
+ return true;
97
+ }
98
+ if (typeof url === "string") {
99
+ url = new URL(url);
100
+ }
101
+ if (url.protocol === "data:") {
102
+ return true;
103
+ }
104
+ if (/^(blob|filesystem):$/.test(url.protocol)) {
105
+ return true;
106
+ }
107
+ return isOriginPotentiallyTrustworthy(url);
72
108
  }
109
+ /**
110
+ * Modifies the referrerURL to enforce any extra security policy considerations.
111
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer Referrer Policy §8.3. Determine request's Referrer}, step 7
112
+ * @callback module:utils/referrer~referrerURLCallback
113
+ * @param {external:URL} referrerURL
114
+ * @returns {external:URL} modified referrerURL
115
+ */
116
+ /**
117
+ * Modifies the referrerOrigin to enforce any extra security policy considerations.
118
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer Referrer Policy §8.3. Determine request's Referrer}, step 7
119
+ * @callback module:utils/referrer~referrerOriginCallback
120
+ * @param {external:URL} referrerOrigin
121
+ * @returns {external:URL} modified referrerOrigin
122
+ */
123
+ /**
124
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer Referrer Policy §8.3. Determine request's Referrer}
125
+ * @param request
126
+ * @param {object} o
127
+ * @param {module:utils/referrer~referrerURLCallback} o.referrerURLCallback
128
+ * @param {module:utils/referrer~referrerOriginCallback} o.referrerOriginCallback
129
+ * @returns {external:URL} Request's referrer
130
+ */
73
131
  function determineRequestsReferrer(request, obj = {}) {
74
- const { referrerURLCallback, referrerOriginCallback } = obj;
75
- if (request.referrer === "no-referrer" || request.referrerPolicy === "") {
76
- return null;
77
- }
78
- const policy = request.referrerPolicy;
79
- if (request.referrer === "about:client") {
80
- return "no-referrer";
81
- }
82
- const referrerSource = new URL(request.referrer);
83
- let referrerURL = stripURLForUseAsAReferrer(referrerSource);
84
- let referrerOrigin = stripURLForUseAsAReferrer(referrerSource, true);
85
- if (referrerURL.toString().length > 4096) {
86
- referrerURL = referrerOrigin;
87
- }
88
- if (referrerURLCallback) {
89
- referrerURL = referrerURLCallback(referrerURL);
90
- }
91
- if (referrerOriginCallback) {
92
- referrerOrigin = referrerOriginCallback(referrerOrigin);
93
- }
94
- const currentURL = new URL(request.url);
95
- switch (policy) {
96
- case "no-referrer":
97
- return "no-referrer";
98
- case "origin":
99
- return referrerOrigin;
100
- case "unsafe-url":
101
- return referrerURL;
102
- case "strict-origin":
103
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
104
- return "no-referrer";
105
- }
106
- return referrerOrigin.toString();
107
- case "strict-origin-when-cross-origin":
108
- if (referrerURL.origin === currentURL.origin) {
109
- return referrerURL;
110
- }
111
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
112
- return "no-referrer";
113
- }
114
- return referrerOrigin;
115
- case "same-origin":
116
- if (referrerURL.origin === currentURL.origin) {
117
- return referrerURL;
118
- }
119
- return "no-referrer";
120
- case "origin-when-cross-origin":
121
- if (referrerURL.origin === currentURL.origin) {
122
- return referrerURL;
123
- }
124
- return referrerOrigin;
125
- case "no-referrer-when-downgrade":
126
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
127
- return "no-referrer";
128
- }
129
- return referrerURL;
130
- default:
131
- throw new TypeError(`Invalid referrerPolicy: ${policy}`);
132
- }
132
+ const { referrerURLCallback, referrerOriginCallback } = obj;
133
+ if (request.referrer === "no-referrer" || request.referrerPolicy === "") {
134
+ return null;
135
+ }
136
+ const policy = request.referrerPolicy;
137
+ if (request.referrer === "about:client") {
138
+ return "no-referrer";
139
+ }
140
+ const referrerSource = new URL(request.referrer);
141
+ let referrerURL = stripURLForUseAsAReferrer(referrerSource);
142
+ let referrerOrigin = stripURLForUseAsAReferrer(referrerSource, true);
143
+ if (referrerURL.toString().length > 4096) {
144
+ referrerURL = referrerOrigin;
145
+ }
146
+ if (referrerURLCallback) {
147
+ referrerURL = referrerURLCallback(referrerURL);
148
+ }
149
+ if (referrerOriginCallback) {
150
+ referrerOrigin = referrerOriginCallback(referrerOrigin);
151
+ }
152
+ const currentURL = new URL(request.url);
153
+ switch (policy) {
154
+ case "no-referrer": return "no-referrer";
155
+ case "origin": return referrerOrigin;
156
+ case "unsafe-url": return referrerURL;
157
+ case "strict-origin":
158
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
159
+ return "no-referrer";
160
+ }
161
+ return referrerOrigin.toString();
162
+ case "strict-origin-when-cross-origin":
163
+ if (referrerURL.origin === currentURL.origin) {
164
+ return referrerURL;
165
+ }
166
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
167
+ return "no-referrer";
168
+ }
169
+ return referrerOrigin;
170
+ case "same-origin":
171
+ if (referrerURL.origin === currentURL.origin) {
172
+ return referrerURL;
173
+ }
174
+ return "no-referrer";
175
+ case "origin-when-cross-origin":
176
+ if (referrerURL.origin === currentURL.origin) {
177
+ return referrerURL;
178
+ }
179
+ return referrerOrigin;
180
+ case "no-referrer-when-downgrade":
181
+ if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
182
+ return "no-referrer";
183
+ }
184
+ return referrerURL;
185
+ default: throw new TypeError(`Invalid referrerPolicy: ${policy}`);
186
+ }
133
187
  }
188
+ /**
189
+ * @see {@link https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header|Referrer Policy §8.1. Parse a referrer policy from a Referrer-Policy header}
190
+ * @param {Headers} headers Response headers
191
+ * @returns {string} policy
192
+ */
134
193
  function parseReferrerPolicyFromHeader(headers) {
135
- const policyTokens = (headers.get("referrer-policy") || "").split(/[,\s]+/);
136
- let policy = "";
137
- for (const token of policyTokens) {
138
- if (token && ReferrerPolicy.has(token)) {
139
- policy = token;
140
- }
141
- }
142
- return policy;
194
+ const policyTokens = (headers.get("referrer-policy") || "").split(/[,\s]+/);
195
+ let policy = "";
196
+ for (const token of policyTokens) {
197
+ if (token && ReferrerPolicy.has(token)) {
198
+ policy = token;
199
+ }
200
+ }
201
+ return policy;
143
202
  }
144
- export {
145
- DEFAULT_REFERRER_POLICY,
146
- ReferrerPolicy,
147
- determineRequestsReferrer,
148
- isOriginPotentiallyTrustworthy,
149
- isUrlPotentiallyTrustworthy,
150
- parseReferrerPolicyFromHeader,
151
- stripURLForUseAsAReferrer,
152
- validateReferrerPolicy
153
- };
203
+
204
+ //#endregion
205
+ export { DEFAULT_REFERRER_POLICY, ReferrerPolicy, determineRequestsReferrer, isOriginPotentiallyTrustworthy, isUrlPotentiallyTrustworthy, parseReferrerPolicyFromHeader, stripURLForUseAsAReferrer, validateReferrerPolicy };
@@ -1,22 +1,29 @@
1
- import GLib from "@girs/glib-2.0";
2
1
  import { Readable } from "node:stream";
2
+ import GLib from "@girs/glib-2.0";
3
3
  import { inputStreamAsyncIterator } from "@gjsify/utils";
4
+
5
+ //#region src/utils/soup-helpers.ts
6
+ /**
7
+ * Promise wrapper around `Soup.Session.send_async` / `send_finish`.
8
+ */
4
9
  async function soupSendAsync(session, msg, ioPriority = GLib.PRIORITY_DEFAULT, cancellable = null) {
5
- return new Promise((resolve, reject) => {
6
- session.send_async(msg, ioPriority, cancellable, (_self, asyncRes) => {
7
- try {
8
- const inputStream = session.send_finish(asyncRes);
9
- resolve(inputStream);
10
- } catch (error) {
11
- reject(error);
12
- }
13
- });
14
- });
10
+ return new Promise((resolve, reject) => {
11
+ session.send_async(msg, ioPriority, cancellable, (_self, asyncRes) => {
12
+ try {
13
+ const inputStream = session.send_finish(asyncRes);
14
+ resolve(inputStream);
15
+ } catch (error) {
16
+ reject(error);
17
+ }
18
+ });
19
+ });
15
20
  }
21
+ /**
22
+ * Converts a `Gio.InputStream` to a Node.js `Readable` stream.
23
+ */
16
24
  function inputStreamToReadable(inputStream, options = {}) {
17
- return Readable.from(inputStreamAsyncIterator(inputStream), options);
25
+ return Readable.from(inputStreamAsyncIterator(inputStream), options);
18
26
  }
19
- export {
20
- inputStreamToReadable,
21
- soupSendAsync
22
- };
27
+
28
+ //#endregion
29
+ export { inputStreamToReadable, soupSendAsync };