Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { test } from "vitest";
import { getResponse, getTextResponse } from "../../__test-utils__";

test("serves Local Explorer UI", async ({ expect }) => {
let response = await getResponse("/cdn-cgi/local/explorer");
expect(response.status()).toBe(200);
response = await getResponse("/cdn-cgi/explorer");
const response = await getResponse("/cdn-cgi/local/explorer");
expect(response.status()).toBe(200);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { describe, test } from "vitest";
import { test } from "vitest";
import { getTextResponse, serverLogs } from "../../__test-utils__";

describe.each(["/cdn-cgi/local/scheduled", "/cdn-cgi/handler/scheduled"])(
"%s",
(path) => {
test("Supports testing Cron Triggers", async ({ expect }) => {
const cronResponse = await getTextResponse(path);
expect(cronResponse).toBe("ok");
expect(serverLogs.info.join()).toContain("Cron processed");
});
}
);
test("Supports testing Cron Triggers", async ({ expect }) => {
const cronResponse = await getTextResponse("/cdn-cgi/local/scheduled");
expect(cronResponse).toBe("ok");
expect(serverLogs.info.join()).toContain("Cron processed");
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import dedent from "ts-dedent";
import { describe, test, vi } from "vitest";
import { test, vi } from "vitest";
import {
getTextResponse,
rootDir,
Expand All @@ -16,43 +16,39 @@ test("Supports sending email via the email binding", async ({ expect }) => {
expect(sendEmailResponse).toBe("Email message sent successfully!");
});

// The canonical path is `/cdn-cgi/local/email`; `/cdn-cgi/handler/email` is the
// legacy path kept working via a rewrite in the trigger-handlers plugin.
describe.each(["/cdn-cgi/local/email", "/cdn-cgi/handler/email"])(
"%s",
(path) => {
test("Supports testing Email Workers", async ({ expect }) => {
const params = new URLSearchParams();
params.append("from", "sender@example.com");
params.append("to", "recipient@example.com");
test("Supports testing Email Workers", async ({ expect }) => {
const params = new URLSearchParams();
params.append("from", "sender@example.com");
params.append("to", "recipient@example.com");

const fetchResponse = await fetch(`${viteTestUrl}${path}?${params}`, {
method: "POST",
body: dedent`
From: "John" <sender@example.com>
Reply-To: sender@example.com
To: recipient@example.com
Subject: Testing Email Workers Local Dev
Content-Type: text/html; charset="windows-1252"
X-Mailer: Curl
Date: Tue, 27 Aug 2024 08:49:44 -0700
Message-ID: <6114391943504294873000@ZSH-GHOSTTY>
const fetchResponse = await fetch(
`${viteTestUrl}/cdn-cgi/local/email?${params}`,
{
method: "POST",
body: dedent`
From: "John" <sender@example.com>
Reply-To: sender@example.com
To: recipient@example.com
Subject: Testing Email Workers Local Dev
Content-Type: text/html; charset="windows-1252"
X-Mailer: Curl
Date: Tue, 27 Aug 2024 08:49:44 -0700
Message-ID: <6114391943504294873000@ZSH-GHOSTTY>

Hi there
`,
});
Hi there
`,
}
);

const emailStdout = serverLogs.info.join();
expect(await fetchResponse.text()).toBe(
"Worker successfully processed email"
);
expect(emailStdout).toContain(
`Received email from sender@example.com on ${new Date(" 27 Aug 2024 08:49:44 -0700").toISOString()} with following message:`
);
expect(emailStdout).toContain("Hi there");
});
}
);
const emailStdout = serverLogs.info.join();
expect(await fetchResponse.text()).toBe(
"Worker successfully processed email"
);
expect(emailStdout).toContain(
`Received email from sender@example.com on ${new Date(" 27 Aug 2024 08:49:44 -0700").toISOString()} with following message:`
);
expect(emailStdout).toContain("Hi there");
});

test("logs sent emails to a directory within the project directory", async ({
expect,
Expand Down
9 changes: 1 addition & 8 deletions packages/vite-plugin-cloudflare/src/plugins/preview.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { buildPublicUrl, Request as MiniflareRequest } from "miniflare";
import { buildPublicUrl } from "miniflare";
import { assertIsPreview } from "../context";
import { getPreviewMiniflareOptions } from "../miniflare-options";
import { createPlugin, createRequestHandler } from "../utils";
import { handleWebSocket } from "../websockets";
import { rewriteLegacyMiniflarePath } from "./trigger-handlers";

/**
* Plugin to provide core preview functionality
Expand Down Expand Up @@ -54,12 +53,6 @@ export const previewPlugin = createPlugin("preview", (ctx) => {
// In preview mode we put our middleware at the front of the chain so that all assets are handled in Miniflare
vitePreviewServer.middlewares.use(
createRequestHandler((request) => {
const url = new URL(request.url);
const rewritten = rewriteLegacyMiniflarePath(url.pathname);
if (rewritten !== url.pathname) {
url.pathname = rewritten;
request = new MiniflareRequest(url, request);
}
return ctx.miniflare.dispatchFetch(request, { redirect: "manual" });
})
);
Expand Down
51 changes: 5 additions & 46 deletions packages/vite-plugin-cloudflare/src/plugins/trigger-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,8 @@
import { CoreHeaders, Request as MiniflareRequest } from "miniflare";
import { CoreHeaders } from "miniflare";
import { createPlugin, createRequestHandler } from "../utils";

// Miniflare v5 moved its internal endpoints under `/cdn-cgi/local/` (and
// `/__cf_local/` for endpoints that must remain reachable over tunnels). These
// map the pre-v5 paths onto their current equivalents. This must stay in sync
// with `rewriteLegacyMiniflarePath()` in Wrangler's ProxyWorker.
const LEGACY_PATH_REWRITES: readonly [string, string][] = [
["/cdn-cgi/handler", "/cdn-cgi/local"],
["/cdn-cgi/mf/scheduled", "/cdn-cgi/local/scheduled"],
["/cdn-cgi/mf/stream", "/__cf_local/stream"],
["/cdn-cgi/mf/imagedelivery", "/__cf_local/imagedelivery"],
["/cdn-cgi/explorer", "/cdn-cgi/local/explorer"],
];

export function rewriteLegacyMiniflarePath(pathname: string): string {
for (const [oldPrefix, newPrefix] of LEGACY_PATH_REWRITES) {
if (pathname === oldPrefix || pathname.startsWith(`${oldPrefix}/`)) {
return newPrefix + pathname.slice(oldPrefix.length);
}
}
return pathname;
}

/**
* Plugin to forward trigger handler routes (scheduled, email) and other
* internal Miniflare endpoints to Miniflare in development, including
* backwards-compatible rewrites for pre-v5 paths.
* Plugin to forward local testing routes to Miniflare in development.
*/
export const triggerHandlersPlugin = createPlugin("trigger-handlers", (ctx) => {
return {
Expand All @@ -38,32 +15,14 @@ export const triggerHandlersPlugin = createPlugin("trigger-handlers", (ctx) => {
}

const entryWorkerName = entryWorkerConfig.name;

function dispatch(request: MiniflareRequest) {
const requestHandler = createRequestHandler((request) => {
request.headers.set(CoreHeaders.ROUTE_OVERRIDE, entryWorkerName);
return ctx.miniflare.dispatchFetch(request, {
redirect: "manual",
});
}

// Canonical paths: forward directly to Miniflare.
viteDevServer.middlewares.use(
"/cdn-cgi/local/",
createRequestHandler((request) => dispatch(request))
);
});

// Backwards compatibility: rewrite legacy paths onto their canonical
// equivalents before dispatching.
for (const [oldPrefix, newPrefix] of LEGACY_PATH_REWRITES) {
viteDevServer.middlewares.use(
oldPrefix,
createRequestHandler((request) => {
const url = new URL(request.url);
url.pathname = newPrefix + url.pathname.slice(oldPrefix.length);
return dispatch(new MiniflareRequest(url, request));
})
);
}
viteDevServer.middlewares.use("/cdn-cgi/local/", requestHandler);
},
};
});
Loading