跳转到内容

Smithy TypeScript API

Filter this guidePick generator option values to hide sections that don't apply.

Smithy 是一种与协议无关的接口定义语言,用于以模型驱动的方式编写 API。

Smithy TypeScript API 生成器使用 Smithy 进行服务定义,并使用 Smithy TypeScript Server SDK 进行实现来创建新的 API。该生成器提供 CDK 或 Terraform 基础设施即代码,将您的服务部署到 AWS Lambda,并通过 AWS API Gateway REST API 公开。它提供类型安全的 API 开发,并从 Smithy 模型自动生成代码。生成的处理程序使用 AWS Lambda Powertools for TypeScript 进行可观测性,包括日志记录、AWS X-Ray 跟踪和 CloudWatch 指标

您可以通过两种方式生成新的 Smithy TypeScript API:

Terminal window
pnpm nx g @aws/nx-plugin:ts#api --framework=smithy
您还可以执行试运行以查看哪些文件会被更改
Terminal window
pnpm nx g @aws/nx-plugin:ts#api --framework=smithy --dry-run
参数类型默认值描述
name 必需string-API 的名称(必填)。用于生成类名和文件路径。
framework trpc | smithytrpc要使用的API框架。
namespace string-Smithy API 的命名空间(仅适用于 smithy 框架)。默认为您的 monorepo 作用域
integrationPattern isolated | sharedisolatedAPI Gateway 集成的生成方式。可选择 isolated(默认)或 shared。
auth iam | cognito | customiam用于对 API 进行身份验证的方法。可选择 iam(默认)、cognito 或 custom。
directory stringpackages存储应用程序的目录。
subDirectory string-项目所在的子目录。默认情况下为项目名称。
iac inherit | cdk | terraforminherit首选的 IaC 提供商。默认情况下,这将继承您的初始选择。
infra rest-lambda | http-lambda | nonerest-lambda用于部署此 API 的基础设施类型。
preferInstallDependencies booleantrue是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。

生成器在 <directory>/<api-name> 目录中创建两个相关项目:

  • 文件夹model/ Smithy 模型项目
    • package.json 定义项目包名称和依赖项的项目清单
    • project.json 项目配置和构建目标
    • smithy-build.json Smithy 构建配置
    • ssdk.rolldown.config.mjs 打包生成的 TypeScript Server SDK
    • 文件夹src/
      • main.smithy 主服务定义
      • 文件夹operations/
        • echo.smithy 示例操作定义
  • 文件夹backend/ TypeScript 后端实现
    • project.json 项目配置和构建目标
    • rolldown.config.ts 打包配置
    • 文件夹src/
      • handler.ts AWS Lambda 处理程序
      • local-server.ts 本地开发服务器
      • service.ts 服务实现
      • context.ts 服务上下文定义
      • 文件夹operations/
        • echo.ts 示例操作实现
      • 文件夹generated/ 生成的 TypeScript SDK(在构建期间创建)

由于此生成器根据您选择的 iac 创建基础设施即代码,它将在 packages/common 中创建一个项目,其中包含相关的 CDK 构造或 Terraform 模块。

通用基础设施即代码项目的结构如下:

  • 文件夹packages/common/constructs
    • 文件夹src
      • 文件夹app/ 特定于项目/生成器的基础设施构造
        • 文件夹apis/
          • <project-name>.ts 用于部署 API 的 CDK 构造
      • 文件夹core/ app 中的构造重用的通用构造
        • 文件夹api/
          • rest-api.ts 用于部署 REST API 的 CDK 构造
          • utils.ts API 构造的实用工具
      • index.ts app 导出构造的入口点
    • project.json 项目构建目标和配置

部署的 Smithy API 具有以下架构,在 API Gateway 阶段前面有一个 AWS WAFv2 Web ACL:

ClientWAFAPI Gateway(REST API)Lambda(Smithy Server SDK)CloudWatch(Logs, Metrics)X-Ray(Traces)

操作在模型项目中的 Smithy 文件中定义。主服务定义在 main.smithy 中:

