Skip to content

Commit

Permalink
Omit Content-Type header for files of unknown extension in Workers As…
Browse files Browse the repository at this point in the history
…sets (#8247)
  • Loading branch information
GregBrimble authored Feb 25, 2025
1 parent c62973b commit a9a4c33
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 17 deletions.
7 changes: 7 additions & 0 deletions .changeset/beige-crews-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-shared": minor
"miniflare": minor
"wrangler": minor
---

feat: Omits Content-Type header for files of an unknown extension in Workers Assets
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I'm a narcissist.
4 changes: 4 additions & 0 deletions fixtures/workers-with-assets/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ describe("[Workers + Assets] dynamic site", () => {
response = await fetch(`http://${ip}:${port}/lava-lamps.jpg`);
expect(response.status).toBe(200);
expect(response.headers.get("Content-Type")).toBe("image/jpeg");

response = await fetch(`http://${ip}:${port}/totallyinvalidextension.greg`);
expect(response.status).toBe(200);
expect(response.headers.has("Content-Type")).toBeFalsy();
});

it("should return 405 for non-GET or HEAD requests on routes where assets exist", async ({
Expand Down
2 changes: 1 addition & 1 deletion packages/miniflare/src/plugins/assets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export type ManifestEntry = {
};

export type AssetReverseMap = {
[pathHash: string]: { filePath: string; contentType: string };
[pathHash: string]: { filePath: string; contentType: string | null };
};

/**
Expand Down
10 changes: 6 additions & 4 deletions packages/miniflare/src/workers/assets/assets-kv.worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ export default <ExportedHandler<Env>>{
);
const newResponse = new Response(response.body, response);
// ensure the runtime will return the metadata we need
newResponse.headers.append(
"cf-kv-metadata",
`{"contentType": "${contentType}"}`
);
if (contentType !== null) {
newResponse.headers.append(
"cf-kv-metadata",
`{"contentType": "${contentType}"}`
);
}
return newResponse;
},
};
16 changes: 9 additions & 7 deletions packages/workers-shared/asset-worker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,10 @@ export default class extends WorkerEntrypoint<Env> {
return true;
}

async unstable_getByETag(
eTag: string
): Promise<{ readableStream: ReadableStream; contentType: string }> {
async unstable_getByETag(eTag: string): Promise<{
readableStream: ReadableStream;
contentType: string | undefined;
}> {
const asset = await getAssetWithMetadataFromKV(
this.env.ASSETS_KV_NAMESPACE,
eTag
Expand All @@ -203,13 +204,14 @@ export default class extends WorkerEntrypoint<Env> {

return {
readableStream: asset.value,
contentType: asset.metadata?.contentType ?? "application/octet-stream",
contentType: asset.metadata?.contentType,
};
}

async unstable_getByPathname(
pathname: string
): Promise<{ readableStream: ReadableStream; contentType: string } | null> {
async unstable_getByPathname(pathname: string): Promise<{
readableStream: ReadableStream;
contentType: string | undefined;
} | null> {
const eTag = await this.unstable_exists(pathname);
if (!eTag) {
return null;
Expand Down
7 changes: 5 additions & 2 deletions packages/workers-shared/asset-worker/src/utils/headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import { CACHE_CONTROL_BROWSER } from "../constants";
*/
export function getHeaders(
eTag: string,
contentType: string,
contentType: string | undefined,
request: Request
) {
const headers = new Headers({
"Content-Type": contentType,
ETag: `"${eTag}"`,
});

if (contentType !== undefined) {
headers.append("Content-Type", contentType);
}

if (isCacheable(request)) {
headers.append("Cache-Control", CACHE_CONTROL_BROWSER);
}
Expand Down
8 changes: 6 additions & 2 deletions packages/workers-shared/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ export const normalizeFilePath = (relativeFilepath: string) => {
};

export const getContentType = (absFilePath: string) => {
let contentType = getType(absFilePath) || "application/octet-stream";
if (contentType.startsWith("text/") && !contentType.includes("charset")) {
let contentType = getType(absFilePath);
if (
contentType &&
contentType.startsWith("text/") &&
!contentType.includes("charset")
) {
contentType = `${contentType}; charset=utf-8`;
}
return contentType;
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const syncAssets = async (
[(await readFile(absFilePath)).toString("base64")],
manifestEntry[1].hash,
{
type: getContentType(absFilePath),
type: getContentType(absFilePath) || "application/octet-stream",
}
),
manifestEntry[1].hash
Expand Down

0 comments on commit a9a4c33

Please sign in to comment.