import { Environment } from '../environment'; import { HTTPServiceRouteParam } from '../env/type'; /** 网关路由配置(cloudbaserc.json gateway.routes[]) */ export interface IGatewayRoute { /** 绑定的自定义域名。配置时自动绑定(需 certId);不填则使用环境 HTTP 访问服务的默认域名(如 {envId}-{uin}.{region}.app.tcloudbase.com) */ domain?: string; /** SSL 证书 ID(绑定自定义域名时需要,可先通过 SSL 控制台/API 获取) */ certId?: string; /** 域名接入方式(默认 DIRECT 直接接入):DIRECT/CDN(接入云开发 CDN)/CUSTOM(自定义接入,需 customCname)/EO(接入云开发 EdgeOne) */ accessType?: 'DIRECT' | 'CDN' | 'CUSTOM' | 'EO'; /** 自定义接入时配置的 CNAME 记录(accessType=CUSTOM 时必填) */ customCname?: string; /** 域名协议(默认 HTTP_AND_HTTPS):HTTP/HTTPS/HTTP_AND_HTTPS/HTTP_TO_HTTPS/HTTPS_TO_HTTP */ protocol?: 'HTTP' | 'HTTPS' | 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP'; /** 域名启用状态(默认 true) */ enable?: boolean; /** 路径,如 /api 或 /web */ path: string; /** 目标:function: 或 hosting: */ target: string; /** 是否开启路径透传(默认 false) */ enablePathTransmission?: boolean; /** 是否开启身份认证(默认 false) */ enableAuth?: boolean; /** 路径重写配置(prefix/staticStorePrefix 只能填一个)。hosting 路由未配置时自动生成 { Prefix: deployPath };显式配置时透传且不校验 hosting 名称(可引用已部署实例) */ pathRewrite?: { prefix?: string; staticStorePrefix?: string; }; /** QPS 限频策略 */ qpsPolicy?: { /** QPS 限额总量(每秒请求次数),100-100000 */ qpsTotal?: number; /** 客户端限频配置 */ qpsPerClient?: { limitBy?: 'UserID' | 'ClientIP'; limitValue?: number; }; }; } /** 网关部署结果 */ export interface IGatewayDeployResult { domain: string; routes: Array<{ path: string; target: string; url: string; }>; } /** * 网关声明式部署器 * 支持 function:(SCF 云函数)与 hosting:(STATIC_STORE 静态托管)两种目标 */ export declare class GatewayDeployer { private environment; constructor(environment: Environment); /** * 部署网关路由 * * 域名规则: * - 未配置 domain → 使用环境 HTTP 访问服务的**默认域名**(Domains 中 IsDefault=true,如 {envId}-{uin}.{region}.app.tcloudbase.com),直接创建路由 * - 配置了 domain(自定义域名)→ **先自动绑定自定义域名**(bindCustomDomain,需 certId),再创建路由 * 不同域名的路由分组创建。 */ deploy(options: { routes: IGatewayRoute[]; envId: string; /** hosting 配置列表(用于为 hosting: 路由生成 PathRewrite.Prefix 部署路径) */ hostings?: Array<{ name?: string; deployPath?: string; }>; }): Promise; /** * 解析路由配置:校验 target 格式并映射为 HTTPServiceRouteParam * * 对齐 tcb routes add 的底层校验(src/commands/routes/add.ts): * - path 必须以 / 开头,每段只含字母/数字/./_/-,50 字符内,不支持通配符 * * - 静态托管(STATIC_STORE)上游名固定为 staticstore,且只支持一级路径 */ parseRoute(route: IGatewayRoute): HTTPServiceRouteParam; /** * 计算网关路由部署计划(dry-run):每个路由 create/update/skip + 变更字段明细 * * 判定逻辑与 deploy() 完全一致:云端不存在的 path → create; * 已存在但显式配置不一致 → update(带 changes);一致 → skip。 */ planRoutes(options: { routes: IGatewayRoute[]; envId: string; hostings?: Array<{ name?: string; deployPath?: string; }>; }): Promise; }>>; /** * 查询指定域名下已存在的路由(幂等收敛用),返回 Map * * 匹配策略(优先级从高到低): * 1. 用 Filters 精确查询目标域名:DescribeHTTPServiceRoute 不带 Filters 时返回的 Domains * 列表可能不完整(如 lowcode 环境 TotalCount=67 但 Domains 只返回部分,HTTPSERVICE 的 * .app.tcloudbase.com 域名缺失),导致云端已有路由查不到被误判为 create * 2. 降级:不带 Filters 全量查询,按域名归一化匹配(去协议/尾斜杠/转小写) * 若目标域名找不到则返回空(保留 domain 维度,避免把其他域名同 path 误判为已存在) */ private getExistingRoutes; /** * 域名归一化:去协议、去尾斜杠、转小写(用于幂等收敛的域名匹配) */ private normalizeDomain; /** * 判断错误是否属于「路由已存在/已占用」类(幂等降级专用) * * 只匹配明确的重复/占用语义(code 含 AlreadyExists/Duplicate/ResourceInUse/Conflict, * 或 message 含 already exists),并显式排除否定语义(not exists/not found 等), * 避免把「环境/资源不存在」等真实失败误判为「已存在」而被静默跳过 */ private isAlreadyExistsError; /** * 判断期望路由与云端已存在路由是否一致 * * 只比较**用户显式声明的字段**(enableAuth/enablePathTransmission 显式配置才比较; * QPSPolicy/PathRewrite 本地有值才比较),避免覆盖控制台单独配置的字段。 */ private routesEqual; /** * 构建 modifyHttpServiceRoute 的路由参数:只包含基础字段 + 用户显式声明的配置字段 */ private buildModifyParam; private deepEqual; /** * 自动绑定自定义域名(幂等,支持证书更新) * * certId 解析优先级: * 1. 显式配置的 certId 优先(未配置时按域名自动匹配已签发证书) * 2. 域名已绑定 + 未显式 certId 或与云端一致 → 跳过绑定(幂等) * 3. 域名已绑定 + 显式 certId 与云端不一致 → 重新绑定(更新证书) * 4. 未绑定且无法确定 certId → 明确报错并给出操作指引 */ private ensureDomainBound; /** * 查询当前环境已绑定的自定义域名列表(含证书 ID,用于幂等跳过与证书更新判断) */ private getBoundDomains; /** * 按域名自动匹配 SSL 证书 ID(腾讯云 ssl.DescribeCertificates) * * 匹配规则(按返回顺序取第一个): * - 证书状态为已签发(Status === 1) * - 证书主域名(Domain)或关联域名(SubjectAltName)包含目标域名 * - 证书未过期(CertEndTime 晚于当前时间) * 查询失败或无匹配返回 null(由调用方给出明确报错) */ private resolveCertIdByDomain; /** * 解析路由(含异步函数类型判断 + hosting 路径重写) * * - function 目标:查询函数详情,HTTP 类型函数 → WEB_SCF(Web 云函数),普通函数 → SCF。 * 与 tcb fn deploy 部署 HTTP 函数后控制台创建路由的行为一致(控制台请求中 UpstreamResourceType=WEB_SCF)。 * - hosting 目标:自动生成 PathRewrite.Prefix = 对应 hosting 配置的 deployPath(控制台行为:静态托管路由必带 * PathRewrite.Prefix,将 /路由 前缀重写到静态托管的实际部署路径,否则请求会打到存储根路径导致 404)。 */ private parseRouteWithType; /** * 映射用户 pathRewrite(camelCase)为 API 格式 HTTPServicePathRewrite(PascalCase) */ private mapPathRewrite; /** * 生成路由变更字段明细(与 routesEqual 的判定字段一致) */ private routeChanges; /** * 解析环境 HTTP 访问服务的默认域名 * * 域名优先级: * 1. Domains 列表中 DomainType=HTTPSERVICE 且 IsDefault=true 的域名(HTTP 网关默认域名) * —— 注意:AI_AGENT/CBR 等类型的域名(如 agt-xxx.agent.tcloudbase.com)也可能 IsDefault=true, * 但它们不是 HTTP 网关默认域名,必须结合 DomainType 过滤 * 2. 通过 DescribeEnvInfo 构造的默认域名 `{envId}-{uin}.{region}.app.tcloudbase.com`(兜底,覆盖 Domains 列表为空的场景——实测部分环境下 Domains 列表为空但默认域名仍存在) * 3. 首个 DomainType=HTTPSERVICE 的域名 * 4. OriginDomain —— 回源域名(供自定义 CDN/WAF 回源使用,非对外访问地址),仅作最后兜底 * 查询失败或域名缺失时**明确报错**,不使用猜测的兜底域名(避免 INVALID_HOST)。 */ private resolveDomain; }