$version: "2.0"
namespace your.namespace
use aws.protocols#restJson1
use smithy.framework#ValidationException
@title("YourService")
@restJson1
service YourService {
version: "1.0.0"
operations: [
Echo,
// Add your operations here
]
errors: [
ValidationException
]
}

各个操作在 operations/ 目录中的单独文件中定义:

$version: "2.0"
namespace your.namespace
@http(method: "POST", uri: "/echo")
operation Echo {
input: EchoInput
output: EchoOutput
}
structure EchoInput {
@required
message: String
foo: Integer
bar: String
}
structure EchoOutput {
@required
message: String
}

如果您有多个共享相同数据类型的 Smithy API,您可以在形状库中定义这些类型一次,而不是在每个模型中重复它们。形状库是一个没有服务的 Smithy 项目 - 只有可重用的形状 - 任意数量的 Smithy 项目都可以依赖它。

使用 smithy#project 生成器生成一个:

Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes
您还可以执行试运行以查看哪些文件会被更改
Terminal window
pnpm nx g @aws/nx-plugin:smithy#project --name=my-shapes --type=shapes --dry-run

然后,您的 API 模型可以使用 use 引用其形状:

$version: "2.0"
namespace com.example.api
use com.example.shared#Customer
structure GetCustomerOutput {
@required
customer: Customer
}

请参阅 Smithy 项目指南,了解如何创建形状库并将其连接为 API 模型的依赖项。

操作实现位于后端项目的 src/operations/ 目录中。每个操作都使用从 TypeScript Server SDK 生成的类型实现(在构建时从您的 Smithy 模型生成)。

import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input) => {
// Your business logic here
return {
message: `Echo: ${input.message}` // type-safe based on your Smithy model
};
};

操作必须在 src/service.ts 中注册到服务定义:

import { ServiceContext } from './context.js';
import { YourServiceService } from './generated/ssdk/index.js';
import { Echo } from './operations/echo.js';
// Import other operations here
// Register operations to the service here
export const Service: YourServiceService<ServiceContext> = {
Echo,
// Add other operations here
};

您可以在 context.ts 中为操作定义共享上下文:

export interface ServiceContext {
// Powertools tracer, logger and metrics are provided by default
tracer: Tracer;
logger: Logger;
metrics: Metrics;
// Add shared dependencies, database connections, etc.
dbClient: any;
userIdentity: string;
}

此上下文传递给所有操作实现,可用于共享资源,如数据库连接、配置或日志记录实用工具。

使用 AWS Lambda Powertools 进行可观测性

Section titled “使用 AWS Lambda Powertools 进行可观测性”

生成器使用 AWS Lambda Powertools 配置结构化日志记录,并通过 Middy 中间件自动注入上下文。

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

您可以通过上下文从操作实现中引用日志记录器:

operations/echo.ts
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
ctx.logger.info('Your log message');
// ...
};

AWS X-Ray 跟踪通过 captureLambdaHandler 中间件自动配置。

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

您可以在操作中向跟踪添加自定义子段:

operations/echo.ts
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
// Creates a new subsegment
const subsegment = ctx.tracer.getSegment()?.addNewSubsegment('custom-operation');
try {
// Your logic here
} catch (error) {
subsegment?.addError(error as Error);
throw error;
} finally {
subsegment?.close();
}
};

CloudWatch 指标通过 logMetrics 中间件自动为每个请求收集。

handler.ts
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
.use(captureLambdaHandler(tracer))
.use(injectLambdaContext(logger))
.use(logMetrics(metrics))
.handler(lambdaHandler);

您可以在操作中添加自定义指标:

operations/echo.ts
import { MetricUnit } from '@aws-lambda-powertools/metrics';
import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
ctx.metrics.addMetric("CustomMetric", MetricUnit.Count, 1);
// ...
};

Smithy 提供内置的错误处理。您可以在 Smithy 模型中定义自定义错误:

@error("client")
@httpError(400)
structure InvalidRequestError {
@required
message: String
}

并将它们注册到您的操作/服务:

operation MyOperation {
...
errors: [InvalidRequestError]
}

然后在 TypeScript 实现中抛出它们:

