feat: add hwlab opencode public proxy config
This commit is contained in:
@@ -282,6 +282,13 @@ export interface HwlabRuntimePublicExposureFrpcProxySpec {
|
||||
readonly remotePort: number;
|
||||
}
|
||||
|
||||
export interface HwlabRuntimePublicExposureFrpcExtraProxySpec extends HwlabRuntimePublicExposureFrpcProxySpec {
|
||||
readonly id: string;
|
||||
readonly hostname?: string;
|
||||
readonly publicBaseUrl?: string;
|
||||
readonly cloudWebEnvName?: string;
|
||||
}
|
||||
|
||||
export interface HwlabRuntimePublicExposureSpec {
|
||||
readonly enabled: boolean;
|
||||
readonly mode: "pk01-caddy-frp";
|
||||
@@ -303,6 +310,7 @@ export interface HwlabRuntimePublicExposureSpec {
|
||||
readonly responseHeaderTimeoutSeconds: number;
|
||||
readonly webProxy: HwlabRuntimePublicExposureFrpcProxySpec;
|
||||
readonly apiProxy: HwlabRuntimePublicExposureFrpcProxySpec;
|
||||
readonly extraProxies: readonly HwlabRuntimePublicExposureFrpcExtraProxySpec[];
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeBootstrapAdminSpec {
|
||||
@@ -1207,6 +1215,32 @@ function publicExposureProxyConfig(value: unknown, path: string): HwlabRuntimePu
|
||||
};
|
||||
}
|
||||
|
||||
function publicExposureExtraProxyConfig(value: unknown, path: string): HwlabRuntimePublicExposureFrpcExtraProxySpec {
|
||||
const raw = asRecord(value, path);
|
||||
const publicBaseUrl = optionalStringField(raw, "publicBaseUrl", path)?.replace(/\/+$/u, "");
|
||||
const hostname = optionalStringField(raw, "hostname", path);
|
||||
if (publicBaseUrl !== undefined) {
|
||||
validatePublicExposureOrigin(publicBaseUrl, `${path}.publicBaseUrl`);
|
||||
if (hostname !== undefined && new URL(publicBaseUrl).hostname !== hostname) throw new Error(`${path}.publicBaseUrl hostname must match ${path}.hostname`);
|
||||
}
|
||||
const cloudWebEnvName = optionalStringField(raw, "cloudWebEnvName", path);
|
||||
if (cloudWebEnvName !== undefined && !/^HWLAB_CLOUD_WEB_[A-Z0-9_]+$/u.test(cloudWebEnvName)) throw new Error(`${path}.cloudWebEnvName must be a HWLAB_CLOUD_WEB_* env name`);
|
||||
if (cloudWebEnvName !== undefined && publicBaseUrl === undefined) throw new Error(`${path}.cloudWebEnvName requires ${path}.publicBaseUrl`);
|
||||
return {
|
||||
id: stringField(raw, "id", path),
|
||||
...publicExposureProxyConfig(value, path),
|
||||
...(hostname === undefined ? {} : { hostname }),
|
||||
...(publicBaseUrl === undefined ? {} : { publicBaseUrl }),
|
||||
...(cloudWebEnvName === undefined ? {} : { cloudWebEnvName }),
|
||||
};
|
||||
}
|
||||
|
||||
function publicExposureExtraProxiesConfig(value: unknown, path: string): HwlabRuntimePublicExposureFrpcExtraProxySpec[] {
|
||||
if (value === undefined) return [];
|
||||
if (!Array.isArray(value)) throw new Error(`${path} must be an array`);
|
||||
return value.map((item, index) => publicExposureExtraProxyConfig(item, `${path}[${index}]`));
|
||||
}
|
||||
|
||||
function publicExposureConfig(value: unknown, path: string): HwlabRuntimePublicExposureSpec | null {
|
||||
if (value === undefined) return null;
|
||||
const raw = asRecord(value, path);
|
||||
@@ -1237,9 +1271,21 @@ function publicExposureConfig(value: unknown, path: string): HwlabRuntimePublicE
|
||||
responseHeaderTimeoutSeconds: numberField(caddy, "responseHeaderTimeoutSeconds", `${path}.caddy`),
|
||||
webProxy: publicExposureProxyConfig(frpc.webProxy, `${path}.frpc.webProxy`),
|
||||
apiProxy: publicExposureProxyConfig(frpc.apiProxy, `${path}.frpc.apiProxy`),
|
||||
extraProxies: publicExposureExtraProxiesConfig(frpc.extraProxies, `${path}.frpc.extraProxies`),
|
||||
};
|
||||
}
|
||||
|
||||
function validatePublicExposureOrigin(publicBaseUrl: string, path: string): void {
|
||||
try {
|
||||
const parsed = new URL(publicBaseUrl);
|
||||
if (parsed.protocol !== "https:") throw new Error("must use https");
|
||||
if (parsed.pathname !== "/" || parsed.search.length > 0 || parsed.hash.length > 0) throw new Error("must point to the public origin root");
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
throw new Error(`${path} must be an https origin root URL: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function observabilityConfig(value: unknown, path: string): HwlabRuntimeObservabilitySpec {
|
||||
const raw = asRecord(value, path);
|
||||
const recordingRules = observabilityRecordingRulesConfig(raw.recordingRules, `${path}.recordingRules`);
|
||||
|
||||
Reference in New Issue
Block a user