Skip to content

Commit

Permalink
Add serve_directly option to assets configuration (#7316)
Browse files Browse the repository at this point in the history
* Add serve_directly option to assets configuration

* fix assets config type

* Apply default for serve_directly

* Update .changeset/six-coats-rule.md

Co-authored-by: Pete Bacon Darwin <[email protected]>

---------

Co-authored-by: Pete Bacon Darwin <[email protected]>
  • Loading branch information
WillTaylorDev and petebacondarwin authored Nov 25, 2024
1 parent 219109a commit 3cdf0e8
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 2 deletions.
7 changes: 7 additions & 0 deletions .changeset/six-coats-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": minor
---

feat: add `serve_directly` option to Workers with Assets

Users can now specify whether their assets are served directly against HTTP requests or whether these requests always go to the Worker, which can then respond with asset retrieved by its assets binding.
1 change: 1 addition & 0 deletions fixtures/asset-config/html-handling.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe.each(testSuites)("$title", ({ title, suite }) => {
return {
html_handling,
not_found_handling: "none",
serve_directly: true,
};
});
});
Expand Down
3 changes: 2 additions & 1 deletion fixtures/asset-config/redirects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const existsMock = (fileList: Set<string>) => {
};
const BASE_URL = "http://example.com";

describe("[Asset Worker] `test url normalization`", () => {
describe("[Asset Worker] `test location rewrite`", () => {
afterEach(() => {
vi.mocked(getAssetWithMetadataFromKV).mockRestore();
});
Expand All @@ -41,6 +41,7 @@ describe("[Asset Worker] `test url normalization`", () => {
return {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
});
});
Expand Down
3 changes: 2 additions & 1 deletion fixtures/asset-config/url-normalization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const existsMock = (fileList: Set<string>) => {
};
const BASE_URL = "http://example.com";

describe("[Asset Worker] `test redirects`", () => {
describe("[Asset Worker] `test slash normalization`", () => {
afterEach(() => {
vi.mocked(getAssetWithMetadataFromKV).mockRestore();
});
Expand All @@ -41,6 +41,7 @@ describe("[Asset Worker] `test redirects`", () => {
return {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
});
});
Expand Down
1 change: 1 addition & 0 deletions packages/workers-shared/asset-worker/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export const applyConfigurationDefaults = (
return {
html_handling: configuration?.html_handling ?? "auto-trailing-slash",
not_found_handling: configuration?.not_found_handling ?? "none",
serve_directly: configuration?.serve_directly ?? true,
};
};
4 changes: 4 additions & 0 deletions packages/workers-shared/asset-worker/tests/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe("[Asset Worker] `handleRequest`", () => {
const configuration: Required<AssetConfig> = {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
const eTag = "some-etag";
const exists = vi.fn().mockReturnValue(eTag);
Expand All @@ -29,6 +30,7 @@ describe("[Asset Worker] `handleRequest`", () => {
const configuration: Required<AssetConfig> = {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
const eTag = "some-etag";
const exists = vi.fn().mockReturnValue(eTag);
Expand All @@ -53,6 +55,7 @@ describe("[Asset Worker] `handleRequest`", () => {
const configuration: Required<AssetConfig> = {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
const eTag = "some-etag";
const exists = vi.fn().mockReturnValue(eTag);
Expand All @@ -77,6 +80,7 @@ describe("[Asset Worker] `handleRequest`", () => {
const configuration: Required<AssetConfig> = {
html_handling: "none",
not_found_handling: "none",
serve_directly: true,
};
const eTag = "some-etag";
const exists = vi.fn().mockReturnValue(eTag);
Expand Down
1 change: 1 addition & 0 deletions packages/workers-shared/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const AssetConfigSchema = z.object({
not_found_handling: z
.enum(["single-page-application", "404-page", "none"])
.optional(),
serve_directly: z.boolean().optional(),
});

export type RoutingConfig = z.infer<typeof RoutingConfigSchema>;
Expand Down
112 changes: 112 additions & 0 deletions packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4948,6 +4948,118 @@ addEventListener('fetch', event => {});`
await runWrangler("deploy");
});

it("serve_directly correctly overrides default if set to false", async () => {
const assets = [
{ filePath: "file-1.txt", content: "Content of file-1" },
{ filePath: "boop/file-2.txt", content: "Content of file-2" },
];
writeAssets(assets);
writeWorkerSource({ format: "js" });
writeWranglerConfig({
main: "index.js",
compatibility_date: "2024-09-27",
compatibility_flags: ["nodejs_compat"],
assets: {
directory: "assets",
binding: "ASSETS",
html_handling: "none",
not_found_handling: "404-page",
serve_directly: false,
},
});
await mockAUSRequest();
mockSubDomainRequest();
mockUploadWorkerRequest({
expectedAssets: {
jwt: "<<aus-completion-token>>",
config: {
html_handling: "none",
not_found_handling: "404-page",
serve_directly: false,
},
},
expectedBindings: [{ name: "ASSETS", type: "assets" }],
expectedMainModule: "index.js",
expectedCompatibilityDate: "2024-09-27",
expectedCompatibilityFlags: ["nodejs_compat"],
});
await runWrangler("deploy");
});

it("serve_directly omitted when not provided in config", async () => {
const assets = [
{ filePath: "file-1.txt", content: "Content of file-1" },
{ filePath: "boop/file-2.txt", content: "Content of file-2" },
];
writeAssets(assets);
writeWorkerSource({ format: "js" });
writeWranglerConfig({
main: "index.js",
compatibility_date: "2024-09-27",
compatibility_flags: ["nodejs_compat"],
assets: {
directory: "assets",
binding: "ASSETS",
html_handling: "none",
not_found_handling: "404-page",
},
});
await mockAUSRequest();
mockSubDomainRequest();
mockUploadWorkerRequest({
expectedAssets: {
jwt: "<<aus-completion-token>>",
config: {
html_handling: "none",
not_found_handling: "404-page",
},
},
expectedBindings: [{ name: "ASSETS", type: "assets" }],
expectedMainModule: "index.js",
expectedCompatibilityDate: "2024-09-27",
expectedCompatibilityFlags: ["nodejs_compat"],
});
await runWrangler("deploy");
});

it("serve_directly provided if set to true", async () => {
const assets = [
{ filePath: "file-1.txt", content: "Content of file-1" },
{ filePath: "boop/file-2.txt", content: "Content of file-2" },
];
writeAssets(assets);
writeWorkerSource({ format: "js" });
writeWranglerConfig({
main: "index.js",
compatibility_date: "2024-09-27",
compatibility_flags: ["nodejs_compat"],
assets: {
directory: "assets",
binding: "ASSETS",
html_handling: "none",
not_found_handling: "404-page",
serve_directly: true,
},
});
await mockAUSRequest();
mockSubDomainRequest();
mockUploadWorkerRequest({
expectedAssets: {
jwt: "<<aus-completion-token>>",
config: {
html_handling: "none",
not_found_handling: "404-page",
serve_directly: true,
},
},
expectedBindings: [{ name: "ASSETS", type: "assets" }],
expectedMainModule: "index.js",
expectedCompatibilityDate: "2024-09-27",
expectedCompatibilityFlags: ["nodejs_compat"],
});
await runWrangler("deploy");
});

it("should be able to upload an asset-only project", async () => {
const assets = [
{ filePath: "file-1.txt", content: "Content of file-1" },
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ export function processAssetsArg(
const assetConfig = {
html_handling: config.assets?.html_handling,
not_found_handling: config.assets?.not_found_handling,
serve_directly: config.assets?.serve_directly,
};

return {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/config/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ export type Assets = {
| "drop-trailing-slash"
| "none";
not_found_handling?: "single-page-application" | "404-page" | "none";
serve_directly?: boolean;
};

export interface Observability {
Expand Down
10 changes: 10 additions & 0 deletions packages/wrangler/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2158,12 +2158,22 @@ const validateAssetsConfig: ValidatorFn = (diagnostics, field, value) => {
["single-page-application", "404-page", "none"]
) && isValid;

isValid =
validateOptionalProperty(
diagnostics,
field,
"serve_directly",
(value as Assets).serve_directly,
"boolean"
) && isValid;

isValid =
validateAdditionalProperties(diagnostics, field, Object.keys(value), [
"directory",
"binding",
"html_handling",
"not_found_handling",
"serve_directly",
]) && isValid;

return isValid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
const assetConfig = {
html_handling: assets?.assetConfig?.html_handling,
not_found_handling: assets?.assetConfig?.not_found_handling,
serve_directly: assets?.assetConfig?.serve_directly,
};

// short circuit if static assets upload only
Expand Down

0 comments on commit 3cdf0e8

Please sign in to comment.