import { InvalidRequestError } from '../generated/ssdk/index.js';
export const MyOperation: MyOperationHandler<ServiceContext> = async (input) => {
if (!input.requiredField) {
throw new InvalidRequestError({
message: "Required field is missing"
});
}
return { /* success response */ };
};

当您的 API 受身份验证保护时,您的操作通常需要知道谁在调用。推荐的方法是在处理程序中解析一次调用者的身份,并通过服务上下文传递它以供特定操作使用。

我们将未授权的情况建模为 Smithy 错误,以便它序列化为正确的 403 响应。将其添加到您的模型中,例如在 model/src/operations/errors.smithy 中,并在任何需要身份的操作上引用它:

$version: "2.0"
namespace your.namespace
/// Thrown when the calling user cannot be determined
@error("client")
@httpError(403)
structure UnauthorizedError {
@required
message: String
}

首先,在 src/context.ts 中的服务上下文上公开已解析的身份。我们将其作为函数提供,以便从操作内部抛出 UnauthorizedError(Server SDK 将其序列化为 403),而不是从处理程序中抛出:

import { Logger } from '@aws-lambda-powertools/logger';
import { Metrics } from '@aws-lambda-powertools/metrics';
import { Tracer } from '@aws-lambda-powertools/tracer';
export interface Identity {
sub: string;
username: string;
}
/**
* Context provided to all operations.
*/
export interface ServiceContext {
tracer: Tracer;
logger: Logger;
metrics: Metrics;
getIdentity: () => Promise<Identity>;
}

接下来,在 src/identity.ts 中编写解析器。当无法确定调用者时,它会抛出 UnauthorizedError。实现取决于您选择的 auth 方法:

auth = iam

对于 IAM 身份验证,我们使用从 API Gateway 事件中提取的 sub 在 Cognito 中查找调用者:

import { CognitoIdentityProvider } from '@aws-sdk/client-cognito-identity-provider';
import type { APIGatewayProxyEvent } from 'aws-lambda';
import { Identity } from './context.js';
import { UnauthorizedError } from './generated/ssdk/index.js';
const cognito = new CognitoIdentityProvider();
export const getIdentity = async (
event: APIGatewayProxyEvent,
): Promise<Identity> => {
const cognitoAuthenticationProvider =
event.requestContext?.identity?.cognitoAuthenticationProvider;
let sub: string | undefined = undefined;
if (cognitoAuthenticationProvider) {
const providerParts = cognitoAuthenticationProvider.split(':');
sub = providerParts[providerParts.length - 1];
}
if (!sub) {
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
}
const { Users } = await cognito.listUsers({
// Assumes user pool id is configured in lambda environment
UserPoolId: process.env.USER_POOL_ID!,
Limit: 1,
Filter: `sub="${sub}"`,
});
if (!Users || Users.length !== 1) {
throw new UnauthorizedError({ message: `No user found with subjectId ${sub}` });
}
return { sub, username: Users[0].Username! };
};
auth = cognito

使用 auth: 'cognito',API Gateway Cognito User Pools 授权器验证调用者在 Authorization 标头中提供的 JWT,并将验证的声明放在事件的 event.requestContext.authorizer.claims 上:

import type { APIGatewayProxyEvent } from 'aws-lambda';
import { Identity } from './context.js';
import { UnauthorizedError } from './generated/ssdk/index.js';
export const getIdentity = async (
event: APIGatewayProxyEvent,
): Promise<Identity> => {
const claims = event.requestContext?.authorizer?.claims as
| Record<string, string>
| undefined;
const sub = claims?.sub;
const username = claims?.username;
if (!sub || !username) {
throw new UnauthorizedError({ message: 'Unable to determine calling user' });
}
return { sub, username };
};

然后在 src/handler.ts 中将解析器连接到上下文:

import { Service } from './service.js';
import { getIdentity } from './identity.js';
// ...
const httpResponse = await serviceHandler.handle(httpRequest, {
tracer,
logger,
metrics,
getIdentity: () => getIdentity(event),
});

现在我们可以在操作中使用已解析的身份,例如在 src/operations/echo.ts 中:

