fix(POSTV1-02): 修复便携网页静态资源类型
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run

This commit is contained in:
suyx
2026-08-05 14:07:42 +08:00
parent a7f62adad4
commit f7cac5dabf
2 changed files with 33 additions and 2 deletions
+20 -1
View File
@@ -1,6 +1,6 @@
import { randomBytes, randomUUID } from "node:crypto"; import { randomBytes, randomUUID } from "node:crypto";
import { createReadStream, existsSync, readFileSync } from "node:fs"; import { createReadStream, existsSync, readFileSync } from "node:fs";
import { resolve } from "node:path"; import { extname, resolve } from "node:path";
import { import {
AccountDeletionCompleteRequestSchema, AccountDeletionCompleteRequestSchema,
@@ -218,6 +218,24 @@ import type { ManagedStorage } from "./managed-storage.js";
import { PrivateContentError, PrivateContentService } from "./private-content.js"; import { PrivateContentError, PrivateContentService } from "./private-content.js";
import { assertSafeAdminDiagnostics, assertSafeAdminServicesStorage } from "./admin-state.js"; import { assertSafeAdminDiagnostics, assertSafeAdminServicesStorage } from "./admin-state.js";
const productAssetContentTypes: Readonly<Record<string, string>> = {
".css": "text/css; charset=utf-8",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".js": "text/javascript; charset=utf-8",
".json": "application/json; charset=utf-8",
".mjs": "text/javascript; charset=utf-8",
".png": "image/png",
".svg": "image/svg+xml",
".webp": "image/webp",
".woff": "font/woff",
".woff2": "font/woff2",
};
function productAssetContentType(path: string) {
return productAssetContentTypes[extname(path).toLowerCase()] ?? "application/octet-stream";
}
const defaultBootstrap: BootstrapResponse = { const defaultBootstrap: BootstrapResponse = {
app_version: "0.0.0", app_version: "0.0.0",
dependencies: [], dependencies: [],
@@ -923,6 +941,7 @@ export async function createApp(options: CreateAppOptions = {}) {
const relativePath = decodeURIComponent(request.url.split("?", 1)[0]!.slice("/assets/".length)); const relativePath = decodeURIComponent(request.url.split("?", 1)[0]!.slice("/assets/".length));
const assetPath = resolve(productWebRoot, "assets", relativePath); const assetPath = resolve(productWebRoot, "assets", relativePath);
if (!assetPath.startsWith(resolve(productWebRoot, "assets")) || !existsSync(assetPath)) return reply.code(404).send(); if (!assetPath.startsWith(resolve(productWebRoot, "assets")) || !existsSync(assetPath)) return reply.code(404).send();
reply.type(productAssetContentType(assetPath));
return reply.send(readFileSync(assetPath)); return reply.send(readFileSync(assetPath));
}); });
app.get("/support-gate.css", { schema: { hide: true } }, async (_request, reply) => { app.get("/support-gate.css", { schema: { hide: true } }, async (_request, reply) => {
+13 -1
View File
@@ -138,7 +138,19 @@ test("portable package serves the product and keeps SQLite data across API resta
assert.ok(cookie); assert.ok(cookie);
const page = await fetch(`http://127.0.0.1:${port}/app`, { headers: { host: `127.0.0.1:${port}`, cookie, "sec-ch-ua": '"Google Chrome";v="150"' } }); const page = await fetch(`http://127.0.0.1:${port}/app`, { headers: { host: `127.0.0.1:${port}`, cookie, "sec-ch-ua": '"Google Chrome";v="150"' } });
assert.equal(page.status, 200); assert.equal(page.status, 200);
assert.match(await page.text(), /<div id="root"><\/div>/); const pageHtml = await page.text();
assert.match(pageHtml, /<div id="root"><\/div>/);
const scriptPath = pageHtml.match(/<script[^>]+src="([^"]+)"/)?.[1];
const stylesheetPath = pageHtml.match(/<link[^>]+href="([^"]+)"/)?.[1];
assert.ok(scriptPath);
assert.ok(stylesheetPath);
const assetHeaders = { host: `127.0.0.1:${port}`, cookie, "sec-ch-ua": '"Google Chrome";v="150"' };
const script = await fetch(`http://127.0.0.1:${port}${scriptPath}`, { headers: assetHeaders });
const stylesheet = await fetch(`http://127.0.0.1:${port}${stylesheetPath}`, { headers: assetHeaders });
assert.equal(script.status, 200);
assert.match(script.headers.get("content-type") ?? "", /^(?:application|text)\/javascript\b/);
assert.equal(stylesheet.status, 200);
assert.match(stylesheet.headers.get("content-type") ?? "", /^text\/css\b/);
assert.ok(existsSync(join(dataRoot, "db", "dada.sqlite3"))); assert.ok(existsSync(join(dataRoot, "db", "dada.sqlite3")));
await verifyWorkerStartup(configPath); await verifyWorkerStartup(configPath);
} finally { } finally {