From 5124b5da4f8c12bbb6192f2d89241a9c54ab73c7 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Wed, 18 Dec 2024 02:08:56 +0000 Subject: [PATCH] Allow Workers Assets to be configured on a path (#7476) --- .changeset/early-baboons-fly.md | 7 + .../asset-worker/tests/handler.test.ts | 50 +++ .../wrangler/src/__tests__/deploy.test.ts | 387 ++++++++++++++---- packages/wrangler/src/__tests__/dev.test.ts | 61 +-- packages/wrangler/src/deploy/deploy.ts | 51 ++- packages/wrangler/src/dev.ts | 8 +- packages/wrangler/src/triggers/deploy.ts | 2 +- 7 files changed, 425 insertions(+), 141 deletions(-) create mode 100644 .changeset/early-baboons-fly.md diff --git a/.changeset/early-baboons-fly.md b/.changeset/early-baboons-fly.md new file mode 100644 index 000000000000..c57ab56ee712 --- /dev/null +++ b/.changeset/early-baboons-fly.md @@ -0,0 +1,7 @@ +--- +"wrangler": minor +--- + +feat: allow routing to Workers with Assets on any HTTP route, not just the root. For example, `example.com/blog/*` can now be used to serve assets. +These assets will be served as though the assets directly were mounted to the root. +For example, if you have `assets = { directory = "./public/" }`, a route like `"example.com/blog/*"` and a file `./public/blog/logo.png`, this will be available at `example.com/blog/logo.png`. Assets outside of directories which match the configured HTTP routes can still be accessed with the [Assets binding](https://developers.cloudflare.com/workers/static-assets/binding/#binding) or with a [Service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to this Worker. diff --git a/packages/workers-shared/asset-worker/tests/handler.test.ts b/packages/workers-shared/asset-worker/tests/handler.test.ts index 9d01d635b071..84b1f251843c 100644 --- a/packages/workers-shared/asset-worker/tests/handler.test.ts +++ b/packages/workers-shared/asset-worker/tests/handler.test.ts @@ -1,4 +1,5 @@ import { vi } from "vitest"; +import { applyConfigurationDefaults } from "../src/configuration"; import { handleRequest } from "../src/handler"; import type { AssetConfig } from "../../utils/types"; @@ -100,4 +101,53 @@ describe("[Asset Worker] `handleRequest`", () => { expect(response.status).toBe(200); }); + + it("cannot fetch assets outside of configured path", async () => { + const assets: Record = { + "/blog/test.html": "aaaaaaaaaa", + "/blog/index.html": "bbbbbbbbbb", + "/index.html": "cccccccccc", + "/test.html": "dddddddddd", + }; + + // Attempt to path traverse down to the root /test within asset-server + let response = await handleRequest( + new Request("https://example.com/blog/../test"), + applyConfigurationDefaults({}), + async (pathname: string) => { + if (pathname.startsWith("/blog/")) { + // our route + return assets[pathname] ?? null; + } else { + return null; + } + }, + async (_: string) => ({ + readableStream: new ReadableStream(), + contentType: "text/html", + }) + ); + + expect(response.status).toBe(404); + + // Attempt to path traverse down to the root /test within asset-server + response = await handleRequest( + new Request("https://example.com/blog/%2E%2E/test"), + applyConfigurationDefaults({}), + async (pathname: string) => { + if (pathname.startsWith("/blog/")) { + // our route + return assets[pathname] ?? null; + } else { + return null; + } + }, + async (_: string) => ({ + readableStream: new ReadableStream(), + contentType: "text/html", + }) + ); + + expect(response.status).toBe(404); + }); }); diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index 263aeec98eef..5488768ef321 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -1602,95 +1602,336 @@ Update them to point to this script instead?`, }); }); - it("should error on routes with paths if assets are present", async () => { - writeWranglerConfig({ - routes: [ - "simple.co.uk/path", - "simple.co.uk/path/*", - "simple.co.uk/", - "simple.co.uk/*", - "simple.co.uk", - { pattern: "route.co.uk/path", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/path/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/", zone_id: "asdfadsf" }, - { pattern: "route.co.uk", zone_id: "asdfadsf" }, - { pattern: "custom.co.uk/path", custom_domain: true }, - { pattern: "custom.co.uk/*", custom_domain: true }, - { pattern: "custom.co.uk", custom_domain: true }, - ], + describe("deploy asset routes", () => { + it("shouldn't error on routes with paths if there are no assets", async () => { + writeWranglerConfig({ + routes: [ + "simple.co.uk/path", + "simple.co.uk/path/*", + "simple.co.uk/", + "simple.co.uk/*", + "simple.co.uk", + { pattern: "route.co.uk/path", zone_id: "asdfadsf" }, + { pattern: "route.co.uk/path/*", zone_id: "asdfadsf" }, + { pattern: "route.co.uk/*", zone_id: "asdfadsf" }, + { pattern: "route.co.uk/", zone_id: "asdfadsf" }, + { pattern: "route.co.uk", zone_id: "asdfadsf" }, + { pattern: "custom.co.uk/path", custom_domain: true }, + { pattern: "custom.co.uk/*", custom_domain: true }, + { pattern: "custom.co.uk", custom_domain: true }, + ], + }); + writeWorkerSource(); + + await expect(runWrangler(`deploy ./index`)).rejects + .toThrowErrorMatchingInlineSnapshot(` + [Error: Invalid Routes: + custom.co.uk/path: + Paths are not allowed in Custom Domains + + custom.co.uk/*: + Wildcard operators (*) are not allowed in Custom Domains + Paths are not allowed in Custom Domains] + `); }); - writeWorkerSource(); - writeAssets([{ filePath: "asset.txt", content: "Content of file-1" }]); - await expect(runWrangler(`deploy --assets="assets"`)).rejects - .toThrowErrorMatchingInlineSnapshot(` - [Error: Invalid Routes: - simple.co.uk/path: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path with /* + it("should warn on mounted paths", async () => { + writeWranglerConfig({ + routes: [ + "simple.co.uk/path/*", + "simple.co.uk/*", + "*/*", + "*/blog/*", + { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, + { pattern: "example.com/*", zone_id: "asdfadsf" }, + { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + ], + }); + await mockAUSRequest([]); + mockSubDomainRequest(); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUploadWorkerRequest({ + expectedAssets: { + jwt: "<>", + config: {}, + }, + expectedType: "none", + }); + mockPublishRoutesRequest({ + routes: [ + // @ts-expect-error - this is what is expected + { + pattern: "simple.co.uk/path/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "simple.co.uk/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "*/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "*/blog/*", + }, + { + pattern: "example.com/blog/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/abc/def/*", + zone_id: "asdfadsf", + }, + ], + }); + + writeWorkerSource(); + writeAssets([{ filePath: "asset.txt", content: "Content of file-1" }]); - simple.co.uk/path/*: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path/* with /* + await runWrangler(`deploy --assets assets`); - simple.co.uk/: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Warning: The following routes will attempt to serve Assets on a configured path: - simple.co.uk: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + • simple.co.uk/path/* (Will match assets: assets/path/*) + • */blog/* (Will match assets: assets/blog/*) + • example.com/blog/* (Will match assets: assets/blog/*) + • example.com/abc/def/* (Will match assets: assets/abc/def/*) - route.co.uk/path: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path with /* + " + `); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + simple.co.uk/path/* + simple.co.uk/* + */* + */blog/* + example.com/blog/* (zone id: asdfadsf) + example.com/* (zone id: asdfadsf) + example.com/abc/def/* (zone id: asdfadsf) + Current Version ID: Galaxy-Class" + `); + }); - route.co.uk/path/*: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path/* with /* + it("does not mention 404s hit a Worker if it's assets only", async () => { + writeWranglerConfig({ + routes: [ + { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, + { pattern: "example.com/*", zone_id: "asdfadsf" }, + { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + ], + assets: { + directory: "assets", + }, + }); + await mockAUSRequest([]); + mockSubDomainRequest(); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUploadWorkerRequest({ + expectedAssets: { + jwt: "<>", + config: {}, + }, + expectedType: "none", + }); + mockPublishRoutesRequest({ + routes: [ + { + pattern: "example.com/blog/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/abc/def/*", + zone_id: "asdfadsf", + }, + ], + }); - route.co.uk/: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + writeAssets([{ filePath: "asset.txt", content: "Content of file-1" }]); - route.co.uk: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + await runWrangler(`deploy`); - custom.co.uk/path: - Paths are not allowed in Custom Domains + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Warning: The following routes will attempt to serve Assets on a configured path: - custom.co.uk/*: - Wildcard operators (*) are not allowed in Custom Domains - Paths are not allowed in Custom Domains] - `); - }); + • example.com/blog/* (Will match assets: assets/blog/*) + • example.com/abc/def/* (Will match assets: assets/abc/def/*) - it("shouldn't error on routes with paths if there are no assets", async () => { - writeWranglerConfig({ - routes: [ - "simple.co.uk/path", - "simple.co.uk/path/*", - "simple.co.uk/", - "simple.co.uk/*", - "simple.co.uk", - { pattern: "route.co.uk/path", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/path/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/", zone_id: "asdfadsf" }, - { pattern: "route.co.uk", zone_id: "asdfadsf" }, - { pattern: "custom.co.uk/path", custom_domain: true }, - { pattern: "custom.co.uk/*", custom_domain: true }, - { pattern: "custom.co.uk", custom_domain: true }, - ], + " + `); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + example.com/blog/* (zone id: asdfadsf) + example.com/* (zone id: asdfadsf) + example.com/abc/def/* (zone id: asdfadsf) + Current Version ID: Galaxy-Class" + `); }); - writeWorkerSource(); - await expect(runWrangler(`deploy ./index`)).rejects - .toThrowErrorMatchingInlineSnapshot(` - [Error: Invalid Routes: - custom.co.uk/path: - Paths are not allowed in Custom Domains + it("does mention hitting the Worker on 404 if there is one", async () => { + writeWranglerConfig({ + routes: [ + { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, + { pattern: "example.com/*", zone_id: "asdfadsf" }, + { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + ], + assets: { + directory: "assets", + }, + }); + writeWorkerSource(); + await mockAUSRequest([]); + mockSubDomainRequest(); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUploadWorkerRequest({ + expectedAssets: { + jwt: "<>", + config: {}, + }, + expectedType: "esm", + expectedMainModule: "index.js", + }); + mockPublishRoutesRequest({ + routes: [ + { + pattern: "example.com/blog/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/abc/def/*", + zone_id: "asdfadsf", + }, + ], + }); - custom.co.uk/*: - Wildcard operators (*) are not allowed in Custom Domains - Paths are not allowed in Custom Domains] - `); - }); + writeAssets([{ filePath: "asset.txt", content: "Content of file-1" }]); + + await runWrangler(`deploy ./index`); + + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Warning: The following routes will attempt to serve Assets on a configured path: + + • example.com/blog/* (Will match assets: assets/blog/*) + • example.com/abc/def/* (Will match assets: assets/abc/def/*) + + Requests not matching an asset will be forwarded to the Worker's code. + + " + `); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + example.com/blog/* (zone id: asdfadsf) + example.com/* (zone id: asdfadsf) + example.com/abc/def/* (zone id: asdfadsf) + Current Version ID: Galaxy-Class" + `); + }); + + it("should not warn on mounted paths if serve_directly = true", async () => { + writeWranglerConfig({ + routes: [ + "simple.co.uk/path/*", + "simple.co.uk/*", + "*/*", + "*/blog/*", + { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, + { pattern: "example.com/*", zone_id: "asdfadsf" }, + { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, + ], + assets: { + directory: "assets", + experimental_serve_directly: true, + }, + }); + await mockAUSRequest([]); + mockSubDomainRequest(); + mockUpdateWorkerSubdomain({ enabled: false, previews_enabled: true }); + mockUploadWorkerRequest({ + expectedAssets: { + jwt: "<>", + config: { + serve_directly: true, + }, + }, + expectedType: "none", + }); + mockPublishRoutesRequest({ + routes: [ + // @ts-expect-error - this is what is expected + { + pattern: "simple.co.uk/path/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "simple.co.uk/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "*/*", + }, + // @ts-expect-error - this is what is expected + { + pattern: "*/blog/*", + }, + { + pattern: "example.com/blog/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/*", + zone_id: "asdfadsf", + }, + { + pattern: "example.com/abc/def/*", + zone_id: "asdfadsf", + }, + ], + }); + + writeWorkerSource(); + writeAssets([{ filePath: "asset.txt", content: "Content of file-1" }]); + + await runWrangler(`deploy`); + expect(std.warn).toMatchInlineSnapshot(`""`); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Worker Startup Time: 100 ms + Uploaded test-name (TIMINGS) + Deployed test-name triggers (TIMINGS) + simple.co.uk/path/* + simple.co.uk/* + */* + */blog/* + example.com/blog/* (zone id: asdfadsf) + example.com/* (zone id: asdfadsf) + example.com/abc/def/* (zone id: asdfadsf) + Current Version ID: Galaxy-Class" + `); + }); + }); it.todo("should error if it's a workers.dev route"); }); diff --git a/packages/wrangler/src/__tests__/dev.test.ts b/packages/wrangler/src/__tests__/dev.test.ts index f4125b907417..23d77e47ea01 100644 --- a/packages/wrangler/src/__tests__/dev.test.ts +++ b/packages/wrangler/src/__tests__/dev.test.ts @@ -374,6 +374,7 @@ describe.sequential("wrangler dev", () => { ], }); }); + it("should error if custom domains with paths are passed in but allow paths on normal routes", async () => { fs.writeFileSync("index.js", `export default {};`); writeWranglerConfig({ @@ -401,61 +402,33 @@ describe.sequential("wrangler dev", () => { Paths are not allowed in Custom Domains] `); }); - it("should error on routes with paths if assets are present", async () => { + + it("should warn on mounted paths in dev", async () => { writeWranglerConfig({ routes: [ - "simple.co.uk/path", "simple.co.uk/path/*", - "simple.co.uk/", "simple.co.uk/*", - "simple.co.uk", - { pattern: "route.co.uk/path", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/path/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/*", zone_id: "asdfadsf" }, - { pattern: "route.co.uk/", zone_id: "asdfadsf" }, - { pattern: "route.co.uk", zone_id: "asdfadsf" }, - { pattern: "custom.co.uk/path", custom_domain: true }, - { pattern: "custom.co.uk/*", custom_domain: true }, - { pattern: "custom.co.uk", custom_domain: true }, + "*/*", + "*/blog/*", + { pattern: "example.com/blog/*", zone_id: "asdfadsf" }, + { pattern: "example.com/*", zone_id: "asdfadsf" }, + { pattern: "example.com/abc/def/*", zone_id: "asdfadsf" }, ], - assets: { - directory: "assets", - }, }); - fs.mkdirSync("assets"); - await expect(runWrangler(`dev`)).rejects - .toThrowErrorMatchingInlineSnapshot(` - [Error: Invalid Routes: - simple.co.uk/path: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path with /* - - simple.co.uk/path/*: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path/* with /* - - simple.co.uk/: - Workers which have static assets must end with a wildcard path. Update the route to end with /* - simple.co.uk: - Workers which have static assets must end with a wildcard path. Update the route to end with /* - - route.co.uk/path: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path with /* - - route.co.uk/path/*: - Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /path/* with /* + fs.mkdirSync("assets"); - route.co.uk/: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + await runWranglerUntilConfig("dev --assets assets"); - route.co.uk: - Workers which have static assets must end with a wildcard path. Update the route to end with /* + expect(std.warn).toMatchInlineSnapshot(` + "▲ [WARNING] Warning: The following routes will attempt to serve Assets on a configured path: - custom.co.uk/path: - Paths are not allowed in Custom Domains + • simple.co.uk/path/* (Will match assets: assets/path/*) + • */blog/* (Will match assets: assets/blog/*) + • example.com/blog/* (Will match assets: assets/blog/*) + • example.com/abc/def/* (Will match assets: assets/abc/def/*) - custom.co.uk/*: - Wildcard operators (*) are not allowed in Custom Domains - Paths are not allowed in Custom Domains] + " `); }); }); diff --git a/packages/wrangler/src/deploy/deploy.ts b/packages/wrangler/src/deploy/deploy.ts index a5e3c88c25bd..5c24b2492cdf 100644 --- a/packages/wrangler/src/deploy/deploy.ts +++ b/packages/wrangler/src/deploy/deploy.ts @@ -174,8 +174,10 @@ function errIsStartupErr(err: unknown): err is ParseError & { code: 10021 } { return false; } -export const validateRoutes = (routes: Route[], hasAssets: boolean) => { +export const validateRoutes = (routes: Route[], assets?: AssetsOptions) => { const invalidRoutes: Record = {}; + const mountedAssetRoutes: string[] = []; + for (const route of routes) { if (typeof route !== "string" && route.custom_domain) { if (route.pattern.includes("*")) { @@ -190,26 +192,17 @@ export const validateRoutes = (routes: Route[], hasAssets: boolean) => { `Paths are not allowed in Custom Domains` ); } - } else if (hasAssets) { + // If we have Assets but we're not always hitting the Worker then validate + } else if ( + assets?.directory !== undefined && + assets.assetConfig.serve_directly !== true + ) { const pattern = typeof route === "string" ? route : route.pattern; const components = pattern.split("/"); - if ( - // = ["route.com"] bare domains are invalid as it would only match exactly that - components.length === 1 || - // = ["route.com",""] as above - (components.length === 2 && components[1] === "") - ) { - invalidRoutes[pattern] ??= []; - invalidRoutes[pattern].push( - `Workers which have static assets must end with a wildcard path. Update the route to end with /*` - ); - // ie it doesn't match exactly "route.com/*" = [route.com, *] - } else if (!(components.length === 2 && components[1] === "*")) { - invalidRoutes[pattern] ??= []; - invalidRoutes[pattern].push( - `Workers which have static assets cannot be routed on a URL which has a path component. Update the route to replace /${components.slice(1).join("/")} with /*` - ); + // If this isn't `domain.com/*` then we're mounting to a path + if (!(components.length === 2 && components[1] === "*")) { + mountedAssetRoutes.push(pattern); } } } @@ -221,6 +214,26 @@ export const validateRoutes = (routes: Route[], hasAssets: boolean) => { .join(`\n\n`) ); } + + if (mountedAssetRoutes.length > 0 && assets?.directory !== undefined) { + const relativeAssetsDir = path.relative(process.cwd(), assets.directory); + + logger.once.warn( + `Warning: The following routes will attempt to serve Assets on a configured path:\n${mountedAssetRoutes + .map((route) => { + const routeNoScheme = route.replace(/https?:\/\//g, ""); + const assetPath = path.join( + relativeAssetsDir, + routeNoScheme.substring(routeNoScheme.indexOf("/")) + ); + return ` • ${route} (Will match assets: ${assetPath})`; + }) + .join("\n")}` + + (assets?.routingConfig.has_user_worker + ? "\n\nRequests not matching an asset will be forwarded to the Worker's code." + : "") + ); + } }; export function renderRoute(route: Route): string { @@ -435,7 +448,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m const routes = props.routes ?? config.routes ?? (config.route ? [config.route] : []) ?? []; - validateRoutes(routes, Boolean(props.assetsOptions)); + validateRoutes(routes, props.assetsOptions); const jsxFactory = props.jsxFactory || config.jsx_factory; const jsxFragment = props.jsxFragment || config.jsx_fragment; diff --git a/packages/wrangler/src/dev.ts b/packages/wrangler/src/dev.ts index 7d48269ec2d3..f2b029641f60 100644 --- a/packages/wrangler/src/dev.ts +++ b/packages/wrangler/src/dev.ts @@ -10,6 +10,7 @@ import { convertCfWorkerInitBindingstoBindings, extractBindingsOfType, } from "./api/startDevWorker/utils"; +import { getAssetsOptions } from "./assets"; import { configFileName, formatConfigSnippet } from "./config"; import { resolveWranglerConfigPath } from "./config/config-helpers"; import { createCommand } from "./core/create-command"; @@ -868,9 +869,7 @@ export async function getHostAndRoutes( routes?: Extract[]; assets?: string; }, - config: Pick & { - dev: Pick; - } + config: Config ) { // TODO: if worker_dev = false and no routes, then error (only for dev) // Compute zone info from the `host` and `route` args and config; @@ -891,7 +890,8 @@ export async function getHostAndRoutes( } }); if (routes) { - validateRoutes(routes, Boolean(args.assets || config.assets)); + const assetOptions = getAssetsOptions({ assets: args.assets }, config); + validateRoutes(routes, assetOptions); } return { host, routes }; } diff --git a/packages/wrangler/src/triggers/deploy.ts b/packages/wrangler/src/triggers/deploy.ts index 64c46ca04bb3..946a9d4c74c7 100644 --- a/packages/wrangler/src/triggers/deploy.ts +++ b/packages/wrangler/src/triggers/deploy.ts @@ -42,7 +42,7 @@ export default async function triggersDeploy( props.routes ?? config.routes ?? (config.route ? [config.route] : []) ?? []; const routesOnly: Array = []; const customDomainsOnly: Array = []; - validateRoutes(routes, Boolean(props.assetsOptions)); + validateRoutes(routes, props.assetsOptions); for (const route of routes) { if (typeof route !== "string" && route.custom_domain) { customDomainsOnly.push(route);