import { ServiceContext } from '../context.js';
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
const identity = await ctx.getIdentity();
return { message: `${identity.username} says ${input.message}` };
};

Smithy 模型项目使用 Smithy CLI 构建 Smithy 工件并生成 TypeScript Server SDK:

Terminal window
pnpm nx build <model-project>

在 macOS 和 Linux 上,CLI 由 mise 解析,构建会按需获取它,因此无需安装任何东西 - 它会在您第一次构建时下载并缓存固定版本。

此过程:

  1. 编译 Smithy 模型并验证它
  2. 从 Smithy 模型生成 OpenAPI 规范
  3. 创建 TypeScript Server SDK,具有类型安全的操作接口
  4. 将构建工件输出dist/<model-project>/build/

后端项目在编译期间自动复制生成的 SDK:

Terminal window
pnpm nx copy-ssdk <backend-project>

mise 不向 npm 发布 Windows 包,因此在 Windows 上,Smithy CLI 是您自己安装的先决条件。按照 Smithy CLI 安装指南安装一次(例如 winget install smithyscoop install smithy),并确保 smithy 在您的 PATH 上。在 Windows 上生成的 Smithy 项目直接运行 smithy,而不是通过 mise

或者,在 WSL 内开发,其中构建运行 Linux 路径,mise 为您解析 CLI - 无需安装任何东西。

在 Windows 上生成的项目提交一个直接调用 smithycompile 目标,因此在其上工作的其他任何人 - 包括在 macOS 或 Linux 上 - 也需要在他们的 PATH 上有 Smithy CLI。要让这些机器通过 mise 解析 CLI,请将目标切换到 mise 命令,如下面所述

macOS 和 Linux 通过 mise 解析 CLI,Windows 使用全局安装的 CLI,但您可以通过编辑模型项目的 project.json 中的 compile 目标的命令在任何平台上选择任一方式。

要使用全局安装的 Smithy CLI 而不是 mise,请将 mise 前缀替换为裸 smithy

project.json
{
"targets": {
"compile": {
"options": {
"commands": ["... npx -y mise@<version> exec smithy@<version> -- smithy build ..."]
"commands": ["... smithy build ..."]
}
}
}
}

要返回到 mise 解析 CLI,请恢复 npx -y mise@<version> exec smithy@<version> -- 前缀。

生成器会自动配置一个 bundle 目标,它使用 Rolldown 来创建部署包:

Terminal window
pnpm nx bundle <project-name>

Rolldown 配置可以在 rolldown.config.ts 中找到,每个要生成的包都有一个入口。Rolldown 会管理并行创建多个包(如果已定义)。

生成器配置了一个具有热重载功能的本地开发服务器:

Terminal window
pnpm nx serve <backend-project>

生成器根据您选择的 iac 创建 CDK 或 Terraform 基础设施。

用于部署 API 的 CDK 构造位于 common/constructs 文件夹中:

import { MyApi } from '@my-scope/common-constructs';
export class ExampleStack extends Stack {
constructor(scope: Construct, id: string) {
// Add the API to your stack
const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
}
}

这将设置:

  1. 用于 Smithy 服务的 AWS Lambda 函数
  2. 作为函数触发器的 API Gateway REST API
  3. IAM 角色和权限
  4. CloudWatch 日志组
  5. X-Ray 跟踪配置
auth = cognito
auth = custom

对于 REST API,生成的构造默认会将 AWS WAFv2 Web ACL 与 API Gateway 阶段关联。Web ACL 使用 AWS 托管的默认规则集(AWSManagedRulesCommonRuleSetAWSManagedRulesKnownBadInputsRuleSet),提供针对常见 Web 漏洞(包括 OWASP Top 10)的保护。WAF 请求日志会写入 CloudWatch Logs 日志组。

您可以编辑生成的 rest-api 构造来添加、删除或调整规则(例如,添加基于速率的规则或其他托管规则组)。

要选择退出(例如,附加您自己的 Web ACL),请将 enableWaf 设置为 false

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
enableWaf: false,
});

对于 REST API,生成的基础设施默认启用访问日志,为每个请求向专用的 CloudWatch Logs 日志组写入一行结构化的 JSON。该日志组使用客户管理的 KMS 密钥加密,并保留一年。

