编程语言编译器云原生语言运行时【免费下载链接】wingA programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡项目地址https://gitcode.com/gh_mirrors/wi/wing点击查看免费下载cloud.Api是 Wing 标准库cloud命名空间中用于创建云端 HTTP 端点的内置资源它把路径 HTTP 方法 inflight 事件处理函数这一路由模型统一封装成跨云抽象。本篇指南以 cloud/api.md 的官方 API 参考为骨架结合仓库中 SDK 源码packages/winglang/sdk/src/cloud/api.ts与模拟器、AWS 实现带读者从零构建一个完整的 REST API理解路由注册、请求/响应对象、CORS 配置并深入剖析 OpenAPI Spec 生成、路径校验等底层原理最终掌握在 Wing 中编写可移植 HTTP 服务的完整实战方案。一、cloud.Api是什么用一条语句定义 HTTP 端点cloud.Api资源代表一组可以由互联网客户端调用的 HTTP 端点集合。在 Wing 的应用模型中API 通常充当应用的前门客户端通过它访问后端服务中的数据、业务逻辑或功能。它的核心建模方式是端点endpoint 一组路由route每个路由绑定一个事件处理函数event handler function。一条路由由两部分组成一个路径path例如/users/:userid其中:userid是路径参数一组 HTTP 方法method例如GET、POST或DELETE。当客户端调用某条路由时对应的事件处理函数一个 inflight 闭包就会执行。从 cloud/api.ts 中的抽象基类 可以看出Api继承自Resource构造函数接受可选的ApiProps目前仅含 CORS 相关配置并在构造树节点时设置标题为Api、描述为A REST API endpoint。这种设计带来的直接收益是开发者只需要用语言层面的api.get(...)、api.post(...)等 preflight 方法声明路由Wing 编译器与 SDK 会负责把路由翻译成目标云平台的产物AWS API Gateway、模拟器中的 Express 服务器等无需关心各平台底层差异。二、快速上手一个完整的 REST API 示例原文档给出了一个使用cloud.Api、cloud.Bucket与cloud.Counter协同实现的员工管理 REST API。以下代码完整复现并逐步解读bring cloud; let api new cloud.Api(); // Used for generating unique id let counter new cloud.Counter(); // our employee data let store new cloud.Bucket(); api.get(/employees, inflight (request: cloud.ApiRequest): cloud.ApiResponse { let result MutJson []; let var i 0; for employee in store.list() { result.setAt(i, employee); i i 1; } return cloud.ApiResponse { status: 200, body: Json.stringify(result) }; }); api.get(/employees/:id, inflight (request: cloud.ApiRequest): cloud.ApiResponse { let employee store.get(request.vars.get(id)); return cloud.ApiResponse { status: 200, body: Json.stringify(employee) }; }); api.post(/employees, inflight (request: cloud.ApiRequest): cloud.ApiResponse { if let body request.body { let employeeData Json.parse(body); let id {counter.inc()}; store.putJson(id, employeeData); return cloud.ApiResponse { status: 201, body: id }; } }); api.put(/employees/:id, inflight (request: cloud.ApiRequest): cloud.ApiResponse { if let body request.body { let employeeData Json.parse(body); let id request.vars.get(id); store.putJson(id, employeeData); return cloud.ApiResponse { status: 200, body: Json.stringify(employeeData) }; } }); api.delete(/employees/:id, inflight (request: cloud.ApiRequest): cloud.ApiResponse { let id request.vars.get(id); store.delete(id); return cloud.ApiResponse { status: 204 }; });逐段要点GET 列表api.get(/employees, ...)遍历store.list()返回的键集合把结果组装进MutJson数组最后以status: 200和Json.stringify(result)返回 JSON 字符串。注意这里返回体必须是字符串因此所有结构化数据都通过Json.stringify序列化。GET 单个路径参数通过request.vars.get(id)读取vars是MutMapstr由路由中:id部分注入随后从 Bucket 取出对象并返回。POST 创建从request.body读取请求体用Json.parse(body)解析为 JSON借助counter.inc()生成唯一自增 idstore.putJson(id, employeeData)写入存储最后返回201与 id 字符串。PUT 更新从request.vars.get(id)定位资源覆盖写入后返回200与新数据。DELETE 删除按 id 删除对象返回204 No Content无响应体。从源码看这条调用链如何工作在模拟器sim实现中target-sim/api.ts 的addEndpoint是路由注册的统一入口先调用_validatePath(path)校验路径合法性调用_addToSpec(...)把路由登记到内部的 OpenAPI Spec 中通过createOrGetFunction将 inflight 处理函数包装成Function资源并建立EventMapping事件映射向Policy添加一条FunctionInflightMethods.INVOKE权限语句确保 API 有权调用处理函数。也就是说每注册一条路由SDK 都会在后台为你创建函数资源 事件订阅 权限策略这整套基础设施这正是 Wing基础设施即代码、代码即基础设施统一模型的体现。三、深入理解请求对象与响应对象ApiRequestinflight 处理函数的入参ApiRequest是传入 inflight handler 的请求形状字段如下与 源码定义 一致字段类型必填说明methodHttpMethod是请求的 HTTP 方法pathstr是请求路径queryMutMapstr是查询字符串query string键值varsMutMapstr是路径变量path variables如:id匹配到的值bodystr否请求体headersMutMapstr否请求头在模拟器中这个对象由 api.inflight.ts 的transformRequest从 Express 的req转换而来headers与query都经过sanitizeParamLikeObject处理把多值参数用逗号拼接成单值见 cloud/api.tsmethod通过parseHttpMethod转成枚举vars直接取 Express 的req.params。ApiResponseinflight 处理函数的返回值ApiResponse是 inflight handler 的响应形状字段类型默认值说明statusnum200响应状态码bodystr无 body响应体headersMutMapstr{}响应头源码中定义了DEFAULT_RESPONSE_STATUS 200见 cloud/api.ts。模拟器在收到 handler 返回后按此逻辑处理api.inflight.ts状态码缺省用 200逐项设置响应头body存在则res.send(body)否则res.end()。处理函数契约IApiEndpointHandler协议任何可以传给api.get(...)等 preflight 方法的处理函数都实现了IApiEndpointHandler协议源码它是一个带有 inflighthandle(request: ApiRequest): ApiResponse?方法的资源。这意味着你既可以传一个匿名 inflight 闭包也可以传一个实现了该接口的自定义 inflight 类——SDK 对两者一视同仁。四、目标平台实现细节Target-specific Detailscloud.Api是可移植抽象同样的 Wing 代码可以编译到不同平台底层产物各不相同模拟器sim模拟实现基于 Node.js 的Express框架。api.inflight.ts 中可以看到使用express()创建应用并express.text({ limit: 10mb, type: */* })把请求体统一按文本解析10MB 限制与 AWS API Gateway 的 payload 上限对齐解析工作留给 inflight handler 自己完成每个路由通过this.appmethod, asyncMiddleware(...))注册到 ExpresstransformRoutePath会把 OpenAPI 风格的{id}转回 Express 的:id写法api.inflight.ts因为 Express v4 不原生支持异步请求处理SDK 用asyncMiddleware包装异步 handlerapi.inflight.ts服务器启动后url形如http://localhost:port即Api.url属性的值api.inflight.ts。另外模拟器会把上次使用的端口写入状态文件state.json下次启动时若端口仍可用则优先复用提升本地开发体验。AWStf-aws与awscdkAWS 实现基于Amazon API Gateway。从 target-tf-aws/api.ts 可以看到 Terraform 版实现会生成ApiGatewayRestApi、ApiGatewayDeployment、ApiGatewayStage等基础设施资源shared-aws/api.ts 定义了IAwsApi接口暴露restApiArn、restApiId、restApiName、stageName、invokeUrl、deploymentId等 AWS 专属属性便于在需要时下钻操作。一个值得注意的细节AWS 阶段名stage name固定为prodshared-aws/api.ts它会出现在 API 的 URL 中。此外AWS 版在onLift时会通过环境变量把Api.url注入 inflight hostshared-aws/api.ts保证 inflight 代码中访问 API 地址时用的是运行时环境变量而非硬编码。Azuretf-azure与 GCPtf-gcp截至本文档所依据的版本Azure 与 GCP 平台尚不支持cloud.Api原文档以 标注并链接到对应的跟踪 issueAzurewinglang/wing#625GCPwinglang/wing#624。因此当前可用的目标是sim、tf-aws与awscdk。五、ApiProps开启 CORS 跨域配置ApiProps是new cloud.Api(props?)的构造选项目前只有两个字段全部围绕 CORS 行为属性类型默认值说明corsboolfalseCORS 配置关闭设为true时按默认选项为所有路由添加 CORS 头corsOptionsApiCorsOptionscors为true时应用默认 CORS 选项自定义 CORS 细节当cors: true但未传corsOptions时默认选项为new cloud.Api({ cors: true, // 默认效果等价于 // allowOrigin: *, // allowMethods: [HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, // HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.OPTIONS], // allowHeaders: [Content-Type, Authorization], // exposeHeaders: [], // allowCredentials: false, });个性化示例new cloud.Api({ cors: true, corsOptions: { allowOrigin: https://example.com } });从 源码构造函数 可以看到this.corsOptions props.cors ? this._cors(props.corsOptions) : undefined;而_cors方法cloud/api.ts用默认值 用户覆盖的方式合并配置保证用户传入的字段优先。ApiCorsOptions全参数详解参数类型默认值说明allowCredentialsboolfalse是否允许携带凭据allowHeadersMutArraystr[Content-Type, Authorization]允许的请求头列表allowMethodsMutArrayHttpMethodGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS允许的 HTTP 方法列表allowOriginstr*允许的来源originexposeHeadersMutArraystr[]暴露给客户端的响应头列表maxAgeduration300 seconds浏览器缓存预检preflight结果的时长这些选项最终通过静态函数cloud.Api.renderCorsHeaders(corsOptions)源码实现渲染成两组 HTTP 头defaultResponse默认响应头Access-Control-Allow-Origin、Access-Control-Expose-Headers、Access-Control-Allow-CredentialsoptionsResponse预检响应头Access-Control-Allow-Origin、Access-Control-Allow-Headers、Access-Control-Allow-Methods、Access-Control-Max-Age。在模拟器中CORS 中间件会在收到OPTIONS请求时直接返回204并携带optionsResponse头其他请求则附加defaultResponse头后继续api.inflight.ts。说明原文档注明CORS 选项可以在单条路由上覆盖这一能力尚未实现not yet implemented当前只能做 API 级别的全局配置。六、路由级选项端点选项Endpoint Options8 个路由方法get/post/put/delete/patch/options/head/connect的第三个可选参数props分别对应ApiGetOptions、ApiPostOptions、ApiPutOptions、ApiDeleteOptions、ApiPatchOptions、ApiOptionsOptions、ApiHeadOptions、ApiConnectOptions。这些类型都继承自共同的基类ApiEndpointOptions源码而ApiEndpointOptions本质上是FunctionProps的别名——也就是说每个路由背后都是一个云函数路由级选项就是函数级配置。各路由级选项的完整字段如下参数类型默认值说明concurrencynum平台相关限制模拟器为 100同一时间最大并发调用数envMutMapstr无环境变量传给处理函数的环境变量logRetentionDaysnum30函数日志保留天数设置为负值表示日志永不过期memorynum1024分配给函数的内存大小MBtimeoutduration1m函数最大运行时长典型用法示例api.get(/slow, inflight (request: cloud.ApiRequest): cloud.ApiResponse { // 长时间运算... return cloud.ApiResponse { status: 200, body: done }; }, { timeout: 5m, memory: 2048, concurrency: 20, env: { REGION: us-east-1 }, logRetentionDays: 7 });七、方法参考8 种 HTTP 方法路由注册Api提供 8 个 preflight 方法签名完全一致只是 HTTP 方法与选项类型不同方法签名说明connectconnect(path, inflight, props?: ApiConnectOptions): void为指定路径注册 CONNECT 请求处理deletedelete(path, inflight, props?: ApiDeleteOptions): void注册 DELETE 处理getget(path, inflight, props?: ApiGetOptions): void注册 GET 处理headhead(path, inflight, props?: ApiHeadOptions): void注册 HEAD 处理optionsoptions(path, inflight, props?: ApiOptionsOptions): void注册 OPTIONS 处理patchpatch(path, inflight, props?: ApiPatchOptions): void注册 PATCH 处理postpost(path, inflight, props?: ApiPostOptions): void注册 POST 处理putput(path, inflight, props?: ApiPutOptions): void注册 PUT 处理每个方法都在抽象基类中声明cloud/api.ts由各平台实现类落实如 target-sim/api.ts 中每个方法都会调用addEndpoint。静态函数静态函数签名说明onLiftTypeonLiftType(host: IInflightHost, ops: MutArraystr)Wing 编译器为每个需要在 inflight 使用本类型的 host 调用一次的钩子常用于添加权限、环境变量等能力toInflighttoInflight(obj: IResource)生成一段异步 JavaScript 语句用于为资源创建 inflight client必须在 async 上下文中执行renderCorsHeadersrenderCorsHeaders(corsOptions?: ApiCorsOptions)生成包含默认 CORS 响应头与 OPTIONS 响应头的对象返回CorsHeaders结构含defaultResponse与optionsResponse两个MutMapstrrenderOpenApiPathrenderOpenApiPath(path: str)把:风格的路径参数转换为合法的 OpenAPI 路径/users/:id→/users/{id}renderOpenApiPath的实现非常直观cloud/api.tspath.replace(/\/:([A-Za-z0-9_-])/g, /{$1})它被_getOpenApiSpec用于把内部路径批量转成 OpenAPI 格式。属性属性类型说明nodeconstructs.Node构造树节点urlstrAPI 端点的基础 URLurl的取值在模拟器下形如http://localhost:port在 AWS 下则是 API Gateway 的调用地址invokeUrl。部署后把这个 URL 暴露给前端或写入环境变量即可让客户端访问你的 API。八、协议与枚举HttpMethod枚举端点的合法 HTTP 方法共 8 个成员源码GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、PATCH。字符串与枚举互转由parseHttpMethod负责遇到不支持的方法会抛出Unsupported HTTP method错误。协议接口IApiEndpointHandler拥有 inflighthandle方法、可传给Api各 preflight 请求方法的资源扩展自IInflightIApiEndpointHandlerClientIApiEndpointHandler的 inflight client其handle(request: ApiRequest): ApiResponse?是真正在端点被请求时执行的入口。九、源码级原理路径校验、歧义检测与 OpenAPI Spec 生成cloud.Api在注册路由时并非简单透传抽象基类内置了一套严谨的路径治理逻辑这可以从 cloud/api.ts 中看到路径格式校验_validatePath路径段只允许字母数字以及-、_、.参数段只允许字母数字和_不满足则抛出Invalid path ...错误。这是路由注册前的第一道防线。歧义检测_arePathsAmbiguous/_findAmbiguousPath如果新路由与已存在路由的路径段数相同、且对应位置一个是参数一个是字面量例如已有/api/hello/:name再注册/api/hello/foo的同一方法会抛出is ambiguous错误。模拟器测试target-sim/api.test.ts专门验证了这类冲突场景。兄弟路径检测_arePathsSiblings/_findSiblingPath形如/:username与/:id这类参数名不同但结构相同的路径会被视为冲突提示try to match the parameter names to avoid this error。重复端点检测同一路径同一方法重复注册会直接报Endpoint for path ... and method ... already exists。OpenAPI Spec 生成_addToSpec/_getOpenApiSpec每个路由被写入内部apiSpec生成operationId如get-employees、路径参数定义、200响应描述与 CORS 头 schema最终_getOpenApiSpec返回符合OpenAPI 3.0.3规范的完整 speccloud/api.ts并调用renderOpenApiPath将路径参数统一转换为{id}格式。这份 spec 正是各平台生成 API Gateway / Express 路由的蓝图。十、测试验证如何在仓库中验证这些行为如果你想在仓库中亲自验证上述行为可以关注以下测试与源码路径模拟器 API 行为测试target-sim/api.test.ts覆盖重复端点、歧义路径、请求回显echo、查询参数、路径参数等场景Terraform-AWS 目标测试target-tf-aws/api.test.ts验证 API Gateway 产物请求处理函数测试shared-aws/api.onrequest.inflight.test.ts。此外仓库中还有大量 Wing 语言层面的 API 用例例如 tests/sdk_tests/api 下的.w文件可以直接用 Wing CLI 在sim平台上运行观察 Express 服务器如何处理请求与 CORS 头。总结cloud.Api是 Wing 云端 HTTP 服务的统一入口一条路由声明即完成路径匹配 函数创建 权限授予 OpenAPI 记录的全部工作。通过本文你可以使用api.get/post/put/delete/...快速搭建 REST API并借助ApiRequest的vars、query、body处理各种请求通过ApiProps.cors/corsOptions精确控制跨域策略用路由级选项timeout、memory、concurrency、env、logRetentionDays调优每个端点的底层函数理解同一份代码在模拟器Express与 AWSAPI Gateway上的不同落地方式以及 Azure/GCP 当前的未支持状态。更多细节可继续查阅 cloud 标准库 API 文档 及 SDK 源码。赞分享编程语言编译器云原生语言运行时【免费下载链接】wingA programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡项目地址https://gitcode.com/gh_mirrors/wi/wing点击查看免费下载相关推荐Wing 标准库 cloud.Api 完全指南用一条 Api 资源构建跨云 HTTP/REST 端点Wing 标准库 cloud.Api 完全指南用一条 Api 资源构建跨云 HTTP/REST 端点 cloud.Api 是 Wing 标准库 wingl编程语言编译器云原生语言运行时Wing 云原生语言 cloud.Api CORS 配置全解析从 cors.test.w 测试用例到多平台实现Wing 云原生语言 cloud.Api CORS 配置全解析从 cors.test.w 测试用例到多平台实现 导读 本文围绕 wing 仓库中 cors.t编程语言编译器云原生语言运行时Wing 语言 cloud.Api 路径变量Path Variables机制详解从路由定义到多目标平台实现Wing 语言 cloud.Api 路径变量Path Variables机制详解从路由定义到多目标平台实现 导读 在 Wing 语言中 cloud.Ap编程语言编译器云原生语言运行时上一篇Python调试不再难VS Code Recipes提供的5种调试方法下一篇Textractor游戏文本提取神器3步实现外语游戏无障碍游玩创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考