Skip to content

Commit e0a0916

Browse files
committed
refactor(miniflare): move platform proxy API to cdn-cgi
1 parent bbd1626 commit e0a0916

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

packages/miniflare/src/plugins/core/proxy/client.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { prefixStream, readPrefix } from "../../../shared";
1010
import {
1111
Awaitable,
1212
CoreHeaders,
13+
CorePaths,
1314
createHTTPReducers,
1415
createHTTPRevivers,
1516
isDurableObjectStub,
@@ -97,7 +98,10 @@ export class ProxyClient {
9798
#bridge: ProxyClientBridge;
9899

99100
constructor(runtimeEntryURL: URL, dispatchFetch: DispatchFetch) {
100-
this.#bridge = new ProxyClientBridge(runtimeEntryURL, dispatchFetch);
101+
this.#bridge = new ProxyClientBridge(
102+
new URL(CorePaths.PLATFORM_PROXY, runtimeEntryURL),
103+
dispatchFetch
104+
);
101105
}
102106

103107
// Lazily initialise proxies as required
@@ -120,7 +124,7 @@ export class ProxyClient {
120124
setRuntimeEntryURL(runtimeEntryURL: URL) {
121125
// This function will be called whenever the runtime restarts. The URL may
122126
// be different if the port has changed.
123-
this.#bridge.url = runtimeEntryURL;
127+
this.#bridge.url = new URL(CorePaths.PLATFORM_PROXY, runtimeEntryURL);
124128
}
125129

126130
dispose(): Promise<void> {
@@ -716,9 +720,12 @@ class ProxyStubHandler<T extends object>
716720
#fetcherFetchCall(args: unknown[]) {
717721
// @ts-expect-error `...args` isn't type-safe here, but `undici` should
718722
// validate types at runtime, and throw appropriate errors
719-
const request = new Request(...args);
723+
const userRequest = new Request(...args);
724+
// Create a new request with the proxy URL, preserving the original request
725+
const request = new Request(this.bridge.url, userRequest);
720726
// If adding new headers here, remember to `delete()` them in `ProxyServer`
721727
// before calling `fetch()`.
728+
request.headers.set(CoreHeaders.ORIGINAL_URL, userRequest.url);
722729
request.headers.set(CoreHeaders.OP_SECRET, PROXY_SECRET_HEX);
723730
request.headers.set(CoreHeaders.OP, ProxyOps.CALL);
724731
request.headers.set(CoreHeaders.OP_TARGET, this.#stringifiedTarget);

packages/miniflare/src/workers/core/entry.worker.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,14 @@ export default <ExportedHandler<Env>>{
382382
};
383383
request = new Request(request, { cf });
384384

385-
// The magic proxy client (used by getPlatformProxy) will always specify an operation
386-
const isProxy = request.headers.get(CoreHeaders.OP) !== null;
387-
if (isProxy) return handleProxy(request, env);
385+
// The magic proxy client (used by getPlatformProxy)
386+
if (new URL(request.url).pathname === CorePaths.PLATFORM_PROXY) {
387+
if (request.headers.get(CoreHeaders.OP) !== null) {
388+
return handleProxy(request, env);
389+
}
390+
391+
return new Response("Invalid proxy request", { status: 400 });
392+
}
388393

389394
// `dispatchFetch()` will always inject this header. When
390395
// calling this function, we never want to display the pretty-error page.

packages/miniflare/test/plugins/core/proxy/client.spec.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { text } from "node:stream/consumers";
55
import { ReadableStream, WritableStream } from "node:stream/web";
66
import util from "node:util";
77
import {
8+
CorePaths,
89
DeferredPromise,
910
fetch,
1011
MessageEvent,
@@ -329,32 +330,38 @@ describe("ProxyClient", () => {
329330
const mf = new Miniflare({ script: nullScript });
330331
useDispose(mf);
331332
const url = await mf.ready;
333+
const proxyUrl = new URL(CorePaths.PLATFORM_PROXY, url);
332334

333335
// Check validates `Host` header
334336
const statusPromise = new DeferredPromise<number>();
335337
const req = http.get(
336-
url,
338+
proxyUrl,
337339
{ setHost: false, headers: { "MF-Op": "GET", Host: "localhost" } },
338340
(res) => statusPromise.resolve(res.statusCode ?? 0)
339341
);
340342
req.on("error", (error) => statusPromise.reject(error));
341343
expect(await statusPromise).toBe(401);
342344

343345
// Check validates `MF-Op-Secret` header
344-
let res = await fetch(url, {
346+
let res = await fetch(proxyUrl, {
345347
headers: { "MF-Op": "GET" }, // (missing)
346348
});
347349
expect(res.status).toBe(401);
348350
await res.arrayBuffer(); // (drain)
349-
res = await fetch(url, {
351+
res = await fetch(proxyUrl, {
350352
headers: { "MF-Op": "GET", "MF-Op-Secret": "aaaa" }, // (too short)
351353
});
352354
expect(res.status).toBe(401);
353355
await res.arrayBuffer(); // (drain)
354-
res = await fetch(url, {
356+
res = await fetch(proxyUrl, {
355357
headers: { "MF-Op": "GET", "MF-Op-Secret": "a".repeat(32) }, // (wrong)
356358
});
357359
expect(res.status).toBe(401);
358360
await res.arrayBuffer(); // (drain)
361+
362+
// Check requests to proxy path without MF-Op header return 400
363+
res = await fetch(proxyUrl);
364+
expect(res.status).toBe(400);
365+
await res.arrayBuffer(); // (drain)
359366
});
360367
});

0 commit comments

Comments
 (0)