API Gateway 使用账户级别的 CloudWatch Logs 角色写入访问日志。此角色在 AWS::ApiGateway::Account 设置上配置,该设置是每个区域每个账户的单例 — 区域中的每个 REST API 只有一个角色。为了在多个独立部署的堆栈中安全地管理此角色,生成的基础设施:

  • 仅在尚未设置有效角色时创建共享的 CloudWatch Logs 角色并在账户上配置它,因此部署永远不会覆盖另一个堆栈拥有的角色。
  • 在拆除时保持账户设置不变,因此销毁一个堆栈永远不会禁用区域中其他 REST API 的日志记录。

账户角色由 ApiGatewayAccount 构造管理,这是一个通过 ApiGatewayAccount.ensure(scope) 解析的堆栈范围单例。每个 REST API 的阶段都依赖于它,该角色由 Lambda 支持的自定义资源配置。

访问日志格式由您的 API 扩展的 RestApi 构造设置。要自定义它,请在生成的 packages/common/constructs/src/app/apis/my-api.ts 中将 deployOptions 传递给 super,同时保留构造已设置的 tracingEnabled

packages/common/constructs/src/app/apis/my-api.ts
super(scope, id, {
apiName: 'MyApi',
// ...
deployOptions: {
tracingEnabled: true,
accessLogFormat: AccessLogFormat.clf(),
},
...props,
});

AccessLogFormataws-cdk-lib/aws-apigateway 导入。任何未设置的内容都会保留构造的默认值 — 一个包含标准字段的 JSON 格式。

REST/HTTP API CDK 构造被配置为提供类型安全的接口,用于为每个操作定义集成。

CDK 构造提供完整的类型安全集成支持,如下所述。

您可以使用静态方法 defaultIntegrations 来使用默认模式,该模式为每个操作定义一个单独的 AWS Lambda 函数:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});

您可以通过 API 构造的 integrations 属性以类型安全的方式访问底层的 AWS Lambda 函数。例如,如果您的 API 定义了一个名为 sayHello 的操作,并且您需要向该函数添加一些权限,可以按如下方式操作:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
// sayHello is typed to the operations defined in your API
api.integrations.sayHello.handler.addToRolePolicy(new PolicyStatement({
effect: Effect.ALLOW,
actions: [...],
resources: [...],
}));

如果您的 API 使用 shared 模式,共享的路由器 Lambda 将作为 api.integrations.$router 公开:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
api.integrations.$router.handler.addEnvironment('LOG_LEVEL', 'DEBUG');

如果您想自定义创建每个默认集成的 Lambda 函数时使用的选项,可以使用 withDefaultOptions 方法。例如,如果您希望所有 Lambda 函数都驻留在 Vpc 中:

const vpc = new Vpc(this, 'Vpc', ...);
new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withDefaultOptions({
vpc,
})
.build(),
});

要自定义用于创建_特定_操作的默认集成的选项(而不影响其他操作),可以使用 withOperationOptions 方法。例如,如果您想仅为一个操作增加 Lambda 函数超时时间:

const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOperationOptions({
sayHello: {
timeout: Duration.seconds(60),
},
})
.build(),
});
// The selected operations remain default integrations, so they're still typed accordingly:
api.integrations.sayHello.handler.addToRolePolicy(new PolicyStatement({ ... }));

您指定的选项将与默认集成选项(以及通过 withDefaultOptions 设置的任何选项)合并。请注意,您不能为通过 withOverrides 替换的操作指定选项,因为这些操作不再使用默认集成。

如果同一操作同时被 withOperationOptionswithOverrides 针对,无论您调用它们的顺序如何,都会遇到类型错误。

您还可以使用 withOverrides 方法覆盖特定操作的集成。每个覆盖必须指定一个 integration 属性,该属性的类型对应于 HTTP 或 REST API 的适当 CDK 集成构造。withOverrides 方法也是类型安全的。例如,如果您想覆盖 getDocumentation API 以指向某个外部网站托管的文档,可以按如下方式实现:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getDocumentation: {
integration: new HttpIntegration('https://example.com/documentation'),
},
})
.build(),
});

