wrangler 0.0.0-a72f64c8 → 0.0.0-a72fccb9
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/package.json +27 -10
- package/templates/gitignore +0 -5
- package/templates/init-tests/test-vitest-new-worker.js +1 -1
- package/templates/init-tests/test-vitest-new-worker.ts +1 -1
- package/templates/middleware/loader-modules.ts +3 -4
- package/templates/middleware/loader-sw.ts +4 -3
- package/templates/middleware/middleware-ensure-req-body-drained.ts +19 -0
- package/templates/middleware/middleware-serve-static-assets.ts +5 -5
- package/templates/pages-dev-pipeline.ts +2 -1
- package/templates/startDevWorker/InspectorProxyWorker.ts +57 -4
- package/templates/startDevWorker/ProxyWorker.ts +113 -39
- package/wrangler-dist/InspectorProxyWorker.js +45 -0
- package/wrangler-dist/InspectorProxyWorker.js.map +1 -1
- package/wrangler-dist/ProxyWorker.js +75 -24
- package/wrangler-dist/ProxyWorker.js.map +1 -1
- package/wrangler-dist/cli.d.ts +465 -60
- package/wrangler-dist/cli.js +47490 -29856
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wrangler",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-a72fccb9",
|
|
4
4
|
"description": "Command-line interface for all things Cloudflare Workers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wrangler",
|
|
@@ -83,7 +83,6 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@cloudflare/kv-asset-handler": "^0.2.0",
|
|
87
86
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
|
88
87
|
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
|
89
88
|
"blake3-wasm": "^2.1.5",
|
|
@@ -91,20 +90,25 @@
|
|
|
91
90
|
"esbuild": "0.17.19",
|
|
92
91
|
"nanoid": "^3.3.3",
|
|
93
92
|
"path-to-regexp": "^6.2.0",
|
|
93
|
+
"resolve": "^1.22.8",
|
|
94
94
|
"resolve.exports": "^2.0.2",
|
|
95
95
|
"selfsigned": "^2.0.1",
|
|
96
96
|
"source-map": "0.6.1",
|
|
97
|
-
"source-map-support": "0.5.21",
|
|
98
97
|
"xxhash-wasm": "^1.0.1",
|
|
99
|
-
"
|
|
98
|
+
"@cloudflare/kv-asset-handler": "0.3.1",
|
|
99
|
+
"miniflare": "3.20240304.1"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
|
+
"@cloudflare/ai": "^1.0.35",
|
|
102
103
|
"@cloudflare/eslint-config-worker": "*",
|
|
103
104
|
"@cloudflare/types": "^6.18.4",
|
|
104
|
-
"https-proxy-agent": "7.0.2",
|
|
105
105
|
"@cloudflare/workers-types": "^4.20230914.0",
|
|
106
|
+
"@cspotcode/source-map-support": "0.8.1",
|
|
106
107
|
"@iarna/toml": "^3.0.0",
|
|
107
108
|
"@microsoft/api-extractor": "^7.28.3",
|
|
109
|
+
"@sentry/node": "^7.86.0",
|
|
110
|
+
"@sentry/types": "^7.86.0",
|
|
111
|
+
"@sentry/utils": "^7.86.0",
|
|
108
112
|
"@types/body-parser": "^1.19.2",
|
|
109
113
|
"@types/busboy": "^1.5.0",
|
|
110
114
|
"@types/command-exists": "^1.2.0",
|
|
@@ -117,6 +121,7 @@
|
|
|
117
121
|
"@types/minimatch": "^5.1.2",
|
|
118
122
|
"@types/prompts": "^2.0.14",
|
|
119
123
|
"@types/react": "^17.0.37",
|
|
124
|
+
"@types/resolve": "^1.20.6",
|
|
120
125
|
"@types/serve-static": "^1.13.10",
|
|
121
126
|
"@types/shell-quote": "^1.7.2",
|
|
122
127
|
"@types/signal-exit": "^3.0.1",
|
|
@@ -142,6 +147,7 @@
|
|
|
142
147
|
"get-port": "^6.1.2",
|
|
143
148
|
"glob-to-regexp": "0.4.1",
|
|
144
149
|
"http-terminator": "^3.2.0",
|
|
150
|
+
"https-proxy-agent": "7.0.2",
|
|
145
151
|
"ignore": "^5.2.0",
|
|
146
152
|
"ink": "^3.2.0",
|
|
147
153
|
"ink-select-input": "^4.2.1",
|
|
@@ -174,22 +180,33 @@
|
|
|
174
180
|
"supports-color": "^9.2.2",
|
|
175
181
|
"timeago.js": "^4.0.2",
|
|
176
182
|
"ts-dedent": "^2.2.0",
|
|
177
|
-
"undici": "5.
|
|
183
|
+
"undici": "5.28.3",
|
|
178
184
|
"update-check": "^1.5.4",
|
|
179
185
|
"ws": "^8.5.0",
|
|
180
186
|
"xdg-app-paths": "^8.3.0",
|
|
181
187
|
"yargs": "^17.7.2",
|
|
182
188
|
"yoga-layout": "file:../../vendor/yoga-layout-2.0.0-beta.1.tgz",
|
|
183
|
-
"@cloudflare/
|
|
184
|
-
"@cloudflare/
|
|
185
|
-
"@cloudflare/
|
|
189
|
+
"@cloudflare/cli": "1.1.1",
|
|
190
|
+
"@cloudflare/pages-shared": "^0.11.18",
|
|
191
|
+
"@cloudflare/workers-tsconfig": "0.0.0"
|
|
186
192
|
},
|
|
187
193
|
"optionalDependencies": {
|
|
188
194
|
"fsevents": "~2.3.2"
|
|
189
195
|
},
|
|
196
|
+
"peerDependencies": {
|
|
197
|
+
"@cloudflare/workers-types": "^4.20230914.0"
|
|
198
|
+
},
|
|
199
|
+
"peerDependenciesMeta": {
|
|
200
|
+
"@cloudflare/workers-types": {
|
|
201
|
+
"optional": true
|
|
202
|
+
}
|
|
203
|
+
},
|
|
190
204
|
"engines": {
|
|
191
205
|
"node": ">=16.17.0"
|
|
192
206
|
},
|
|
207
|
+
"workers-sdk": {
|
|
208
|
+
"prerelease": true
|
|
209
|
+
},
|
|
193
210
|
"scripts": {
|
|
194
211
|
"assert-git-version": "node -r esbuild-register scripts/assert-git-version.ts",
|
|
195
212
|
"build": "pnpm run clean && pnpm run bundle && pnpm run emit-types",
|
|
@@ -203,7 +220,7 @@
|
|
|
203
220
|
"test": "pnpm run assert-git-version && jest",
|
|
204
221
|
"test:ci": "pnpm run test --coverage",
|
|
205
222
|
"test:debug": "pnpm run test --silent=false --verbose=true",
|
|
206
|
-
"test:e2e": "vitest
|
|
223
|
+
"test:e2e": "vitest -c ./e2e/vitest.config.ts",
|
|
207
224
|
"test:watch": "pnpm run test --testTimeout=50000 --watch",
|
|
208
225
|
"type:tests": "tsc -p ./src/__tests__/tsconfig.json && tsc -p ./e2e/tsconfig.json"
|
|
209
226
|
}
|
package/templates/gitignore
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
1
2
|
import { unstable_dev } from "wrangler";
|
|
2
3
|
import type { UnstableDevWorker } from "wrangler";
|
|
3
|
-
import { describe, expect, it, beforeAll, afterAll } from "vitest";
|
|
4
4
|
|
|
5
5
|
describe("Worker", () => {
|
|
6
6
|
let worker: UnstableDevWorker;
|
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
// // through wrangler, or we can potentially let users directly add them as a sort
|
|
5
5
|
// // of "plugin" system.
|
|
6
6
|
|
|
7
|
+
import worker from "__ENTRY_POINT__";
|
|
7
8
|
import {
|
|
8
|
-
Dispatcher,
|
|
9
|
-
Middleware,
|
|
10
9
|
__facade_invoke__,
|
|
11
10
|
__facade_register__,
|
|
11
|
+
Dispatcher,
|
|
12
|
+
Middleware,
|
|
12
13
|
} from "./common";
|
|
13
14
|
|
|
14
|
-
import worker from "__ENTRY_POINT__";
|
|
15
|
-
|
|
16
15
|
// We need to preserve all of the exports from the worker
|
|
17
16
|
export * from "__ENTRY_POINT__";
|
|
18
17
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
__facade_invoke__,
|
|
3
|
+
__facade_register__,
|
|
4
|
+
__facade_registerInternal__,
|
|
2
5
|
Awaitable,
|
|
3
6
|
Dispatcher,
|
|
4
7
|
IncomingRequest,
|
|
5
8
|
Middleware,
|
|
6
|
-
__facade_invoke__,
|
|
7
|
-
__facade_register__,
|
|
8
|
-
__facade_registerInternal__,
|
|
9
9
|
} from "./common";
|
|
10
|
+
|
|
10
11
|
export { __facade_register__, __facade_registerInternal__ };
|
|
11
12
|
|
|
12
13
|
// Miniflare 2's `EventTarget` follows the spec and doesn't allow exceptions to
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Middleware } from "./common";
|
|
2
|
+
|
|
3
|
+
const drainBody: Middleware = async (request, env, _ctx, middlewareCtx) => {
|
|
4
|
+
try {
|
|
5
|
+
return await middlewareCtx.next(request, env);
|
|
6
|
+
} finally {
|
|
7
|
+
try {
|
|
8
|
+
if (request.body !== null && !request.bodyUsed) {
|
|
9
|
+
const reader = request.body.getReader();
|
|
10
|
+
while (!(await reader.read()).done) {}
|
|
11
|
+
}
|
|
12
|
+
} catch (e) {
|
|
13
|
+
console.error("Failed to drain the unused request body.", e);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default drainBody;
|
|
19
|
+
export const wrap = undefined;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/// <reference path="middleware-serve-static-assets.d.ts"/>
|
|
2
2
|
|
|
3
|
+
import manifest from "__STATIC_CONTENT_MANIFEST";
|
|
3
4
|
import {
|
|
4
5
|
getAssetFromKV,
|
|
5
|
-
NotFoundError,
|
|
6
6
|
MethodNotAllowedError,
|
|
7
|
+
NotFoundError,
|
|
7
8
|
serveSinglePageApp,
|
|
8
9
|
} from "@cloudflare/kv-asset-handler";
|
|
10
|
+
import { cacheControl, spaMode } from "config:middleware/serve-static-assets";
|
|
11
|
+
import type { Middleware } from "./common";
|
|
9
12
|
import type { Options } from "@cloudflare/kv-asset-handler";
|
|
10
|
-
import { spaMode, cacheControl } from "config:middleware/serve-static-assets";
|
|
11
13
|
import type * as kvAssetHandler from "@cloudflare/kv-asset-handler";
|
|
12
|
-
import manifest from "__STATIC_CONTENT_MANIFEST";
|
|
13
|
-
const ASSET_MANIFEST = JSON.parse(manifest);
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const ASSET_MANIFEST = JSON.parse(manifest);
|
|
16
16
|
|
|
17
17
|
const staticAssets: Middleware = async (request, env, _ctx, middlewareCtx) => {
|
|
18
18
|
let options: Partial<Options> = {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// @ts-ignore entry point will get replaced
|
|
2
2
|
import worker from "__ENTRY_POINT__";
|
|
3
|
+
import { isRoutingRuleMatch } from "./pages-dev-util";
|
|
4
|
+
|
|
3
5
|
// @ts-ignore entry point will get replaced
|
|
4
6
|
export * from "__ENTRY_POINT__";
|
|
5
|
-
import { isRoutingRuleMatch } from "./pages-dev-util";
|
|
6
7
|
|
|
7
8
|
// @ts-ignore routes are injected
|
|
8
9
|
const routes = __ROUTES__;
|
|
@@ -5,10 +5,6 @@ import {
|
|
|
5
5
|
DevToolsCommandResponses,
|
|
6
6
|
DevToolsEvent,
|
|
7
7
|
DevToolsEvents,
|
|
8
|
-
type InspectorProxyWorkerIncomingWebSocketMessage,
|
|
9
|
-
type InspectorProxyWorkerOutgoingRequestBody,
|
|
10
|
-
type InspectorProxyWorkerOutgoingWebsocketMessage,
|
|
11
|
-
type ProxyData,
|
|
12
8
|
serialiseError,
|
|
13
9
|
} from "../../src/api/startDevWorker/events";
|
|
14
10
|
import {
|
|
@@ -18,6 +14,22 @@ import {
|
|
|
18
14
|
MaybePromise,
|
|
19
15
|
urlFromParts,
|
|
20
16
|
} from "../../src/api/startDevWorker/utils";
|
|
17
|
+
import type {
|
|
18
|
+
InspectorProxyWorkerIncomingWebSocketMessage,
|
|
19
|
+
InspectorProxyWorkerOutgoingRequestBody,
|
|
20
|
+
InspectorProxyWorkerOutgoingWebsocketMessage,
|
|
21
|
+
ProxyData,
|
|
22
|
+
} from "../../src/api/startDevWorker/events";
|
|
23
|
+
|
|
24
|
+
const ALLOWED_HOST_HOSTNAMES = ["127.0.0.1", "[::1]", "localhost"];
|
|
25
|
+
const ALLOWED_ORIGIN_HOSTNAMES = [
|
|
26
|
+
"devtools.devprod.cloudflare.dev",
|
|
27
|
+
"cloudflare-devtools.pages.dev",
|
|
28
|
+
/^[a-z0-9]+\.cloudflare-devtools\.pages\.dev$/,
|
|
29
|
+
"127.0.0.1",
|
|
30
|
+
"[::1]",
|
|
31
|
+
"localhost",
|
|
32
|
+
];
|
|
21
33
|
|
|
22
34
|
interface Env {
|
|
23
35
|
PROXY_CONTROLLER: Fetcher;
|
|
@@ -281,6 +293,13 @@ export class InspectorProxyWorker implements DurableObject {
|
|
|
281
293
|
|
|
282
294
|
this.sendDebugLog("NEW RUNTIME WEBSOCKET", runtimeWebSocketUrl);
|
|
283
295
|
|
|
296
|
+
// Make sure DevTools re-fetches script contents,
|
|
297
|
+
// and uses the newly created execution context
|
|
298
|
+
this.sendDevToolsMessage({
|
|
299
|
+
method: "Runtime.executionContextsCleared",
|
|
300
|
+
params: undefined,
|
|
301
|
+
});
|
|
302
|
+
|
|
284
303
|
const upgrade = await fetch(runtimeWebSocketUrl, {
|
|
285
304
|
headers: {
|
|
286
305
|
...this.proxyData.headers,
|
|
@@ -451,6 +470,40 @@ export class InspectorProxyWorker implements DurableObject {
|
|
|
451
470
|
}
|
|
452
471
|
|
|
453
472
|
async handleDevToolsWebSocketUpgradeRequest(req: Request) {
|
|
473
|
+
// Validate `Host` header
|
|
474
|
+
let hostHeader = req.headers.get("Host");
|
|
475
|
+
if (hostHeader == null) return new Response(null, { status: 400 });
|
|
476
|
+
try {
|
|
477
|
+
const host = new URL(`http://${hostHeader}`);
|
|
478
|
+
if (!ALLOWED_HOST_HOSTNAMES.includes(host.hostname)) {
|
|
479
|
+
return new Response("Disallowed `Host` header", { status: 401 });
|
|
480
|
+
}
|
|
481
|
+
} catch {
|
|
482
|
+
return new Response("Expected `Host` header", { status: 400 });
|
|
483
|
+
}
|
|
484
|
+
// Validate `Origin` header
|
|
485
|
+
let originHeader = req.headers.get("Origin");
|
|
486
|
+
if (originHeader === null && !req.headers.has("User-Agent")) {
|
|
487
|
+
// VSCode doesn't send an `Origin` header, but also doesn't send a
|
|
488
|
+
// `User-Agent` header, so allow an empty origin in this case.
|
|
489
|
+
originHeader = "http://localhost";
|
|
490
|
+
}
|
|
491
|
+
if (originHeader === null) {
|
|
492
|
+
return new Response("Expected `Origin` header", { status: 400 });
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
const origin = new URL(originHeader);
|
|
496
|
+
const allowed = ALLOWED_ORIGIN_HOSTNAMES.some((rule) => {
|
|
497
|
+
if (typeof rule === "string") return origin.hostname === rule;
|
|
498
|
+
else return rule.test(origin.hostname);
|
|
499
|
+
});
|
|
500
|
+
if (!allowed) {
|
|
501
|
+
return new Response("Disallowed `Origin` header", { status: 401 });
|
|
502
|
+
}
|
|
503
|
+
} catch {
|
|
504
|
+
return new Response("Expected `Origin` header", { status: 400 });
|
|
505
|
+
}
|
|
506
|
+
|
|
454
507
|
// DevTools attempting to connect
|
|
455
508
|
this.sendDebugLog("DEVTOOLS WEBSOCKET TRYING TO CONNECT");
|
|
456
509
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
createDeferred,
|
|
3
|
+
DeferredPromise,
|
|
4
|
+
urlFromParts,
|
|
5
|
+
} from "../../src/api/startDevWorker/utils";
|
|
2
6
|
import type {
|
|
7
|
+
ProxyData,
|
|
3
8
|
ProxyWorkerIncomingRequestBody,
|
|
4
9
|
ProxyWorkerOutgoingRequestBody,
|
|
5
|
-
ProxyData,
|
|
6
10
|
} from "../../src/api/startDevWorker/events";
|
|
7
|
-
import {
|
|
8
|
-
DeferredPromise,
|
|
9
|
-
createDeferred,
|
|
10
|
-
} from "../../src/api/startDevWorker/utils";
|
|
11
11
|
|
|
12
12
|
interface Env {
|
|
13
13
|
PROXY_CONTROLLER: Fetcher;
|
|
@@ -37,6 +37,7 @@ export class ProxyWorker implements DurableObject {
|
|
|
37
37
|
|
|
38
38
|
proxyData?: ProxyData;
|
|
39
39
|
requestQueue = new Map<Request, DeferredPromise<Response>>();
|
|
40
|
+
requestRetryQueue = new Map<Request, DeferredPromise<Response>>();
|
|
40
41
|
|
|
41
42
|
fetch(request: Request) {
|
|
42
43
|
if (isRequestForLiveReloadWebsocket(request)) {
|
|
@@ -94,17 +95,29 @@ export class ProxyWorker implements DurableObject {
|
|
|
94
95
|
return new Response(null, { status: 204 });
|
|
95
96
|
}
|
|
96
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Process requests that are being retried first, then process newer requests.
|
|
100
|
+
* Requests that are being retried are, by definition, older than requests which haven't been processed yet.
|
|
101
|
+
* We don't need to be more accurate than this re ordering, since the requests are being fired off synchronously.
|
|
102
|
+
*/
|
|
103
|
+
*getOrderedQueue() {
|
|
104
|
+
yield* this.requestRetryQueue;
|
|
105
|
+
yield* this.requestQueue;
|
|
106
|
+
}
|
|
107
|
+
|
|
97
108
|
processQueue() {
|
|
98
|
-
const { proxyData } = this; //
|
|
109
|
+
const { proxyData } = this; // store proxyData at the moment this function was called
|
|
99
110
|
if (proxyData === undefined) return;
|
|
100
111
|
|
|
101
|
-
for (const [request, deferredResponse] of this.
|
|
112
|
+
for (const [request, deferredResponse] of this.getOrderedQueue()) {
|
|
113
|
+
this.requestRetryQueue.delete(request);
|
|
102
114
|
this.requestQueue.delete(request);
|
|
103
115
|
|
|
104
|
-
const
|
|
116
|
+
const outerUrl = new URL(request.url);
|
|
105
117
|
const headers = new Headers(request.headers);
|
|
106
118
|
|
|
107
119
|
// override url parts for proxying
|
|
120
|
+
const userWorkerUrl = new URL(request.url);
|
|
108
121
|
Object.assign(userWorkerUrl, proxyData.userWorkerUrl);
|
|
109
122
|
|
|
110
123
|
// set request.url in the UserWorker
|
|
@@ -113,8 +126,12 @@ export class ProxyWorker implements DurableObject {
|
|
|
113
126
|
headers.set("MF-Original-URL", innerUrl.href);
|
|
114
127
|
headers.set("MF-Disable-Pretty-Error", "true"); // disables the UserWorker miniflare instance from rendering the pretty error -- instead the ProxyWorker miniflare instance will intercept the json error response and render the pretty error page
|
|
115
128
|
|
|
129
|
+
rewriteUrlRelatedHeaders(headers, outerUrl, innerUrl);
|
|
130
|
+
|
|
116
131
|
// merge proxyData headers with the request headers
|
|
117
132
|
for (const [key, value] of Object.entries(proxyData.headers ?? {})) {
|
|
133
|
+
if (value === undefined) continue;
|
|
134
|
+
|
|
118
135
|
if (key.toLowerCase() === "cookie") {
|
|
119
136
|
const existing = request.headers.get("cookie") ?? "";
|
|
120
137
|
headers.set("cookie", `${existing};${value}`);
|
|
@@ -123,10 +140,12 @@ export class ProxyWorker implements DurableObject {
|
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
|
|
126
|
-
// explicitly NOT await-ing this promise, we are in a loop and want to process the whole queue quickly
|
|
127
|
-
// if we decide to await, we should include a timeout (~100ms) in case the user worker has long-running/parellel requests
|
|
143
|
+
// explicitly NOT await-ing this promise, we are in a loop and want to process the whole queue quickly + synchronously
|
|
128
144
|
void fetch(userWorkerUrl, new Request(request, { headers }))
|
|
129
145
|
.then((res) => {
|
|
146
|
+
res = new Response(res.body, res);
|
|
147
|
+
rewriteUrlRelatedHeaders(res.headers, innerUrl, outerUrl);
|
|
148
|
+
|
|
130
149
|
if (isHtmlResponse(res)) {
|
|
131
150
|
res = insertLiveReloadScript(request, res, this.env, proxyData);
|
|
132
151
|
}
|
|
@@ -137,17 +156,55 @@ export class ProxyWorker implements DurableObject {
|
|
|
137
156
|
// errors here are network errors or from response post-processing
|
|
138
157
|
// to catch only network errors, use the 2nd param of the fetch.then()
|
|
139
158
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
// we have crossed an async boundary, so proxyData may have changed
|
|
160
|
+
// if proxyData.userWorkerUrl has changed, it means there is a new downstream UserWorker
|
|
161
|
+
// and that this error is stale since it was for a request to the old UserWorker
|
|
162
|
+
// so here we construct a newUserWorkerUrl so we can compare it to the (old) userWorkerUrl
|
|
163
|
+
const newUserWorkerUrl =
|
|
164
|
+
this.proxyData && urlFromParts(this.proxyData.userWorkerUrl);
|
|
165
|
+
|
|
166
|
+
// only report errors if the downstream proxy has NOT changed
|
|
167
|
+
if (userWorkerUrl.href === newUserWorkerUrl?.href) {
|
|
168
|
+
void sendMessageToProxyController(this.env, {
|
|
169
|
+
type: "error",
|
|
170
|
+
error: {
|
|
171
|
+
name: error.name,
|
|
172
|
+
message: error.message,
|
|
173
|
+
stack: error.stack,
|
|
174
|
+
cause: error.cause,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
deferredResponse.reject(error);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// if the request can be retried (subset of idempotent requests which have no body), requeue it
|
|
182
|
+
else if (request.method === "GET" || request.method === "HEAD") {
|
|
183
|
+
this.requestRetryQueue.set(request, deferredResponse);
|
|
184
|
+
// we would only end up here if the downstream UserWorker is chang*ing*
|
|
185
|
+
// i.e. we are in a `pause`d state and expecting a `play` message soon
|
|
186
|
+
// this request will be processed (retried) when the `play` message arrives
|
|
187
|
+
// for that reason, we do not need to call `this.processQueue` here
|
|
188
|
+
// (but, also, it can't hurt to call it since it bails when
|
|
189
|
+
// in a `pause`d state i.e. `this.proxyData` is undefined)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// if the request cannot be retried, respond with 503 Service Unavailable
|
|
193
|
+
// important to note, this is not an (unexpected) error -- it is an acceptable flow of local development
|
|
194
|
+
// it would be incorrect to retry non-idempotent requests
|
|
195
|
+
// and would require cloning all body streams to avoid stream reuse (which is inefficient but not out of the question in the future)
|
|
196
|
+
// this is a good enough UX for now since it solves the most common GET use-case
|
|
197
|
+
else {
|
|
198
|
+
deferredResponse.resolve(
|
|
199
|
+
new Response(
|
|
200
|
+
"Your worker restarted mid-request. Please try sending the request again. Only GET or HEAD requests are retried automatically.",
|
|
201
|
+
{
|
|
202
|
+
status: 503,
|
|
203
|
+
headers: { "Retry-After": "0" },
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
151
208
|
});
|
|
152
209
|
}
|
|
153
210
|
}
|
|
@@ -166,25 +223,14 @@ function isRequestForLiveReloadWebsocket(req: Request): boolean {
|
|
|
166
223
|
return isWebSocketUpgrade && websocketProtocol === LIVE_RELOAD_PROTOCOL;
|
|
167
224
|
}
|
|
168
225
|
|
|
169
|
-
|
|
226
|
+
function sendMessageToProxyController(
|
|
170
227
|
env: Env,
|
|
171
|
-
message: ProxyWorkerOutgoingRequestBody
|
|
172
|
-
retries = 3
|
|
228
|
+
message: ProxyWorkerOutgoingRequestBody
|
|
173
229
|
) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
});
|
|
179
|
-
} catch (cause) {
|
|
180
|
-
if (retries > 0) {
|
|
181
|
-
return sendMessageToProxyController(env, message, retries - 1);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// no point sending an error message if we can't send this message
|
|
185
|
-
|
|
186
|
-
throw cause;
|
|
187
|
-
}
|
|
230
|
+
return env.PROXY_CONTROLLER.fetch("http://dummy", {
|
|
231
|
+
method: "POST",
|
|
232
|
+
body: JSON.stringify(message),
|
|
233
|
+
});
|
|
188
234
|
}
|
|
189
235
|
|
|
190
236
|
function insertLiveReloadScript(
|
|
@@ -250,3 +296,31 @@ function insertLiveReloadScript(
|
|
|
250
296
|
|
|
251
297
|
return htmlRewriter.transform(response);
|
|
252
298
|
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Rewrite references to URLs in request/response headers.
|
|
302
|
+
*
|
|
303
|
+
* This function is used to map the URLs in headers like Origin and Access-Control-Allow-Origin
|
|
304
|
+
* so that this proxy is transparent to the Client Browser and User Worker.
|
|
305
|
+
*/
|
|
306
|
+
function rewriteUrlRelatedHeaders(headers: Headers, from: URL, to: URL) {
|
|
307
|
+
const setCookie = headers.getAll("Set-Cookie");
|
|
308
|
+
headers.delete("Set-Cookie");
|
|
309
|
+
headers.forEach((value, key) => {
|
|
310
|
+
if (typeof value === "string" && value.includes(from.host)) {
|
|
311
|
+
headers.set(
|
|
312
|
+
key,
|
|
313
|
+
value.replaceAll(from.origin, to.origin).replaceAll(from.host, to.host)
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
for (const cookie of setCookie) {
|
|
318
|
+
headers.append(
|
|
319
|
+
"Set-Cookie",
|
|
320
|
+
cookie.replace(
|
|
321
|
+
new RegExp(`Domain=${from.hostname}($|;|,)`),
|
|
322
|
+
`Domain=${to.hostname}$1`
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -41,6 +41,15 @@ function urlFromParts(parts, base = "http://localhost") {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// templates/startDevWorker/InspectorProxyWorker.ts
|
|
44
|
+
var ALLOWED_HOST_HOSTNAMES = ["127.0.0.1", "[::1]", "localhost"];
|
|
45
|
+
var ALLOWED_ORIGIN_HOSTNAMES = [
|
|
46
|
+
"devtools.devprod.cloudflare.dev",
|
|
47
|
+
"cloudflare-devtools.pages.dev",
|
|
48
|
+
/^[a-z0-9]+\.cloudflare-devtools\.pages\.dev$/,
|
|
49
|
+
"127.0.0.1",
|
|
50
|
+
"[::1]",
|
|
51
|
+
"localhost"
|
|
52
|
+
];
|
|
44
53
|
var InspectorProxyWorker_default = {
|
|
45
54
|
fetch(req, env) {
|
|
46
55
|
const singleton = env.DURABLE_OBJECT.idFromName("");
|
|
@@ -207,6 +216,10 @@ var InspectorProxyWorker = class {
|
|
|
207
216
|
);
|
|
208
217
|
runtimeWebSocketUrl.protocol = this.proxyData.userWorkerUrl.protocol;
|
|
209
218
|
this.sendDebugLog("NEW RUNTIME WEBSOCKET", runtimeWebSocketUrl);
|
|
219
|
+
this.sendDevToolsMessage({
|
|
220
|
+
method: "Runtime.executionContextsCleared",
|
|
221
|
+
params: void 0
|
|
222
|
+
});
|
|
210
223
|
const upgrade = await fetch(runtimeWebSocketUrl, {
|
|
211
224
|
headers: {
|
|
212
225
|
...this.proxyData.headers,
|
|
@@ -330,6 +343,38 @@ var InspectorProxyWorker = class {
|
|
|
330
343
|
return new Response(null, { status: 404 });
|
|
331
344
|
}
|
|
332
345
|
async handleDevToolsWebSocketUpgradeRequest(req) {
|
|
346
|
+
let hostHeader = req.headers.get("Host");
|
|
347
|
+
if (hostHeader == null)
|
|
348
|
+
return new Response(null, { status: 400 });
|
|
349
|
+
try {
|
|
350
|
+
const host = new URL(`http://${hostHeader}`);
|
|
351
|
+
if (!ALLOWED_HOST_HOSTNAMES.includes(host.hostname)) {
|
|
352
|
+
return new Response("Disallowed `Host` header", { status: 401 });
|
|
353
|
+
}
|
|
354
|
+
} catch {
|
|
355
|
+
return new Response("Expected `Host` header", { status: 400 });
|
|
356
|
+
}
|
|
357
|
+
let originHeader = req.headers.get("Origin");
|
|
358
|
+
if (originHeader === null && !req.headers.has("User-Agent")) {
|
|
359
|
+
originHeader = "http://localhost";
|
|
360
|
+
}
|
|
361
|
+
if (originHeader === null) {
|
|
362
|
+
return new Response("Expected `Origin` header", { status: 400 });
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
const origin = new URL(originHeader);
|
|
366
|
+
const allowed = ALLOWED_ORIGIN_HOSTNAMES.some((rule) => {
|
|
367
|
+
if (typeof rule === "string")
|
|
368
|
+
return origin.hostname === rule;
|
|
369
|
+
else
|
|
370
|
+
return rule.test(origin.hostname);
|
|
371
|
+
});
|
|
372
|
+
if (!allowed) {
|
|
373
|
+
return new Response("Disallowed `Origin` header", { status: 401 });
|
|
374
|
+
}
|
|
375
|
+
} catch {
|
|
376
|
+
return new Response("Expected `Origin` header", { status: 400 });
|
|
377
|
+
}
|
|
333
378
|
this.sendDebugLog("DEVTOOLS WEBSOCKET TRYING TO CONNECT");
|
|
334
379
|
await this.websockets.runtimeDeferred.promise;
|
|
335
380
|
this.sendDebugLog("DEVTOOLS WEBSOCKET CAN NOW CONNECT");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../templates/startDevWorker/InspectorProxyWorker.ts", "../src/api/startDevWorker/events.ts", "../src/api/startDevWorker/utils.ts"],
|
|
4
|
-
"mappings": ";AAAA,OAAOA,aAAY;;;
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["assert", "assert"]
|
|
6
6
|
}
|