You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

65 lines
2.2 KiB

import path from "node:path";
function trimSlashes(input: string): string {
return input.trim().replace(/^\/+|\/+$/g, "");
}
function hasParentSegment(input: string): boolean {
return input
.split("/")
.map((part) => part.trim())
.some((part) => part === "..");
}
/** 允许相对项目根或绝对路径;禁止含 `..` 的路径片段(防止配置逃逸)。 */
function ensureConfigurableDir(input: string, fallback: string, envName: string): string {
const raw = input.trim();
if (!raw) {
return fallback;
}
const normalized = path.normalize(raw);
const segments = normalized.split(path.sep);
if (segments.some((part) => part === "..")) {
throw new Error(`${envName} must not contain ".." path segments`);
}
return normalized;
}
function ensureSafeSubdir(input: string, fallback: string, envName: string): string {
const value = trimSlashes(input);
if (!value) {
return fallback;
}
if (hasParentSegment(value)) {
throw new Error(`${envName} must not contain ".." segments`);
}
return value;
}
/** 静态资源 URL 前缀固定为 `/static`,不允许通过环境变量覆写。 */
export const STATIC_PUBLIC_PREFIX = "/static";
/** 静态资源根目录(相对项目根或绝对路径),默认 `static` */
export const STATIC_DIR = ensureConfigurableDir(process.env.STATIC_DIR ?? "static", "static", "STATIC_DIR");
/** 媒体上传子目录(相对 STATIC_DIR),默认 `upload` */
export const UPLOAD_SUBDIR = ensureSafeSubdir(
process.env.UPLOAD_SUBDIR ?? "upload",
"upload",
"UPLOAD_SUBDIR",
);
/** 媒体上传目录(与 STATIC_DIR 同为相对或绝对),默认 `static/upload` */
export const RELATIVE_ASSETS_DIR = path.join(STATIC_DIR, UPLOAD_SUBDIR);
/** 与 `media` 返回及静态路径一致,无前导 host */
export const POST_MEDIA_PUBLIC_PREFIX = `${STATIC_PUBLIC_PREFIX}/${UPLOAD_SUBDIR}/`;
/** 允许的上传文件 MIME 类型 */
export const ALLOWED_MIME_TYPES = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'] as const;
/** 单文件最大大小(字节) */
export const MAX_FILE_SIZE = 5 * 1024 * 1024;
/** 单次上传最大文件数 */
export const MAX_FILE_COUNT = 10;