diff --git a/apps/server/src/projectFaviconRoute.test.ts b/apps/server/src/projectFaviconRoute.test.ts index a346e513eb..03d9893fff 100644 --- a/apps/server/src/projectFaviconRoute.test.ts +++ b/apps/server/src/projectFaviconRoute.test.ts @@ -117,6 +117,25 @@ describe("tryHandleProjectFaviconRequest", () => { }); }); + it("serves jpeg icons discovered from source metadata with the correct content type", async () => { + const projectDir = makeTempDir("t3code-favicon-route-jpeg-"); + const iconPath = path.join(projectDir, "public", "brand", "logo.jpeg"); + fs.mkdirSync(path.dirname(iconPath), { recursive: true }); + fs.writeFileSync( + path.join(projectDir, "index.html"), + '', + ); + fs.writeFileSync(iconPath, "jpeg-favicon", "utf8"); + + await withRouteServer(async (baseUrl) => { + const pathname = `/api/project-favicon?cwd=${encodeURIComponent(projectDir)}`; + const response = await request(baseUrl, pathname); + expect(response.statusCode).toBe(200); + expect(response.contentType).toContain("image/jpeg"); + expect(response.body).toBe("jpeg-favicon"); + }); + }); + it("resolves icon link when href appears before rel in HTML", async () => { const projectDir = makeTempDir("t3code-favicon-route-html-order-"); const iconPath = path.join(projectDir, "public", "brand", "logo.svg"); diff --git a/apps/server/src/projectFaviconRoute.ts b/apps/server/src/projectFaviconRoute.ts index cf234ad894..6fd1b3b2e7 100644 --- a/apps/server/src/projectFaviconRoute.ts +++ b/apps/server/src/projectFaviconRoute.ts @@ -1,13 +1,7 @@ import fs from "node:fs"; import http from "node:http"; import path from "node:path"; - -const FAVICON_MIME_TYPES: Record = { - ".png": "image/png", - ".jpg": "image/jpeg", - ".svg": "image/svg+xml", - ".ico": "image/x-icon", -}; +import Mime from "@effect/platform-node/Mime"; const FALLBACK_FAVICON_SVG = ``; @@ -71,8 +65,7 @@ function isPathWithinProject(projectCwd: string, candidatePath: string): boolean } function serveFaviconFile(filePath: string, res: http.ServerResponse): void { - const ext = path.extname(filePath).toLowerCase(); - const contentType = FAVICON_MIME_TYPES[ext] ?? "application/octet-stream"; + const contentType = Mime.getType(filePath) ?? "application/octet-stream"; fs.readFile(filePath, (readErr, data) => { if (readErr) { res.writeHead(500, { "Content-Type": "text/plain" });