@php-wasm/web-service-worker 3.0.46 → 3.0.51
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.
- package/fetch-with-cors-proxy.d.ts +1 -0
- package/firewall-interference-error.d.ts +13 -0
- package/index.cjs +1 -1
- package/index.d.ts +2 -0
- package/index.js +119 -76
- package/package.json +6 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function fetchWithCorsProxy(input: RequestInfo, init?: RequestInit, corsProxyUrl?: string, playgroundUrl?: string): Promise<Response>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when a CORS proxy response appears to have been
|
|
3
|
+
* intercepted by a network firewall or corporate proxy.
|
|
4
|
+
*
|
|
5
|
+
* This is detected when a response from the CORS proxy is missing
|
|
6
|
+
* the X-Playground-Cors-Proxy header that legitimate responses include.
|
|
7
|
+
*/
|
|
8
|
+
export declare class FirewallInterferenceError extends Error {
|
|
9
|
+
readonly url: string;
|
|
10
|
+
readonly status: number;
|
|
11
|
+
readonly statusText: string;
|
|
12
|
+
constructor(url: string, status: number, statusText: string);
|
|
13
|
+
}
|
package/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("@php-wasm/scopes"),L=25e3;let P=0;function T(e,t,...o){const s=w();return e.postMessage({...t,requestId:s},...o),s}function w(){return++P}function m(e,t,o=L){return new Promise((s,n)=>{const r=i=>{i.data.type==="response"&&i.data.requestId===t&&(e.removeEventListener("message",r),clearTimeout(a),s(i.data.response))},a=setTimeout(()=>{n(new Error("Request timed out")),e.removeEventListener("message",r)},o);e.addEventListener("message",r)})}function U(e,t){return{type:"response",requestId:e,response:t}}async function x(e){let t=new URL(e.request.url);if(!y.isURLScoped(t))try{const c=new URL(e.request.referrer);t=y.setURLScope(t,y.getURLScope(c))}catch{}const o=e.request.headers.get("content-type"),s=e.request.method==="POST"?new Uint8Array(await e.request.clone().arrayBuffer()):void 0,n={};for(const c of e.request.headers.entries())n[c[0]]=c[1];let r;try{const c={method:"request",args:[{body:s,url:t.toString(),method:e.request.method,headers:{...n,Host:t.host,"User-agent":self.navigator.userAgent,"Content-type":o}}]},d=y.getURLScope(t);if(d===null)throw new Error(`The URL ${t.toString()} is not scoped. This should not happen.`);const p=await R(c,d);if(r=await m(self,p),delete r.headers["x-frame-options"],r.headers["content-security-policy"]){const l=r.headers["content-security-policy"].map(u=>E("frame-ancestors",u)).filter(u=>u.trim().length>0);l.length>0?r.headers["content-security-policy"]=l:delete r.headers["content-security-policy"]}}catch(c){throw console.error(c,{url:t.toString()}),c}if(r.httpStatusCode>=300&&r.httpStatusCode<=399&&r.headers.location)return Response.redirect(new URL(r.headers.location[0],t.toString()),r.httpStatusCode);const i=[101,103,204,205,304].includes(r.httpStatusCode)?null:r.bytes;return new Response(i,{headers:r.headers,status:r.httpStatusCode})}async function R(e,t){const o=w();for(const s of await self.clients.matchAll({includeUncontrolled:!0}))s.postMessage({...e,scope:t,requestId:o});return o}async function h(e,t){let o;return["GET","HEAD"].includes(e.method)||"body"in t?o=void 0:!e.bodyUsed&&e.body?o=e.body:o=await e.arrayBuffer(),new Request(t.url||e.url,{body:o,method:e.method,headers:e.headers,referrer:e.referrer,referrerPolicy:e.referrerPolicy,mode:e.mode==="navigate"?"same-origin":e.mode,credentials:e.credentials,cache:e.cache,redirect:e.redirect,integrity:e.integrity,...o&&{duplex:"half"},...t})}async function g(e){if(!e.body)return[e,e];const[t,o]=e.body.tee();return[await h(e,{body:t,duplex:"half"}),await h(e,{body:o,duplex:"half"})]}function q(e){const t={};return e.headers.forEach((o,s)=>{t[s]=o}),t}function E(e,t){const o=/^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u,s=/[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u,n=/[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;return t.split(";").filter(r=>{const a=r.replace(o,"").replace(s,""),[i]=a.split(n,1);return i.toLowerCase()!==e.toLowerCase()}).join(";")}class b extends Error{constructor(t,o,s){super(`Could not fetch ${t} – your network appears to be blocking this request (HTTP ${o}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`),this.name="FirewallInterferenceError",this.url=t,this.status=o,this.statusText=s}}const H="X-Playground-Cors-Proxy";async function A(e,t,o,s){var p;let n=typeof e=="string"?new Request(e,t):e;const r=s?new URL(s):null;let a=r?new URL(n.url,r):new URL(n.url);if(a.hostname==="localhost"||a.hostname==="127.0.0.1"||a.hostname==="[::1]"||a.hostname==="::1")return await fetch(n);if(a.protocol==="http:"){a.protocol="https:";const l=a.toString();n=await h(n,{url:l}),a=new URL(l)}if(!o)return await fetch(n);if(r&&a.protocol===r.protocol&&a.hostname===r.hostname&&a.port===r.port&&a.pathname.startsWith(r.pathname))return await fetch(n);const[c,d]=await g(n);try{return await fetch(c)}catch{const u=((p=new Headers(d.headers).get("x-cors-proxy-allowed-request-headers"))==null?void 0:p.split(","))||[],C=u.includes("authorization")||u.includes("cookie"),S=await h(d,{url:`${o}${n.url}`,...C&&{credentials:"include"}}),f=await fetch(S,t);if(!f.headers.has(H))throw new b(n.url,f.status,f.statusText);return f}}exports.FirewallInterferenceError=b;exports.awaitReply=m;exports.broadcastMessageExpectReply=R;exports.cloneRequest=h;exports.convertFetchEventToPHPRequest=x;exports.fetchWithCorsProxy=A;exports.getNextRequestId=w;exports.getRequestHeaders=q;exports.postMessageExpectReply=T;exports.removeContentSecurityPolicyDirective=E;exports.responseTo=U;exports.teeRequest=g;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { isURLScoped as
|
|
2
|
-
const
|
|
3
|
-
let
|
|
4
|
-
function
|
|
5
|
-
const s =
|
|
1
|
+
import { isURLScoped as R, setURLScope as C, getURLScope as y } from "@php-wasm/scopes";
|
|
2
|
+
const E = 25e3;
|
|
3
|
+
let b = 0;
|
|
4
|
+
function H(e, t, ...o) {
|
|
5
|
+
const s = w();
|
|
6
6
|
return e.postMessage(
|
|
7
7
|
{
|
|
8
8
|
...t,
|
|
9
9
|
requestId: s
|
|
10
10
|
},
|
|
11
|
-
...
|
|
11
|
+
...o
|
|
12
12
|
), s;
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
return ++
|
|
14
|
+
function w() {
|
|
15
|
+
return ++b;
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
return new Promise((s,
|
|
19
|
-
const
|
|
20
|
-
i.data.type === "response" && i.data.requestId === t && (e.removeEventListener("message",
|
|
17
|
+
function L(e, t, o = E) {
|
|
18
|
+
return new Promise((s, n) => {
|
|
19
|
+
const r = (i) => {
|
|
20
|
+
i.data.type === "response" && i.data.requestId === t && (e.removeEventListener("message", r), clearTimeout(a), s(i.data.response));
|
|
21
21
|
}, a = setTimeout(() => {
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
e.addEventListener("message",
|
|
22
|
+
n(new Error("Request timed out")), e.removeEventListener("message", r);
|
|
23
|
+
}, o);
|
|
24
|
+
e.addEventListener("message", r);
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
function
|
|
27
|
+
function q(e, t) {
|
|
28
28
|
return {
|
|
29
29
|
type: "response",
|
|
30
30
|
requestId: e,
|
|
31
31
|
response: t
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
async function
|
|
34
|
+
async function I(e) {
|
|
35
35
|
let t = new URL(e.request.url);
|
|
36
|
-
if (!
|
|
36
|
+
if (!R(t))
|
|
37
37
|
try {
|
|
38
|
-
const
|
|
39
|
-
t =
|
|
38
|
+
const c = new URL(e.request.referrer);
|
|
39
|
+
t = C(t, y(c));
|
|
40
40
|
} catch {
|
|
41
41
|
}
|
|
42
|
-
const
|
|
43
|
-
for (const
|
|
44
|
-
c[
|
|
45
|
-
let
|
|
42
|
+
const o = e.request.headers.get("content-type"), s = e.request.method === "POST" ? new Uint8Array(await e.request.clone().arrayBuffer()) : void 0, n = {};
|
|
43
|
+
for (const c of e.request.headers.entries())
|
|
44
|
+
n[c[0]] = c[1];
|
|
45
|
+
let r;
|
|
46
46
|
try {
|
|
47
|
-
const
|
|
47
|
+
const c = {
|
|
48
48
|
method: "request",
|
|
49
49
|
args: [
|
|
50
50
|
{
|
|
@@ -52,48 +52,48 @@ async function A(e) {
|
|
|
52
52
|
url: t.toString(),
|
|
53
53
|
method: e.request.method,
|
|
54
54
|
headers: {
|
|
55
|
-
...
|
|
55
|
+
...n,
|
|
56
56
|
Host: t.host,
|
|
57
57
|
// Safari and Firefox don't make the User-Agent header
|
|
58
58
|
// available in the fetch event. Let's add it manually:
|
|
59
59
|
"User-agent": self.navigator.userAgent,
|
|
60
|
-
"Content-type":
|
|
60
|
+
"Content-type": o
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
]
|
|
64
|
-
},
|
|
65
|
-
if (
|
|
64
|
+
}, d = y(t);
|
|
65
|
+
if (d === null)
|
|
66
66
|
throw new Error(
|
|
67
67
|
`The URL ${t.toString()} is not scoped. This should not happen.`
|
|
68
68
|
);
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
const l =
|
|
72
|
-
(
|
|
69
|
+
const h = await U(c, d);
|
|
70
|
+
if (r = await L(self, h), delete r.headers["x-frame-options"], r.headers["content-security-policy"]) {
|
|
71
|
+
const l = r.headers["content-security-policy"].map(
|
|
72
|
+
(u) => T(
|
|
73
73
|
"frame-ancestors",
|
|
74
|
-
|
|
74
|
+
u
|
|
75
75
|
)
|
|
76
|
-
).filter((
|
|
77
|
-
l.length > 0 ?
|
|
76
|
+
).filter((u) => u.trim().length > 0);
|
|
77
|
+
l.length > 0 ? r.headers["content-security-policy"] = l : delete r.headers["content-security-policy"];
|
|
78
78
|
}
|
|
79
|
-
} catch (
|
|
80
|
-
throw console.error(
|
|
79
|
+
} catch (c) {
|
|
80
|
+
throw console.error(c, { url: t.toString() }), c;
|
|
81
81
|
}
|
|
82
|
-
if (
|
|
82
|
+
if (r.httpStatusCode >= 300 && r.httpStatusCode <= 399 && r.headers.location)
|
|
83
83
|
return Response.redirect(
|
|
84
|
-
new URL(
|
|
85
|
-
|
|
84
|
+
new URL(r.headers.location[0], t.toString()),
|
|
85
|
+
r.httpStatusCode
|
|
86
86
|
);
|
|
87
87
|
const i = [101, 103, 204, 205, 304].includes(
|
|
88
|
-
|
|
89
|
-
) ? null :
|
|
88
|
+
r.httpStatusCode
|
|
89
|
+
) ? null : r.bytes;
|
|
90
90
|
return new Response(i, {
|
|
91
|
-
headers:
|
|
92
|
-
status:
|
|
91
|
+
headers: r.headers,
|
|
92
|
+
status: r.httpStatusCode
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
async function
|
|
96
|
-
const
|
|
95
|
+
async function U(e, t) {
|
|
96
|
+
const o = w();
|
|
97
97
|
for (const s of await self.clients.matchAll({
|
|
98
98
|
// Sometimes the client that triggered the current fetch()
|
|
99
99
|
// event is considered uncontrolled in Google Chrome. This
|
|
@@ -111,14 +111,14 @@ async function S(e, t) {
|
|
|
111
111
|
* helps WASM workers ignore requests meant for other WASM workers.
|
|
112
112
|
*/
|
|
113
113
|
scope: t,
|
|
114
|
-
requestId:
|
|
114
|
+
requestId: o
|
|
115
115
|
});
|
|
116
|
-
return
|
|
116
|
+
return o;
|
|
117
117
|
}
|
|
118
|
-
async function
|
|
119
|
-
let
|
|
120
|
-
return ["GET", "HEAD"].includes(e.method) || "body" in t ?
|
|
121
|
-
body:
|
|
118
|
+
async function f(e, t) {
|
|
119
|
+
let o;
|
|
120
|
+
return ["GET", "HEAD"].includes(e.method) || "body" in t ? o = void 0 : !e.bodyUsed && e.body ? o = e.body : o = await e.arrayBuffer(), new Request(t.url || e.url, {
|
|
121
|
+
body: o,
|
|
122
122
|
method: e.method,
|
|
123
123
|
headers: e.headers,
|
|
124
124
|
referrer: e.referrer,
|
|
@@ -128,45 +128,88 @@ async function h(e, t) {
|
|
|
128
128
|
cache: e.cache,
|
|
129
129
|
redirect: e.redirect,
|
|
130
130
|
integrity: e.integrity,
|
|
131
|
-
...
|
|
131
|
+
...o && { duplex: "half" },
|
|
132
132
|
...t
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
async function
|
|
135
|
+
async function S(e) {
|
|
136
136
|
if (!e.body)
|
|
137
137
|
return [e, e];
|
|
138
|
-
const [t,
|
|
138
|
+
const [t, o] = e.body.tee();
|
|
139
139
|
return [
|
|
140
|
-
await
|
|
141
|
-
await
|
|
140
|
+
await f(e, { body: t, duplex: "half" }),
|
|
141
|
+
await f(e, { body: o, duplex: "half" })
|
|
142
142
|
];
|
|
143
143
|
}
|
|
144
|
-
function
|
|
144
|
+
function O(e) {
|
|
145
145
|
const t = {};
|
|
146
|
-
return e.headers.forEach((
|
|
147
|
-
t[s] =
|
|
146
|
+
return e.headers.forEach((o, s) => {
|
|
147
|
+
t[s] = o;
|
|
148
148
|
}), t;
|
|
149
149
|
}
|
|
150
|
-
function
|
|
151
|
-
const
|
|
152
|
-
return t.split(";").filter((
|
|
153
|
-
const a =
|
|
154
|
-
|
|
150
|
+
function T(e, t) {
|
|
151
|
+
const o = /^[\u{9}\u{A}\u{C}\u{D}\u{20}]+/u, s = /[\u{9}\u{A}\u{C}\u{D}\u{20}]+$/u, n = /[\u{9}\u{A}\u{C}\u{D}\u{20}]/u;
|
|
152
|
+
return t.split(";").filter((r) => {
|
|
153
|
+
const a = r.replace(o, "").replace(s, ""), [i] = a.split(
|
|
154
|
+
n,
|
|
155
155
|
// The directive name is the first token.
|
|
156
156
|
1
|
|
157
157
|
);
|
|
158
158
|
return i.toLowerCase() !== e.toLowerCase();
|
|
159
159
|
}).join(";");
|
|
160
160
|
}
|
|
161
|
+
class x extends Error {
|
|
162
|
+
constructor(t, o, s) {
|
|
163
|
+
super(
|
|
164
|
+
`Could not fetch ${t} – your network appears to be blocking this request (HTTP ${o}). This often happens on school, university, or corporate networks. Try switching to a different network or using a VPN.`
|
|
165
|
+
), this.name = "FirewallInterferenceError", this.url = t, this.status = o, this.statusText = s;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const P = "X-Playground-Cors-Proxy";
|
|
169
|
+
async function D(e, t, o, s) {
|
|
170
|
+
var h;
|
|
171
|
+
let n = typeof e == "string" ? new Request(e, t) : e;
|
|
172
|
+
const r = s ? new URL(s) : null;
|
|
173
|
+
let a = r ? new URL(n.url, r) : new URL(n.url);
|
|
174
|
+
if (a.hostname === "localhost" || a.hostname === "127.0.0.1" || a.hostname === "[::1]" || a.hostname === "::1")
|
|
175
|
+
return await fetch(n);
|
|
176
|
+
if (a.protocol === "http:") {
|
|
177
|
+
a.protocol = "https:";
|
|
178
|
+
const l = a.toString();
|
|
179
|
+
n = await f(n, { url: l }), a = new URL(l);
|
|
180
|
+
}
|
|
181
|
+
if (!o)
|
|
182
|
+
return await fetch(n);
|
|
183
|
+
if (r && a.protocol === r.protocol && a.hostname === r.hostname && a.port === r.port && a.pathname.startsWith(r.pathname))
|
|
184
|
+
return await fetch(n);
|
|
185
|
+
const [c, d] = await S(n);
|
|
186
|
+
try {
|
|
187
|
+
return await fetch(c);
|
|
188
|
+
} catch {
|
|
189
|
+
const u = ((h = new Headers(d.headers).get("x-cors-proxy-allowed-request-headers")) == null ? void 0 : h.split(",")) || [], m = u.includes("authorization") || u.includes("cookie"), g = await f(d, {
|
|
190
|
+
url: `${o}${n.url}`,
|
|
191
|
+
...m && { credentials: "include" }
|
|
192
|
+
}), p = await fetch(g, t);
|
|
193
|
+
if (!p.headers.has(P))
|
|
194
|
+
throw new x(
|
|
195
|
+
n.url,
|
|
196
|
+
p.status,
|
|
197
|
+
p.statusText
|
|
198
|
+
);
|
|
199
|
+
return p;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
161
202
|
export {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
T as
|
|
203
|
+
x as FirewallInterferenceError,
|
|
204
|
+
L as awaitReply,
|
|
205
|
+
U as broadcastMessageExpectReply,
|
|
206
|
+
f as cloneRequest,
|
|
207
|
+
I as convertFetchEventToPHPRequest,
|
|
208
|
+
D as fetchWithCorsProxy,
|
|
209
|
+
w as getNextRequestId,
|
|
210
|
+
O as getRequestHeaders,
|
|
211
|
+
H as postMessageExpectReply,
|
|
212
|
+
T as removeContentSecurityPolicyDirective,
|
|
213
|
+
q as responseTo,
|
|
214
|
+
S as teeRequest
|
|
172
215
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/web-service-worker",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.51",
|
|
4
4
|
"description": "PHP.wasm – service worker utils",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"main": "./index.cjs",
|
|
32
32
|
"module": "./index.js",
|
|
33
33
|
"license": "GPL-2.0-or-later",
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "ebc05da827807f3311ed1de8711fa74266183fab",
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=20.18.3",
|
|
37
37
|
"npm": ">=10.1.0"
|
|
@@ -45,10 +45,12 @@
|
|
|
45
45
|
"@playwright/test": "1.55.1",
|
|
46
46
|
"ws": "8.18.3",
|
|
47
47
|
"tmp": "0.2.5",
|
|
48
|
-
"form-data": "^4.0.4"
|
|
48
|
+
"form-data": "^4.0.4",
|
|
49
|
+
"lodash": "^4.17.23",
|
|
50
|
+
"glob": "^9.3.0"
|
|
49
51
|
},
|
|
50
52
|
"dependencies": {
|
|
51
|
-
"@php-wasm/scopes": "3.0.
|
|
53
|
+
"@php-wasm/scopes": "3.0.51"
|
|
52
54
|
},
|
|
53
55
|
"optionalDependencies": {
|
|
54
56
|
"fs-ext": "2.1.1"
|