您还会注意到,当通过 api.integrations.getDocumentation 访问时,被覆盖的集成不再具有 handler 属性。

您可以向集成添加额外的属性,这些属性也将相应地进行类型化,从而允许其他类型的集成被抽象但保持类型安全。例如,如果您为 REST API 创建了 S3 集成,并且稍后希望引用特定操作的存储桶,可以按如下方式操作:

const storageBucket = new Bucket(this, 'Bucket', { ... });
const apiGatewayRole = new Role(this, 'ApiGatewayS3Role', {
assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
});
storageBucket.grantRead(apiGatewayRole);
const api = new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getFile: {
bucket: storageBucket,
integration: new AwsIntegration({
service: 's3',
integrationHttpMethod: 'GET',
path: `${storageBucket.bucketName}/{fileName}`,
options: {
credentialsRole: apiGatewayRole,
requestParameters: {
'integration.request.path.fileName': 'method.request.querystring.fileName',
},
integrationResponses: [{ statusCode: '200' }],
},
}),
options: {
requestParameters: {
'method.request.querystring.fileName': true,
},
methodResponses: [{
statusCode: '200',
}],
}
},
})
.build(),
});
// Later, perhaps in another file, you can access the bucket property we defined
// in a type-safe manner
api.integrations.getFile.bucket.grantRead(...);

您还可以在集成中提供 options 来覆盖特定的方法选项,例如授权器。例如,如果您希望为 getDocumentation 操作使用 Cognito 身份验证:

new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this)
.withOverrides({
getDocumentation: {
integration: new HttpIntegration('https://example.com/documentation'),
options: {
authorizer: new CognitoUserPoolsAuthorizer(...) // for REST, or HttpUserPoolAuthorizer for an HTTP API
}
},
})
.build(),
});

如果您愿意,可以选择不使用默认集成,而是直接为每个操作提供一个集成。这在以下情况下很有用,例如,每个操作需要使用不同类型的集成,或者您希望在添加新操作时收到类型错误:

new MyApi(this, 'MyApi', {
integrations: {
sayHello: {
integration: new LambdaIntegration(...),
},
getDocumentation: {
integration: new HttpIntegration(...),
},
},
});

生成的 CDK API 构造支持两种集成模式:

  • isolated 为每个操作创建一个 Lambda 函数。这是生成的 API 的默认设置。
  • shared 创建一个默认路由器 Lambda 并将其重用于每个操作,除非您覆盖特定集成。

isolated 为您提供更细粒度的每个操作权限和配置。shared 减少了 Lambda 和 API Gateway 集成的扩散,同时仍允许选择性覆盖。

例如,将 pattern 设置为 'shared' 会创建一个函数,而不是每个集成一个函数:

packages/common/constructs/src/app/apis/my-api.ts
export class MyApi<...> extends ... {
public static defaultIntegrations = (scope: Construct) => {
...
return IntegrationBuilder.rest({
pattern: 'shared',
...
});
};
}

由于操作在 Smithy 中定义,我们使用代码生成向 CDK 构造提供元数据以实现类型安全的集成。

一个 generate:<ApiName>-metadata 目标被添加到通用构造 project.json 中以促进此代码生成,它会发出一个文件,例如 packages/common/constructs/src/generated/my-api/metadata.gen.ts。由于这是在构建时生成的,因此在版本控制中被忽略。

auth = iam

如果您选择了 IAM 身份验证,您可以使用 grantInvokeAccess 方法授予对 API 的访问权限:

api.grantInvokeAccess(myIdentityPool.authenticatedRole);

要从 React 网站调用您的 API,您可以使用 connection 生成器,它从您的 Smithy 模型提供类型安全的客户端生成。

使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目:

Smithy
React to Smithy API从 React 网站调用 Smithy API
SmithyAmazon Aurora
Smithy API to Relational Database将 Smithy API 连接到 Aurora 关系数据库
SmithyAmazon DynamoDB
Smithy API to TypeScript DynamoDB将 Smithy API 连接到 DynamoDB 表