diff --git a/config/pikaoa.yaml b/config/pikaoa.yaml index e1fd2e23..b5e080b0 100644 --- a/config/pikaoa.yaml +++ b/config/pikaoa.yaml @@ -357,6 +357,9 @@ publicEdge: containerName: pikaoa-edge httpPort: 80 httpsPort: 443 + protocols: + - h1 + - h2 responseHeaderTimeoutSeconds: 60 sites: production: diff --git a/scripts/src/pikaoa-public-edge.ts b/scripts/src/pikaoa-public-edge.ts index b3f94561..3a2e9674 100644 --- a/scripts/src/pikaoa-public-edge.ts +++ b/scripts/src/pikaoa-public-edge.ts @@ -37,6 +37,7 @@ interface EdgeSpec { containerName: string; httpPort: number; httpsPort: number; + protocols: string[]; responseHeaderTimeoutSeconds: number; }; sites: EdgeSite[]; @@ -132,6 +133,7 @@ function readSpec(path: string): EdgeSpec { containerName: string(caddy.containerName, "publicEdge.caddy.containerName"), httpPort: integer(caddy.httpPort, "publicEdge.caddy.httpPort"), httpsPort: integer(caddy.httpsPort, "publicEdge.caddy.httpsPort"), + protocols: stringList(caddy.protocols, "publicEdge.caddy.protocols"), responseHeaderTimeoutSeconds: integer(caddy.responseHeaderTimeoutSeconds, "publicEdge.caddy.responseHeaderTimeoutSeconds"), }, sites: Object.entries(sites).map(([id, value]) => { @@ -329,7 +331,8 @@ PY } function renderCaddyfile(spec: EdgeSpec): string { - return spec.sites.map((site) => `${site.hostname} {\n reverse_proxy ${site.upstream} {\n transport http {\n response_header_timeout ${spec.caddy.responseHeaderTimeoutSeconds}s\n }\n }\n}`).join("\n\n") + "\n"; + const global = `{\n servers {\n protocols ${spec.caddy.protocols.join(" ")}\n }\n}\n`; + return global + spec.sites.map((site) => `${site.hostname} {\n reverse_proxy ${site.upstream} {\n transport http {\n response_header_timeout ${spec.caddy.responseHeaderTimeoutSeconds}s\n }\n }\n}`).join("\n\n") + "\n"; } function renderCompose(spec: EdgeSpec): string { @@ -356,6 +359,11 @@ function boolean(value: unknown, path: string): boolean { return value; } +function stringList(value: unknown, path: string): string[] { + if (!Array.isArray(value) || value.length === 0) throw inputError(`${path} 必须是非空字符串数组`, "invalid-config", path); + return value.map((item, index) => string(item, `${path}[${index}]`)); +} + function hostname(value: unknown, path: string): string { const result = string(value, path); if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/u.test(result)) throw inputError(`${path} 不是合法 hostname`, "invalid-config", path);