Scalar.Aws.Lambda 集成指南:在 AWS Lambda 中渲染 Scalar API Reference
【免费下载链接】scalarScalar is an open-source API platform: 🌐 Modern REST API Client 📖 Beautiful API References ✨ 1st-Class OpenAPI/Swagger Support项目地址: https://gitcode.com/GitHub_Trending/sc/scalar
Scalar 是一个开源的 API 平台,提供了美观的 API References 与一流的 OpenAPI/Swagger 支持。Scalar.Aws.Lambda是 Scalar 官方为 AWS 生态提供的 .NET 集成包,让你可以直接在由 Amazon API Gateway HTTP API 前置的 AWS Lambda 函数中,基于 OpenAPI/Swagger 文档渲染出交互式的 API 参考页面。读完本文,你将掌握Scalar.Aws.Lambda的两种接入方式(零 DI 静态工厂与依赖注入)、{proxy+}路由声明、Stage 前缀自动识别、静态资源与文档的解析规则,以及当前版本的支持边界与已知限制。
包定位与适用场景
Scalar.Aws.Lambda(NuGet 包名Scalar.Aws.Lambda)提供的核心能力是:在 AWS Lambda 函数中直接渲染 Scalar API Reference,而无需单独托管一个 Web 服务。它面向的典型架构是:
浏览器 ──▶ Amazon API Gateway HTTP API ──▶ AWS Lambda (Scalar.Aws.Lambda) ──▶ OpenAPI 文档从 CHANGELOG.md 可以看到,该集成在 0.2.0 版本中随#9764引入,同时提供了两条等价的接入路径:零 DI 的静态 handler 工厂(ScalarApiReferenceHandler.Create)和DI 注册服务(AddScalarApiReference/IScalarApiReference)。值得注意的是,驱动它的请求处理器、渲染结果与静态资源表是从共享项目中迁移而来的,并受到SCALAR_SERVERLESS常量保护,因此Scalar.AspNetCore、Scalar.Aspire、Scalar.Azure.Functions均未受任何行为影响——这也意味着你可以在 Azure Functions 与 AWS Lambda 之间复用同一套 serverless 渲染逻辑。
[!NOTE] 当前版本仅支持API Gateway HTTP API(payload format 2.0)。REST API(payload format 1.0)、Application Load Balancer 与 Lambda Function URL 均不在首批支持范围内,详见下文限制与路线图。
快速开始:安装与接入
1. 安装包
dotnet add package Scalar.Aws.Lambda2. 选择入口
Scalar.Aws.Lambda提供两个共享同一套实现的入口,按你函数的托管方式任选其一即可。
方案 A —— 零 DI 静态工厂
适用于没有依赖注入容器的普通 Lambda 函数。ScalarApiReferenceHandler.Create(...)会返回一个可直接作为 Lambda 入口使用的请求/响应委托(ScalarApiReferenceHandler.cs):
using Amazon.Lambda.APIGatewayEvents; using Amazon.Lambda.RuntimeSupport; using Amazon.Lambda.Serialization.SystemTextJson; using Scalar.Aws.Lambda; var handler = ScalarApiReferenceHandler.Create(options => { options.Title = "My API"; }); await LambdaBootstrapBuilder.Create<APIGatewayHttpApiV2ProxyRequest, APIGatewayHttpApiV2ProxyResponse>(handler, new DefaultLambdaJsonSerializer()) .Build() .RunAsync();从源码结构看,Create内部维护了一个极简的StaticOptionsSnapshot:它实现了IOptionsSnapshot<ScalarOptions>,在每次访问时都构建一份全新的ScalarOptions并应用配置回调,从而在无 DI 场景下模拟出 DI 路径中IOptionsSnapshot的按请求生命周期,让ScalarApiReference成为两个入口共享的唯一传输逻辑实现(ScalarApiReferenceHandler.cs)。
方案 B —— 依赖注入
适用于使用Amazon.Lambda.RuntimeSupport泛型主机托管的 Lambda 函数。注册 Scalar 服务后解析IScalarApiReference即可:
using Microsoft.Extensions.DependencyInjection; using Scalar.Aws.Lambda; var services = new ServiceCollection(); services.AddScalarApiReference(options => { options.Title = "My API"; }); await using var provider = services.BuildServiceProvider(); // IScalarApiReference 以 Scoped 方式注册,请按每次调用创建独立 DI 作用域 using var scope = provider.CreateScope(); var scalar = scope.ServiceProvider.GetRequiredService<IScalarApiReference>(); var response = await scalar.HandleAsync(request, context);[!IMPORTANT]
IScalarApiReference以Scoped生命周期注册(见 ScalarServiceCollectionExtensions.cs)。请遵循标准的 Lambda + DI 规范,在每次调用时新建 DI 作用域,而不要从根 provider 直接解析。
3. 声明 API Gateway 路由
路由必须使用{proxy+}贪婪路径参数(并为裸索引路径额外声明一条普通路由)。以 SAM 模板为例:
Events: ScalarIndex: Type: HttpApi Properties: Path: /scalar Method: GET ScalarProxy: Type: HttpApi Properties: Path: /scalar/{proxy+} Method: ANY仓库自带的 playground/template.yaml 即采用这一模式,并额外给出可直接上手的完整骨架(Runtime: dotnet10、Handler: Scalar.Aws.Lambda.Playground、函数级Timeout: 10/MemorySize: 256,输出ScalarApiUrl指向https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/scalar/),可作为你部署时的最小参考。
4. 指向你的 OpenAPI 文档
默认情况下,Scalar 会从openapi/{documentName}.json(相对于 reference 的路径)查找 OpenAPI 文档。你可以在该路由暴露文档,也可以改变匹配模式:
options.AddDocument("v1", routePattern: "openapi/v1.json");5. Stage 与路由前缀
当你的 API Gateway stage不是$default(例如prod)时,Scalar.Aws.Lambda会自动探测 stage 名并将其从渲染出的相对 URL 中剥离,无需额外配置。若你使用了自定义域名 base path mapping(该前缀对 stage 名不可见),则需要显式设置ScalarOptions.RoutePrefix:
options.RoutePrefix = "my-base-path";RoutePrefix定义在 ScalarOptions.AwsLambda.cs:当其值为null(默认)时,前缀会从request.RequestContext.Stage自动探测;HTTP API 在$defaultstage 下不会把 stage 嵌入路径,因此该场景不加任何前缀。
按请求定制配置
两个入口都接受一个可选回调,用于按请求定制选项:
// 静态工厂 var handler = ScalarApiReferenceHandler.Create(options => options.Title = "My API"); // DI var response = await scalar.HandleAsync(request, context, (options, req) => { options.Title = $"My API ({req.RequestContext.DomainName})"; });深入理解 HTTP API 事件模型(payload format 2.0)
Scalar.Aws.Lambda只支持HTTP API + payload format 2.0,即Amazon.Lambda.APIGatewayEvents中的APIGatewayHttpApiV2ProxyRequest/APIGatewayHttpApiV2ProxyResponse。理解这一事件模型的细节,是正确配置路由与排查问题的关键。
{proxy+}路由的解析
HTTP API 支持贪婪路径参数{proxy+},其语义类似 ASP.NET Core 的 catch-all 路由参数。声明{proxy+}后,Scalar 会直接从request.PathParameters["proxy"]读取路径剩余部分(见 ScalarApiReference.cs,常量RouteRemainderKey = "proxy"):
GET /scalar与GET /scalar/:渲染默认文档的 reference 索引页。GET /scalar/v3:渲染v3文档的 reference 索引页。GET /scalar/scalar.js、GET /scalar/scalar.aws.lambda.js、GET /scalar/favicon.svg:提供内嵌的静态资源。
另外,如果PathParameters完全不存在(例如函数被直接调用、未经过 API Gateway 代理集成),请求会被当作索引请求处理而不是抛错,这为本地调试提供了便利。
Stage 处理
HTTP API 对任何命名 stage都会把 stage 名作为路径段嵌入RawPath,唯独特殊的$defaultstage 不会:
| Stage | GET /scalar/对应的RawPath | 行为 |
|---|---|---|
$default | /scalar/ | 不剥离前缀。 |
prod | /prod/scalar/ | 自动探测并剥离prod,避免其泄漏到相对 URL。 |
实现上,HandleAsync在每次请求时先调用ApplyRoutePrefix:只有RoutePrefix尚未被显式设置时,才会读取request.RequestContext.Stage并将命名 stage 折叠进RoutePrefix(ScalarApiReference.cs)。这与 Azure Functions 集成将host.json的routePrefix折叠进同一选项的做法相互呼应。
而自定义域名 base path mapping 添加的前缀不会反映在RequestContext.Stage中——此时必须显式设置ScalarOptions.RoutePrefix为该 base path。
Header 处理
API Gateway HTTP API 会把 header 名转为小写,并在headers字段中用逗号合并重复 header(与 REST API / payload format 1.0 不同,这里没有multiValueHeaders字段)。Scalar.Aws.Lambda以大小写不敏感方式读取Accept-Encoding与If-None-Match(见 ScalarApiReference.cs 的AcceptsGzip/GetHeader),因此无论调用方如何书写 header 大小写(API Gateway 通常已小写化,但直接测试调用可能不会)都能正确处理。
响应体编码
APIGatewayHttpApiV2ProxyResponse.IsBase64Encoded仅在响应体为gzip 压缩的静态资源(二进制内容)时为true;HTML 页面与未压缩的静态资源则以纯 UTF-8 文本返回,IsBase64Encoded = false。BuildResponseAsync的实现(ScalarApiReference.cs)完整覆盖了四种响应形态:
- 302:设置
Location头,用于重定向(如GET /scalar→/scalar/)。 - 304:携带
ETag/Cache-Control(必要时加Vary: Accept-Encoding),配合If-None-Match实现条件请求。 - 404:资源不存在时直接返回。
- 200:携带
Cache-Control、Vary、ETag、Content-Type,正文为 HTML 或(base64 编码的)二进制静态资源。
限制与路线图
你必须自己提供函数
与 Azure Functions 集成类似(且不同于 ASP.NET Core 集成——后者通过MapScalarApiReference()替你注册端点),本包要求你自行声明 Lambda 函数,并将请求转发给IScalarApiReference或ScalarApiReferenceHandler.Create(...)返回的委托。
仅支持 API Gateway HTTP API(payload format 2.0)
以下事件源在首个版本中不受支持:
- API Gateway REST API(payload format 1.0)——
APIGatewayProxyRequest/APIGatewayProxyResponse。 - Application Load Balancer目标组。
- Lambda Function URL。
这些事件形状在路由/路径参数解析、header 结构、stage 处理上差异足够大,值得为它们编写专门的适配器而非勉强做兼容 shim——这已列入路线图。如果你现在就需要其中一种,可以通过Scalar.Shared中的底层构件自行实现等价的ScalarRequestProcessor逻辑;如果你是在 Lambda 中托管完整的 ASP.NET Core 应用(通过Amazon.Lambda.AspNetCoreServer),则应直接使用Scalar.AspNetCore包的MapScalarApiReference()。
路由参数名必须为proxy
catch-all 路由参数必须命名为proxy(例如Path: /scalar/{proxy+})。适配器通过request.PathParameters["proxy"]区分静态资源请求与 reference 页面,并解析文档名。
自定义域名 base path mapping
Stage 自动探测读取的是request.RequestContext.Stage,它不会反映自定义域名的 base path mapping。若你使用自定义域名,请将ScalarOptions.RoutePrefix显式设置为该 base path。
源码结构速览
如果你希望深入阅读实现或参与贡献,本集成在仓库中的组织方式如下:
- 入口与接口:ScalarApiReferenceHandler.cs(零 DI 静态工厂)、IScalarApiReference.cs(DI 服务接口)、ScalarApiReference.cs(核心请求处理与响应构建)。
- 扩展与选项:ScalarServiceCollectionExtensions.cs(
AddScalarApiReference注册)、ScalarOptions.AwsLambda.cs(RoutePrefix选项)。 - 内嵌静态资源:
StaticAssets目录下的scalar.aws.lambda.js与favicon.svg。 - 可运行样例:playground/template.yaml 与
playground/Function.cs(SAM 本地 playground)。 - 测试:
tests/Scalar.Aws.Lambda.Tests下的ScalarApiReferenceHandlerTests.cs、ScalarApiReferenceTests.cs、ScalarRequestProcessorTests.cs覆盖了入口、stage 前缀与请求处理的核心行为,是理解预期行为的良好参考。
综上,Scalar.Aws.Lambda以极低的接入成本让 serverless 架构获得完整的 Scalar API Reference 渲染能力:两条等价入口覆盖有无 DI 容器的两种托管方式,{proxy+}+ stage 自动识别让路由声明几乎零配置,而条件请求、gzip 静态资源与明确的错误响应则保证了生产环境下的行为可预期。结合本文的源码级说明与 getting-started.md、http-api-model.md、limitations.md 等文档,你可以快速完成从包安装到 SAM 部署的完整链路。
【免费下载链接】scalarScalar is an open-source API platform: 🌐 Modern REST API Client 📖 Beautiful API References ✨ 1st-Class OpenAPI/Swagger Support项目地址: https://gitcode.com/GitHub_Trending/sc/scalar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考