aws dynamodb
Last month, The Swift Core Team & Swift Server Work Group had announced the availability of Swift AWS Lambda Runtime as well as support of Swift on Amazon Linux 2 OS. With both of this announcement, we finally have some official support to run Swift on AWS Lambda environment.
上个月,Swift核心团队和Swift Server工作组宣布了Swift AWS Lambda Runtime的可用性以及对Amazon Linux 2 OS上Swift的支持。 有了这两个公告,我们终于获得了一些官方支持,可以在AWS Lambda环境上运行Swift。
Swift has many advantages such as low memory footprint, high performance, and quick start time. The Swift AWS Lambda runtime also uses SwiftNIO
to provide high performance non blocking networking engine for us to run asynchronous event driven code.
Swift具有许多优势,例如低内存占用,高性能和快速启动时间。 Swift AWS Lambda运行时还使用SwiftNIO
为我们提供了高性能的非阻塞网络引擎,以运行异步事件驱动的代码。
The runtime itself provides built-in support for many Lambda supported events such as HTTP request event from API Gateway, S3 object storage event, Simple Notification Service, and Simple Queue Service.
运行时本身为许多Lambda支持的事件提供了内置支持,例如来自API网关的HTTP请求事件,S3对象存储事件,简单通知服务和简单队列服务。
我们将建立什么 (What We Will Build)
In this tutorial, we’ll build a simple Swift Serverless REST API endpoints to create, update, delete, and retrieve list of todo. Here are the topics we’ll learn:
在本教程中,我们将构建一个简单的Swift Serverless REST API端点,以创建,更新,删除和检索待办事项列表。 以下是我们将学习的主题:
- Swift Lambda Runtime to handle API Gateway request event. Swift Lambda Runtime来处理API网关请求事件。
- Swift AWS DynamoDB SDK to persist the todo data in the Cloud. Swift AWS DynamoDB SDK将待办事项数据持久存储在云中。
- SwiftNIO to handle asynchronous event processing in network using EventLoopFuture. SwiftNIO使用EventLoopFuture处理网络中的异步事件处理。
- Docker to build and package the Swift binary ready for AWS Lambda Custom provided runtime. Docker构建和打包Swift二进制文件,可用于AWS Lambda Custom提供的运行时。
- Serverless Framework to provision and deploy to AWS Lambda with IAM Role. 无服务器框架,以IAM角色调配和部署到AWS Lambda。
You can download the completed project Source from the GitHub repository. I have provided the backend
and iOS client
app under one repository. Please follow the instruction on the README
file to build.
您可以从GitHub存储库下载完整的项目源。 我在一个存储库下提供了backend
和iOS client
应用程序。 请按照README
文件上的说明进行构建。
You can also watch the full video tutorial from YouTube.
您也可以观看YouTube上的完整视频教程。
Let’s begin to create a new Swift project and build the Todos REST API app!
让我们开始创建一个新的Swift项目并构建Todos REST API应用程序!
项目和依赖项设置 (Project & Dependencies Setup)
First, let’s open terminal, create a new directory named TodoAPI. You can put it anywhere you want.
首先,让我们打开终端,创建一个名为TodoAPI的新目录。 您可以将其放置在任何位置。
mkdir TodoAPI && cd TodoAPI
Create a new swift executable using swift package init passing executable to the type flag. If you are using macOS, double click on the Package.swift
file to open the project in Xcode automatically.
使用swift包init将可执行文件传递给type标志来创建一个新的swift可执行文件。 如果您使用的是macOS,请双击Package.swift
文件以自动在Xcode中打开项目。
swift package init --type executable
Let’s add the required dependencies for our backend app. Open Package.swift file from the navigator and copy the following code.
让我们为后端应用程序添加必需的依赖项。 从导航器中打开Package.swift文件,然后复制以下代码。
Here’s the things the we have added in the package:
这是我们在软件包中添加的内容:
macOS v10_14
as the platform.macOS v10_14
为平台。Swift AWS Lambda Runtime package provided by The Swift Server Work Group, currently the version is
0.2.0
and its in pre-release stage.由The Swift Server Work Group提供的Swift AWS Lambda Runtime软件包,当前版本是
0.2.0
并且处于预发行阶段。- Swift AWS SDK, this package provides native Swift API for us to interact with various AWS Services such as DynamoDB, S3, and many more. Swift AWS SDK,此软件包为我们提供了本机Swift API,可与各种AWS服务(例如DynamoDB,S3等)进行交互。
AWSDynamoDB, AWSLambdaRuntime, and AWSLambdaEvents added as the dependencies into the
TodoAPI
target.将AWSDynamoDB,AWSLambdaRuntime和AWSLambdaEvents作为依赖项添加到
TodoAPI
目标中。
Make sure to save the file using Command + S
shortcut. This will download and the resolve all the dependencies. You can view the progress from the dependencies section on the navigator.
确保使用Command + S
快捷方式保存文件。 这将下载并解析所有依赖项。 您可以从导航器上的“依赖项”部分查看进度。
After all packages has been downloaded, try to build and run to make sure there is no build time error.
下载所有软件包后,尝试构建并运行以确保没有构建时间错误。
处理函数调用 (Handling Function Invocation)
Let’s explore on how AWS Lambda Runtime handle the function invoked. There are 2 types of handler provided by the Swift AWS Lambda Runtime.
让我们探讨一下AWS Lambda Runtime如何处理调用的函数。 Swift AWS Lambda运行时提供了两种处理程序。
The first one is to use closure/callback. In this example, the request payload is a string, it can be also a JSON that conforms to decodable, and various AWS events such as S3, API Gateway, and many more. Make sure to invoke callback passing the response we want to return in the function.
第一个是使用闭包/回调。 在此示例中,请求有效负载是一个字符串,它也可以是符合可解码的JSON,以及各种AWS事件,例如S3,API Gateway等。 确保调用回调以传递要在函数中返回的响应。
import AWSLambdaRuntimeLambda.run { (context, payload: String, callback) in
callback(.success("Hello, \(payload)"))
}
The second one is to use EventLoopLambdaHandler
, which is more suited to performance sensitive function, in this case the function will run in the same thread as the networking handlers, so no need for performance cost because of context switching between networking and processing threads. It used SwiftNIO EventLoop
primitives, in this case our handler will return an event loop.
第二种方法是使用EventLoopLambdaHandler
,它更适合对性能敏感的功能,在这种情况下,该功能将在与网络处理程序相同的线程中运行,因此由于在网络线程和处理线程之间进行上下文切换,因此不需要性能成本。 它使用了SwiftNIO EventLoop
原语,在这种情况下,我们的处理程序将返回一个事件循环。
If you are familiar with Javascript, the EventLoop
concept is very similar to a Promise
, which means the value will be resolved in the future
. We’ll be using the EventLoopLambdaHandler
to build our REST API.
如果您熟悉Javascript,则EventLoop
概念与Promise
非常相似,这意味着该值将在future
得到解决。 我们将使用EventLoopLambdaHandler
来构建REST API。
建立Todo模型 (Building Todo Model)
Let’s create the model for the Todo first, create new directory named Models, and create a new Swift file named Todo. Then, let’s create a Todo struct that conforms to Codable protocol. It has six properties:
让我们首先为Todo创建模型,创建名为Models的新目录,并创建名为Todo的新Swift文件。 然后,让我们创建一个符合Codable协议的Todo结构。 它具有六个属性:
id
asString
.id
为String
。name
asString
.name
为String
。isCompleted
asBoolean
.isCompleted
为Boolean
。dueDate
,createdAt
,updatedAt
asDate
.dueDate
,createdAt
,updatedAt
的Date
。
Also to help us later when writing the model to dynamoDB dictionary, let’s create a struct named DynamoDBField
inside Todo struct. In this case, we just need to provide the key for each of the property using static constant.
为了在以后将模型写入dynamoDB字典时为我们提供帮助,让我们在Todo结构中创建一个名为DynamoDBField
结构。 在这种情况下,我们只需要使用静态常量为每个属性提供键。
public struct Todo: Codable {
public let id: String
public let name: String
public let isCompleted: Bool
public var dueDate: Date?
public var createdAt: Date?
public var updatedAt: Date?
public struct DynamoDBField {
static let id = "id"
static let name = "name"
static let isCompleted = "isCompleted"
static let dueDate = "dueDate"
static let createdAt = "createdAt"
static let updatedAt = "updatedAt"
}
}
建筑公用事业ISO8601日期格式 (Building Utils ISO8601 Date Formatter)
Let’s create a new file name Utils.swift
, we’ll use this to store the date formatter using ISO8601
format using the static constant inside the Utils struct. As DynamoDB doesn’t provide support to store date as data type, we need to convert the date to the ISO8601 string using the formatter and store the date as string.
让我们创建一个新文件名Utils.swift
,我们将使用Utils结构内部的静态常量使用ISO8601
格式存储日期格式程序。 由于DynamoDB不支持将日期存储为数据类型,因此我们需要使用格式化程序将日期转换为ISO8601字符串并将日期存储为字符串。
```
public struct Utils {
public static let iso8601Formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
return formatter
}()
}extension Date {
var iso8601: String {
Utils.iso8601Formatter.string(from: self)
}
}
Below, let’s create a simple extension for Date
to convert the instance to iso8601 string
using computed property
. In this case, we just need to use Utils date formatter to convert to the date using the string(fromDate:)
method passing self
as the parameter.
在下面,让我们为Date
创建一个简单的扩展,以使用computed property
将实例转换为iso8601 string
。 在这种情况下,我们只需要使用Utils日期格式化程序,就可以使用将self
作为参数的string(fromDate:)
方法转换为日期。
用APIError表示错误 (Representing Error with APIError)
Next, create a new file named APIError
. We declare the APIError
as enum
that conforms to Swift Error protocol. Let’s declare 3 cases:
接下来,创建一个名为APIError
的新文件。 我们将APIError
声明为符合Swift Error协议的enum
。 让我们声明3种情况:
decodingError
decodingError
requestError
requestError
todoNotFound
todoNotFound
Todo模型扩展,用于DynamoDB项目的编码和解码 (Todo Model Extension For Encoding and Decoding of DynamoDB Item)
Next, create a new file named Todo+DynamoDB.swift
. In this file, we’ll create an extension for Todo that will help us to convert Todo instance to dynamoDB dictionary. This will be used when we want to create and update item into DynamoDB. Make sure to import DynamoDB at the top of the source file.
接下来,创建一个名为Todo+DynamoDB.swift
的新文件。 在此文件中,我们将为Todo创建扩展名,以帮助我们将Todo实例转换为dynamoDB字典。 当我们要创建项目并将其更新到DynamoDB中时,将使用此方法。 确保在源文件的顶部导入DynamoDB。
The dictionary uses String
as the key and DynamoDB.AttributeValue
as the value. We’ll use the DynamoDBField
constant that we have declared before inside Todo Struct as the key. Then, we can initialize DynamoDB.AttributeValue
instance passing the correct data type, for string it will be s:
and boolean is bool:
. Make sure to convert the Date
into the String
before putting it into the dictionary.
字典使用String
作为键,并使用DynamoDB.AttributeValue
作为值。 我们将使用在Todo Struct内部之前声明的DynamoDBField
常量作为键。 然后,我们可以初始化DynamoDB.AttributeValue
实例,并传递正确的数据类型,对于字符串,它将为s:
,布尔值为bool:
DynamoDB.AttributeValue
在将Date
放入字典之前,请确保将Date
转换为String
。
Next, we also need to create an initializer
that accepts DynamoDB Dictionary to initialize Todo instance. This will be used later when we retrieve todo items from DynamoDB SDK.
接下来,我们还需要创建一个initializer
接受DynamoDB字典初始化的Todo实例。 当我们从DynamoDB SDK检索待办事项时,将使用此方法。
In this case, using the guard statement, we make sure all the properties exists in the dictionary and can be casted to the actual data type before we assign them to the properties. If one of them is not exists or the data type is incompatible, we throw a DecodingError
.
在这种情况下,使用guard语句,我们确保所有属性都存在于字典中,并且可以在将它们分配给属性之前将其强制转换为实际的数据类型。 如果其中之一不存在或数据类型不兼容,则抛出DecodingError
。
构建Todo服务以与AWS DynamoDB SDK进行交互 (Building The Todo Service to Interact with AWS DynamoDB SDK)
Let’s move on to create TodoService
, this service has the responsibility to interact with AWSDynamoDB SDK to get list of items and also to read, create, update, and delete a single item.
让我们继续创建TodoService
,此服务负责与AWSDynamoDB SDK交互以获取项目列表,以及读取,创建,更新和删除单个项目。
Create a new file named TodoService.swift
file and import AWS DynamoDB at the top of the source file. Declare TodoService class
, we’ll need 2 instance property. First is the instance of DynamoDB itself, the second one is the tableName
of the todo item in AWS. We create an initializer to inject those 2 properties.
创建一个名为TodoService.swift
文件的新文件,然后在源文件顶部导入AWS DynamoDB。 声明TodoService class
,我们需要2个实例属性。 第一个是DynamoDB本身的实例,第二个是AWS中todo项的tableName
。 我们创建一个初始化器来注入这两个属性。
获取待办事项列表 (Get Todos List)
Next, create a new method named getAllTodos
that returns an EventLoopFuture
of Todo Array
. In the implementation, we need to create the DynamoDB ScanInput
instance passing the tableName
. Next, we can use the dynamoDB scan method passing the input. We’re going to chain
the ScanOutput
to todos array using the FlatMapThrowing
operator, if you are familiar with Javascript promise
pattern, you can think of this as the then
. In case of this, as the mapping can throw
an error, we need to use FlatMapThrowing
operator.
接下来,创建一个名为getAllTodos
的新方法,该方法返回Todo Array
的EventLoopFuture
。 在实现中,我们需要创建传递tableName
的DynamoDB ScanInput
实例。 接下来,我们可以使用dynamoDB扫描方法传递输入。 我们要去chain
的ScanOutput
使用到待办事项阵列FlatMapThrowing
运营商,如果你熟悉JavaScript promise
的模式,你可以认为这为then
。 在这种情况下,由于映射可能会throw
错误,因此我们需要使用FlatMapThrowing
运算符。
获取单个待办事项 (Get Single Todo Item)
Let’s create the method to read a single item given an ID
of the Todo. We give it a name of getTodo
and pass id
of type String
as single parameter. This will return an EventLoopFuture
of Todo
. In the implementation, we use the DynamoDB’s GetItemInput
passing the key
, which is the dictionary containing the id key
and DynamoDB Attribute value of String
, we also need to pass the tableName
. Then, we can use the GetItem
passing the input as the parameter. We use FlatMapThrowing
to convert the GetItemOutput
to the Todo instance
passing the dictionary from the item, also if the output’s item is nil
, we’ll throw a TodoNotFound APIError
.
让我们创建一种方法来读取给定Todo ID
的单个项目。 我们给它命名为getTodo
,并将String
类型的id
作为单个参数传递。 这将返回Todo
的EventLoopFuture
。 在实现中,我们使用DynamoDB的GetItemInput
传递key
,该key
是包含id key
和DynamoDB Attribute value of String
的字典,我们还需要传递tableName
。 然后,我们可以使用GetItem
传递输入作为参数。 我们使用FlatMapThrowing
的转换GetItemOutput
到Todo instance
通过字典从项目,此外,如果输出的产品nil
,我们会扔一个TodoNotFound APIError
。
创建待办事项 (Create Todo)
For creating todo, create a new method named createTodo
with a single parameter of Todo
Model, the return type is EventLoopFuture
of Todo. In the implementation, we copy
the Todo struct to a new variable, then initialize current date. Then, we assign the updatedAt
and createdAt
property with the date. Next, we create a DynamoDB’s PutItemInput
passing the todo dynamoDB dictionary using the computed property we created before as well as the tableName
. At last we invoke putItem
method on the DB passing the input. In this case, we can just return the instance of Todo.
要创建待办事项,请使用一个Todo
Model参数创建一个名为createTodo
的新方法,返回类型为Todo的EventLoopFuture
。 在实现中,我们copy
Todo结构copy
到新变量,然后初始化当前日期。 然后,我们分配updatedAt
和createdAt
与日期属性。 接下来,我们使用之前创建的计算属性以及tableName
创建一个传递todo dynamoDB字典的DynamoDB的PutItemInput
。 最后,我们在传递输入的DB上调用putItem
方法。 在这种情况下,我们可以只返回Todo的实例。
更新待办事项 (Update Todo)
For updating Todo, create a new method named updateTodo
with a single parameter of Todo
Model, the return type is EventLoopFuture
of Todo. Create a new variable to copy
the Todo struct instance, then we just assign the updatedAt
with current Date. Implementation of UpdateItemInput
is quite complex compared to CreateItemInput
. We’ll need to create the expressionAttributeNames
Array containing the keys we want to update, then we create the expressionAttributeValues
Array which are the values we want to update. Pass the key, which is the ID
, returnValues
to allNew
, then make sure to pass the tableName
, at last we use the update expression literal
passing the placeholder attribute names and values
we have created. At last, we can use the updateItem
passing the input, then using FlatMap
, we invoke the getTodo
item passing the ID
to return a EventLoopFuture
of Todo.
要更新Todo,请使用Todo
Model的单个参数创建一个名为updateTodo
的新方法,返回类型为Todo的EventLoopFuture
。 创建一个新变量以copy
Todo struct实例,然后我们将updatedAt
分配给当前Date。 与CreateItemInput
相比, UpdateItemInput
实现非常复杂。 我们需要创建包含要更新的键的expressionAttributeNames
Array,然后创建expressionAttributeValues
Array,它们是我们想要更新的值。 将ID
, returnValues
的键传递给allNew
,然后确保传递tableName
,最后,我们使用update expression literal
传递所创建的placeholder attribute names and values
。 最后,我们可以使用updateItem
传递输入,然后使用FlatMap
,调用传递ID
的getTodo
项以返回Todo的EventLoopFuture
。
删除待办事项 (Deleting Todo)
At last, to delete an item, we need to create deleteTodo
method passing the id of string
as single parameter. The return type of this will be an EventFuture
of Void
. In the implementation, create DynamoDB deleteItemInput
passing the key
and tableName
. At last, we invoke the db’s deleteItemMethod
passing the input. Using map
we return a void closure
.
最后,要删除项目,我们需要创建deleteTodo
方法,将id of string
的id of string
作为单个参数传递。 此类型的返回类型将是EventFuture
of Void
。 在实现中,创建传递key
和tableName
DynamoDB deleteItemInput
。 最后,我们通过输入来调用数据库的deleteItemMethod
。 使用map
我们返回一个void closure
。
That’s it for the TodoService
class. With this, we’ll be able to perform CRUD
operation to DynamoDB! Let’s move on to create our LambdaHandler
!
TodoService
类就是这样。 这样,我们将能够对DynamoDB执行CRUD
操作! 让我们继续创建我们的LambdaHandler
!
构建TodoLambdaHandler来处理CRUD操作 (Building The TodoLambdaHandler to handle CRUD Operation)
Create a new file named TodoLambdaHandler.swift
. We need to import several frameworks into the source code.
创建一个名为TodoLambdaHandler.swift
的新文件。 我们需要将几个框架导入源代码。
import Foundation
import AWSLambdaEvents
import AWSLambdaRuntime
import AsyncHTTPClient
import NIO
import AWSDynamoDB
First, let’s declare the TodoLambdaHandler
as a struct
that implements EventLambdaHandler
Protocol. The protocol itself used associatedtype
for the event Input
and the response Output
. In our case, we’re going to use APIGateway Request
for the input event
and APIGateway Response
for the output response
. There are several other options you can explore such as S3, SQS, or DynamoDB events.
首先,让我们将TodoLambdaHandler
声明为实现EventLambdaHandler
协议的struct
。 协议本身将associatedtype
用于事件Input
和响应Output
。 在本例中,我们将使用APIGateway Request
来input event
并使用APIGateway Response
来output response
。 您可以探索其他几个选项,例如S3,SQS或DynamoDB事件。
struct TodoLamdaHandler: EventLoopLambdaHandler { typealias In = APIGateway.Request
typealias Out = APIGateway.Response let db: AWSDynamoDB.DynamoDB
let todoService: TodoService
let httpClient: HTTPClient
}
DynamoDB,HTTP客户端和TodoService的初始化 (Initialization of DynamoDB, HTTP Client, and TodoService)
Next, we need to create the initializer that accepts the Lambda.Initialization context
, basically we need to initialize the DynamoDB instance and TodoService
in the implementation.
接下来,我们需要创建一个接受Lambda.Initialization context
的初始化程序,基本上,我们需要在实现中初始化DynamoDB实例和TodoService
。
First let’s create HTTPClient
instance, we need to pass this when initializing DynamoDB later. Declare the timeout variable and initialize it with HTTPClient.Configuration.Timeout
passing 30 seconds
to both connect and read
parameters. Next, lets declare the httpClient
variable and initialize HTTPClient
passing the .shared
with the current context eventLoop
as the eventLoopGroupProvider
, then for the configuration, we initialize HTTPClient.Configuration
passing the timeout
variable we created before.
首先让我们创建HTTPClient
实例,稍后在初始化DynamoDB时需要传递此实例。 声明超时变量,并使用HTTPClient.Configuration.Timeout
对其进行初始化,将30 seconds
传递给connect and read
参数。 接着,让声明httpClient
变量和初始化HTTPClient
传递.shared
与当前上下文eventLoop
作为eventLoopGroupProvider
,那么对于该结构,我们初始化HTTPClient.Configuration
经过timeout
我们之前创建的变量。
Next, we need to retrieve the name of the table for our DynamoDB todo item, we’ll be storing the TODOS_TABLE_NAME
, AWS_REGION
, and _HANDLER
as the environment variables
when we we deploy our function to AWS Lambda.
接下来,我们需要检索DynamoDB todo项的表名,当我们将函数部署到AWS Lambda时,将存储TODOS_TABLE_NAME
, AWS_REGION
和_HANDLER
作为environment variables
。
To retrieve the environment variable, we can use Lambda.env
static method passing the name of the variable we want to retrieve from the environment.
要检索环境变量,可以使用Lambda.env
静态方法传递要从环境中检索的变量的名称。
Declare the tableName
constant and pass the string of TODOS_TABLE_NAME
as the parameter.
声明tableName
常量,并将TODOS_TABLE_NAME
的字符串作为参数传递。
For the region, we pass AWS_REGION
as the parameter, then using the value, we initialize the Region
enum passing it to the rawValue
parameter, if it doesn’t exists, we provide a default fallback
region which is us-west-2
located at Oregon, US.
对于区域,我们传递AWS_REGION
作为参数,然后使用该值,初始化Region
枚举,将其传递给rawValue
参数,如果不存在,我们提供default fallback
区域,该区域位于us-west-2
美国俄勒冈州。
Next, we need to initialize the AWSDynamoDB instance. Declare the db constant and using DynamoDB initializer we pass the region and the httpClientProvider
.
接下来,我们需要初始化AWSDynamoDB实例。 声明db常量,并使用DynamoDB初始化程序传递区域和httpClientProvider
。
For the TodoService
, we can initialize it passing the instance of the db
and the tableName
.
对于TodoService
,我们可以通过db
实例和tableName
对其进行初始化。
At last, we assign all the property into the instance properties so we can reference to them later. That’s it for the initialization! we have the DB instance and TodoService to perform the CRUD handling operation.
最后,我们将所有属性分配给实例属性,以便稍后引用它们。 初始化就这样! 我们有数据库实例和TodoService来执行CRUD处理操作。
使用处理程序枚举处理CRUD操作 (Handling CRUD Operation with Handler Enum)
There is one required method we need to implement acting as the entry-point when handling the request into our app. It is handle(context:event:)->EventLoopFuture
. This will be invoked passing the context and the request API Gateway
event containing the HTTP payload
. The return type expected is EventLoopFuture API Gateway response
which is the representation of the HTTP response
we want to return to the client.
处理对我们应用程序的请求时,我们需要实现一种必需的方法,作为入口点。 它是handle(context:event:)->EventLoopFuture
。 将通过上下文和包含HTTP payload
的request API Gateway
事件来调用此方法。 预期的返回类型是EventLoopFuture API Gateway response
,它是我们要返回给客户端的HTTP response
的表示。
As we are going to use a single binary
to perform all the CRUD operations, we need to be able to know the type of the operation we need to perform when user hits our API. To do this, we need to create an enum
named Handler
. Basically, this enum represents all the supported operations in our API.
由于我们将使用single binary
执行所有CRUD操作,因此我们需要能够知道用户点击我们的API时需要执行的操作类型。 为此,我们需要创建一个名为Handler
的enum
。 基本上,该枚举代表了我们API中所有受支持的操作。
Create a new file named Handler
inside Model
folder. Import AWSLambdaRuntime
at the top, and then declare enum Handler with type of String
. Our API supports five different operations, create, update, delete, read, and list
. To get the handler value, we’ll declare a static computed property named current that returns the handler. We’ll retrieve the handler from the environment variable named _HANDLER
, we will set this environment variable for each of the operation when we deploy our function later using Serverless framework.
在Model
文件夹中创建一个名为Handler
的新文件。 在顶部导入AWSLambdaRuntime
,然后声明String
类型的枚举Handler。 我们的API支持五种不同的操作,即create, update, delete, read, and list
。 为了获得处理程序的值,我们将声明一个名为current的静态计算属性,该属性返回处理程序。 我们将从名为_HANDLER
的环境变量中检索处理程序,稍后在使用无服务器框架部署函数时,将为每个操作设置此环境变量。
enum Handler: String {
case create
case update
case delete
case read
case list
static var current: Handler? {
guard let handler = Lambda.env("_HANDLER") else {
return nil
}
return Handler(rawValue: handler)
}
}
API网关请求和响应扩展 (Extension For API Gateway Request And Response)
Before implementing the handler method, let’s create a helper extension for the APIGateway Request and Response
that will help us to decode
the request into the Model
and encode
the model into the response as JSON
string.
在实现处理程序方法之前,让我们为APIGateway Request and Response
创建一个帮助程序扩展,它将帮助我们将请求decode
为Model
,并将模型encode
为JSON
字符串。
Create a new folder named extensions
, then create a new file named APIGateway+Extension.swift
inside. At the top import Foundation
and AWSLambdaEvents
.
创建一个名为extensions
的新文件夹,然后在其中创建一个名为APIGateway+Extension.swift
的新文件。 在顶部导入Foundation
和AWSLambdaEvents
。
First, let’s declare the extension for the APIGateway.Request
. We declare one helper method that will help us to decode the JSON body of the request to a Decodable
type using generic
placeholder. Let’s declare the jsonDecoder
static constant and set the date decoding strategy to custom formatter passing the ISO8601 date formatter
from the Utils struct.
首先,让我们声明APIGateway.Request
的扩展名。 我们声明了一个辅助方法,该方法将帮助我们使用generic
占位符将请求的JSON主体解码为Decodable
类型。 让我们声明jsonDecoder
静态常量,并设置日期格式传递解码策略来定制ISO8601 date formatter
从utils的结构。
In the bodyObject
implementation, using the if let
statement, we check whether the body data exists, if not we throw a Request Error
. Then, using the JSON decoder
, we just decode the type passing the jsonData
, and finally return the decoded
instance.
在bodyObject
实现中,使用if let
语句检查主体数据是否存在,如果不存在,则抛出Request Error
。 然后,使用JSON decoder
,我们仅解码传递jsonData
的类型,最后返回decoded
实例。
Next, let’s create the helper extension for APIGateway Response
. Let’s begin by declaring the jsonEncoder
static constant. Similar to the JSONDecoder
, we set the dateDecodingStrategy
to use custom ISO8601
date formatter.
接下来,让我们为APIGateway Response
创建帮助程序扩展。 让我们首先声明jsonEncoder
静态常量。 类似于JSONDecoder
,我们设置dateDecodingStrategy
使用自定义的ISO8601
日期格式。
Next, lets’ declare the constant for the defaultHeaders
. The value itself is a dictionary with type of String
as the key and value. This will be used to set the HTTP response headers
to allow CORS
when invoked from a website and to allow all HTTP methods.
接下来,让我们声明defaultHeaders
的常量。 该值本身是一个字典,以String
类型为键和值。 这将用于设置HTTP response headers
,以便从网站调用时允许CORS
,并允许所有HTTP方法。
Let’s move on to create a new initializer that accepts error and AWSLambdaEvents.HTTPResponseStatus
. In this case we just invoke the initializer
passing the status code
, then pass the defaultHeaders
to the HTTP headers, also in the body we pass hardcoded JSON
string with the key of error and string value of the error. We’ll use this later when we want to return an error as the response.
让我们继续创建一个新的初始化器,该初始化器接受error和AWSLambdaEvents.HTTPResponseStatus
。 在这种情况下,我们只调用传递status code
的initializer
status code
,然后将defaultHeaders
传递给HTTP标头,同样在主体中,我们传递带有错误键和错误字符串值的hardcoded JSON
字符串。 当我们要返回错误作为响应时,将在以后使用它。
The second initializer
accepts an encodable
object using generic
placeholder and the HTTPResponseStatus
. This will be helpful later when we want to return instance of Todo or Todo array as they both conforms to Codable
protocol. In the implementation, we encode the instance using JSONEncoder
and assign the String
of the data to the body variable using UTF-8
encoding. At last, we invoke the initializer passing the status code, defaultHeaders, and the body.
第二个initializer
使用generic
占位符和HTTPResponseStatus
接受可encodable
对象。 当我们想返回Todo或Todo数组的实例时,这将很有帮助,因为它们都符合Codable
协议。 在实现中,我们使用JSONEncoder
编码实例,并使用UTF-8
编码将数据的String
分配给主体变量。 最后,我们调用初始化器,传递状态码,defaultHeaders和主体。
At the bottom, create a new Struct named EmptyResponse
that conforms to Encodable
. The implementation is empty, as this will be used when we want to return a response with empty body such as when deleting a Todo item.
在底部,创建一个新的Struct,名为EmptyResponse
,它符合Encodable
。 该实现是空的,因为当我们要返回带有空正文的响应时(例如删除Todo项时),将使用该实现。
实现Todo Lambda处理程序 (Implementing Todo Lambda Handler)
Finally, let’s move back to the TodoLambdaHandler
to implement the handler method!
最后,让我们回到TodoLambdaHandler
来实现handler方法!
使用枚举处理程序枚举作为主处理程序传入事件 (Using Enum Handler Enum as Main Handler Incoming Event)
First, let’s use a guard
statement to get the current type of the handler operation using the Handler.current
static property, if it is not exits, we just return a resolved successful eventLoopFuture
passing the APIGateway.Response
instance with APIError
and badRequest
HTTP Status Type. This will returns the response with 40
` as the HTTP Status code containing the error message in the body.
首先,让我们使用guard
语句通过Handler.current
静态属性获取处理程序操作的当前类型,如果未退出,我们只需返回已resolved successful eventLoopFuture
并通过APIGateway.Response
实例APIError
和badRequest
HTTP状态类型。 这将返回与响应40
`作为包含在体内的错误消息的HTTP状态代码。
Then, we use the switch statement on the enum instance to handle all the possible operations. We’ll create a method to handle each of the operation. All of them accept Lambda.Context
and APIGateway.Request
, then returns EventLoopFuture of APIGateway.Response
.
然后,我们在枚举实例上使用switch语句来处理所有可能的操作。 我们将创建一个方法来处理每个操作。 它们都接受Lambda.Context
和APIGateway.Request
,然后返回APIGateway.Response的APIGateway.Response
。
处理创建待办事项 (Handling Create Todo)
First, let’s declare the handleCreate
method to handle creating single Todo Item. Using the guard statement, we decode the request body to Todo instance, if it doesn’t exists, we return a resolved EventLoopFuture
passing the APIGateway.Response
of RequestError
and badRequest
httpStatus. Next, we invoke TodoService’s createTodo
method passing the todo instance. As this returns a Future
of Todo, we need to map it to APIGateway.Response
using the map
operator. In the closure body, we initialize the APIGateway.Response
passing the Todo instance and ok
as the HTTPResponseStatus
. This will encode the instance into the JSON data, then put in the response body and set the HTTP status code to 200.
首先,让我们声明handleCreate
方法来处理创建单个Todo Item的过程。 使用保护声明,我们请求主体进行解码,以藤例如,如果不存在的话,我们返回一个解决EventLoopFuture
传递APIGateway.Response
的RequestError
和badRequest
则httpStatus。 接下来,我们通过传递todo实例调用TodoService的createTodo
方法。 当这返回“ Future
的待办事项”时,我们需要使用map
运算符将其map
到APIGateway.Response
。 在闭包主体中,我们初始化APIGateway.Response
并传递Todo实例, APIGateway.Response
将其ok
为HTTPResponseStatus
。 这会将实例编码为JSON数据,然后放入响应正文并将HTTP状态代码设置为200。
Also in case there is an error in the eventLoop
chain, we need to catch it and return the appropriate error. Let’s declare a method named catchError
that accept a Lambda context and error as the parameter, then return EventLoopFuture
of APIGateway.Response
. In the body, we just need to initialize the APIGateway.Response
and pass the error, then return the resolved future passing the response.
同样,如果eventLoop
链中有错误,我们需要捕获它并返回适当的错误。 让我们声明一个名为catchError
的方法,该方法接受Lambda上下文和error作为参数,然后返回EventLoopFuture
的APIGateway.Response
。 在主体中,我们只需要初始化APIGateway.Response
并传递错误,然后返回已解析的将来传递的响应。
Going back to create method, to catch the error, we can use the flatMapError
operator. This will be invoked if there is an error thrown in one of the upstream
, think of this as the catch error promise
in Javascript. In this case, we can just invoke the catchError
method we created before to return the APIGateway.Response
.
回到create方法,要捕获错误,我们可以使用flatMapError
运算符。 如果upstream
之一抛出错误,则将调用此方法,将其视为Javascript中的catch error promise
。 在这种情况下,我们可以调用之前创建的catchError
方法来返回APIGateway.Response
。
处理读待办事项 (Handling Read Todo)
Next, let’s create the handleRead
method. In the implementation, we check if the pathParameters
dictionary contains value with key of id, if not we just return resolved promise of response with request error and http status 400. Then, we just need to invoke todoService’s getTodo
method passing the value of id. Using map
operator we transform the Todo instance to Response passing the todo instance to be encoded in the HTTP Body and set the status code to 200.
接下来,让我们创建handleRead
方法。 在实现中,我们检查pathParameters
词典是否包含带有id关键字的值,否则,我们只返回带有请求错误和http状态400的已解决响应承诺。然后,我们只需要调用todoService的getTodo
方法并传递id的值即可。 使用map
运算符,我们将Todo实例转换为Response,并传递要在HTTP正文中进行编码的todo实例,并将状态代码设置为200。
处理更新待办事项 (Handling Update Todo)
To update a todo item, let’s create the handleUpdate
method. Just like the handleCreate
method, using the guard
statement, we decode
the http body to Todo
instance. If fails, we just return resolved promise with response containing requestError
and 400 as the http status code. Then, we invoke todo’s service updateTodo
method passing the updatedTodo
item. Using the map operator, we transform the result of the todo item to APIGateway
passing the todo instance to be encoded as JSON in the HTTP body, and set the status code to 200.
要更新待办事项,我们创建handleUpdate
方法。 就像handleCreate
方法一样,我们使用guard
语句将http正文decode
为Todo
实例。 如果失败,我们只返回已解决的promise,响应中包含requestError
和400作为http状态代码。 然后,我们调用todo的服务updateTodo
方法,并传递updatedTodo
项目。 使用map运算符,我们将todo项的结果转换为APIGateway
并传递todo实例,以在HTTP正文中将其编码为JSON,并将状态代码设置为200。
处理删除待办事项 (Handle Delete Todo)
Next, let’s create the handleDelete
for deleting a todo item. Just like handleRead
method, we need to get the id to delete from the pathParameters
passing id as the key to the dictionary. After that, we just invoke todoService’s deleteTodo
method passing the id. In this case, we just need to return APIGateway response with empty body and status code of 200.
接下来,让我们创建handleDelete
来删除待办事项。 就像handleRead
方法一样,我们需要获取id以将id作为字典的键从pathParameters
删除。 在那之后,我们只是调用传递ID的todoService的deleteTodo
方法。 在这种情况下,我们只需要返回带有空主体和状态码200的APIGateway响应。
处理待办事项清单 (Handle List Todos)
The last handler, is the handleList
method. In this handler, we just invoke todoService’s getAllTodos
method, then transform the result of the Todo Array into APIGateway Response passing the array to be encoded as JSON into the HTTP body and set the status code as 200.
最后一个处理程序是handleList
方法。 在此处理程序中,我们仅调用todoService的getAllTodos
方法,然后将Todo数组的结果转换为APIGateway Response,将要编码为JSON的数组传递到HTTP正文中,并将状态代码设置为200。
That’s it for the TodoLambdaHandler
, now let’s put this into main.swift
where we will run the Lambda passing the handler.
TodoLambdaHandler
就是这样,现在将其放入main.swift
,在此我们将传递通过处理程序的Lambda。
Lambda.run(TodoLamdaHandler.init)
We have completed building the app, now let’s build the app and archive the app into a Zip file so it can be uploaded to AWS Lambda!
我们已经完成了应用程序的构建,现在让我们构建应用程序并将其存档到一个Zip文件中,以便可以将其上传到AWS Lambda!
使用Docker Swift Amazon Linux 2 Distro构建和打包 (Building and Packaging Using Docker Swift Amazon Linux 2 Distro)
Before we begin the process, make sure to install Docker into your operating system. Check the link to install docker from the description if you haven’t installed. We’re going to use Docker Container using official Swift Amazon Linux 2 Image to build the release, and package the binary into the bootstrap file required by the AWS Lambda to run the function.
在开始该过程之前,请确保将Docker安装到您的操作系统中。 如果尚未安装,请从说明中检查链接以安装docker。 我们将使用Docker Container和官方Swift Amazon Linux 2 Image来构建发行版,并将二进制文件打包到AWS Lambda所需的引导程序文件中,以运行该功能。
Let’s follow the instruction from Fabian Fett’s website. He is one of the contributor of the Swift AWS Lambda library. He posted a great tutorial on building and packaging Swift into the zip file ready to be used in AWS.
让我们按照Fabian Fett网站上的说明进行操作。 他是Swift AWS Lambda库的贡献者之一。 他发布了一篇很棒的教程,介绍如何将Swift构建和打包到zip文件中,以便在AWS中使用。
创建Dockerfile (Creating The Dockerfile)
In this step, we need to create a Dockerfile
on the project directory. So, let’s open terminal and navigate to the project directory. Then, create a new file named Dockerfile
. Open it in your editor, then copy and paste into the file.
在此步骤中,我们需要在项目目录上创建一个Dockerfile
。 因此,让我们打开终端并导航到项目目录。 然后,创建一个名为Dockerfile
的新文件。 在编辑器中将其打开,然后复制并粘贴到文件中。
FROM swiftlang/swift:nightly-amazonlinux2
RUN yum -y install \
git \
libuuid-devel \
libicu-devel \
libedit-devel \
libxml2-devel \
sqlite-devel \
python-devel \
ncurses-devel \
curl-devel \
openssl-devel \
tzdata \
libtool \
jq \
tar \
zip
This will use the the Swift Nightly image for Amazon Linux 2 from SwiftLang docker repository, then add the required dependencies to build and run Swift.
这将使用SwiftLang docker存储库中的Amazon Linux 2的Swift Nightly映像,然后添加所需的依赖项以构建和运行Swift。
Next, let’s build the container using the Dockerfile
. Let’s give it a name of swift-lambda-builder
. Type the following syntax.
接下来,让我们使用Dockerfile
构建容器。 让我们给它命名为swift-lambda-builder
。 输入以下语法。
docker build -t swift-lambda-builder .
从Docker容器构建应用 (Building The App from Docker Container)
Wait after the container are created, then let’s build the binary from the Docker container using this syntax.
在创建容器之后等待,然后让我们使用此语法从Docker容器构建二进制文件。
docker run \
--rm \
--volume "$(pwd)/:/src" \
--workdir "/src/" \
swift-lambda-builder \
swift build --product TodoAPI -c release
This will run the swift-lambda-builder
container and set the current directory as the working directory, then execute swift build command passing the TodoAPI
as the product flag and compile it in release mode.
这将运行swift-lambda-builder
容器并将当前目录设置为工作目录,然后执行swift build命令,将TodoAPI
作为产品标志传递,并在发布模式下进行编译。
创建脚本以存档应用程序和依赖项 (Creating Script to Archive App and Dependencies)
Next, let’s create package the executables for the deployment. Basically, we need to create the bootstrap
file and symlink all the executable
, we also need to copy
several Swift runtime library into the folder. To help us do this, let’s create shell script
. Create a new folder called scripts
, then inside the folder
, create a new shell file named package.sh
. Copy and paste the code into the file, replace SquareNumber
with TodoAPI
.
接下来,让我们创建用于部署的可执行文件的程序包。 基本上,我们需要创建bootstrap
文件并symlink all the executable
,我们还需要copy
几个Swift运行时库copy
到该文件夹中。 为了帮助我们做到这一点,让我们创建shell script
。 创建一个名为scripts
的新文件夹,然后在该folder
内创建一个名为package.sh
的新外壳文件。 将代码复制并粘贴到文件中,用SquareNumber
替换TodoAPI
。
#!/bin/bashset -euexecutable=$1target=.build/lambda/$executable
rm -rf "$target"
mkdir -p "$target"
cp ".build/release/$executable" "$target/"
cp -Pv \
/usr/lib/swift/linux/libBlocksRuntime.so \
/usr/lib/swift/linux/libFoundation*.so \
/usr/lib/swift/linux/libdispatch.so \
/usr/lib/swift/linux/libicu* \
/usr/lib/swift/linux/libswiftCore.so \
/usr/lib/swift/linux/libswiftDispatch.so \
/usr/lib/swift/linux/libswiftGlibc.so \
"$target"
cd "$target"
ln -s "$executable" "bootstrap"
zip --symlinks lambda.zip *
Don’t forget to set the file as executable using
不要忘记使用以下命令将文件设置为可执行文件
sudo chmod +x package.sh
Navigate back to project directory and run this syntax.
导航回到项目目录并运行此语法。
docker run \
--rm \
--volume "$(pwd)/:/src" \
--workdir "/src/" \
swift-lambda-builder \
scripts/package.sh TodoAPI
Just like before, this will run the swift-lambda-builder container
, then execute package.sh
inside the scripts folder.
和之前一样,这将运行swift-lambda-builder container
,然后在scripts文件夹中执行package.sh
。
We can check the result of the final zipped
package, by navigating to build/lambda/TodoAPI
. The Lambda.zip
file should exists in the directory.
我们可以通过导航到build/lambda/TodoAPI
来检查最终zipped
包的结果。 Lambda.zip
文件应存在于目录中。
That’s it for packaging! now let’s move on to the next step, where we will use Serverless framework
to handle deployment
of our function to AWS.
包装就是这样! 现在,我们继续下一步,使用Serverless framework
将功能deployment
到AWS。
使用无服务器框架进行配置和部署 (Provisioning And Deployment with Serverless Framework)
To begin, please make sure you have node.js
installed in your system, you can install using the installer from the official website or using brew package manager.
首先,请确保已在系统中安装了node.js
,可以使用官方网站上的安装程序或brew软件包管理器进行安装。
After that run:
在那之后运行:
sudo npm install -g serverless
I assume you have already setup the AWS credentials in your user directory ~/.aws/credentials
. If not, please create an IAM role
from AWS console with required privileges
, in my case, i usually provide full access to provision resources in my main machine.
我假设您已经在用户目录~/.aws/credentials
设置了AWS ~/.aws/credentials
。 如果不是,请使用required privileges
从AWS控制台创建一个IAM role
,在我的情况下,我通常提供对主机中预配置资源的完全访问权限。
To use serverless, we just need to create a Serverless yaml file in the project directory. This YAML contains all the declaration we need to provision the service. Let’s create serverless.yml
file in our project directory.
要使用无服务器,我们只需要在项目目录中创建一个无服务器yaml文件。 该YAML包含我们提供服务所需的所有声明。 让我们在项目目录中创建serverless.yml
文件。
Open it with your code editor, be very careful with indentation when editing a YAML file, as it uses indentation to structure the data. It is preferred to use spaces instead of tabs when editing YAML file. In this case i use 2 spaces for the indentation.
使用代码编辑器打开它,在编辑YAML文件时请小心使用缩进,因为它使用缩进来构造数据。 在编辑YAML文件时,最好使用空格而不是制表符。 在这种情况下,我使用2个空格作为缩进。
At the top, let’s declare the service
, you should provide your own unique
value here. In this case, i named it as alf-todoapi
. Next, declare the package
, inside the package, we have one key, artifact
. Let’s put the directory of where our Lambda.zip
is located inside the build
folder. This will be used for deploying to AWS later.
在顶部,让我们声明service
,您应该在此处提供自己的unique
值。 在这种情况下,我将其命名为alf-todoapi
。 接下来,声明package
,在package
内部,我们有一个键artifact
。 让我们将Lambda.zip
所在的目录放在build
文件夹中。 稍后将用于部署到AWS。
Next, lets’ declare custom key used for referencing resources in this YAML. We’ll have one key which is todosTableName
with value of todos-${self:provider.stage}
.
接下来,让我们声明用于引用此YAML中的资源的自定义键。 我们将拥有一个键,它是todosTableName
,其值为todosTableName
todos-${self:provider.stage}
。
Next, let’s declare the provider
. Inside the provider
, set the name to aws
and runtime as provided
. For stage
, we’ll set it as dev
, and region
to us-west-2
. For the `environment`, we have one variable, which is the TODOS_TABLE_NAME
and for the value we can retrieve it from the custom.todosTableName
we created earlier. Next, let’s declare the IAM role
for the functions. For our functions, we only provide 2 IAM role, one is to write logs to CloudWatch
, and the other one is to perform CRUD operation to DynamoDB
. Other than those 2, our function won’t be able to access other AWS services and resources.
接下来,让我们声明provider
。 在provider
内部,根据provider
的name to aws
将name to aws
设置name to aws
和runtime as provided
。 对于stage
,我们将其设置为dev
,并将region
为us-west-2
。 对于`environment`,我们有一个变量,即TODOS_TABLE_NAME
,对于该值,我们可以从custom.todosTableName
创建的custom.todosTableName
检索它。 接下来,让我们声明这些函数的IAM role
。 对于我们的功能,我们仅提供2个IAM角色,一个是write logs to CloudWatch
,另一个是perform CRUD operation to DynamoDB
。 除此之外,我们的功能将无法访问其他AWS服务和资源。
Next, let’s declare the functions. We have five functions that triggered from HTTP events.:
接下来,让我们声明功能。 我们有五个从HTTP事件触发的功能:
createTodo
with handler of create, we set the path to/todos
, method toPOST
, and enableCORS
.使用create处理程序的
createTodo
,我们将路径设置为/todos
,方法设置为POST
,并启用CORS
。readTodo
with handler of read, set the path to/todos/{id}
. method toGET
. theid
placeholder can be retrieved from thepathParameters
dictionary in the event request from API Gateway.具有读取处理程序的
readTodo
,将路径设置为/todos/{id}
。GET
方法。 可以在API网关发出的事件请求中从pathParameters
字典中检索id
占位符。updateTodo
with handler of update, set the path to/todos/{id}
and method toPUT
. Make sure to enableCORS
.具有更新处理程序的
updateTodo
,将路径设置为/todos/{id}
并将方法设置为PUT
。 确保启用CORS
。deleteTodo
with handler of delete, set the path to/todos/{id}
and method toDELETE
.具有删除处理程序的
deleteTodo
,将路径设置为/todos/{id}
并将方法设置为DELETE
。listTodos
with handler of list, set the path to/todos
and method toGET
.具有list处理程序的
listTodos
,将路径设置为/todos
,将方法设置为GET
。
The handler value itself can be accessed from the _HANDLER
environment variable. We are using that to initialize the handler operation in the code we have created.
可以从_HANDLER
环境变量访问处理程序值本身。 我们使用它来初始化我们创建的代码中的处理程序操作。
Next, we need to provision
the DynamoDB table resource. We need to put inside the resources
. Give it name of TodosTable
. The type is AWS::DynamoDB::Table
. For the properties, TableName
value can be retrieved from the custom.TodosTableName
variable. The AttributeDefinition
will have one single Attribute Name
which is used as the Key
for this table. Finally, set the BillingMode
as PAY_PER_REQUEST
.
接下来,我们需要provision
DynamoDB表资源。 我们需要投入resources
。 给它起名字TodosTable
。 类型是AWS::DynamoDB::Table
。 对于属性,可以从custom.TodosTableName
变量中检索TableName
值。 AttributeDefinition
将有一个单一的Attribute Name
,用作此表的Key
。 最后,将BillingMode
设置为PAY_PER_REQUEST
。
That’s it for the Serverless YAML file, you can learn more about Serverless by visiting the website that i provide in description below. Other than AWS, it also supports deployment to Google Cloud Function and Azure Function.
仅用于无服务器YAML文件,您可以通过访问我在下面的描述中提供的网站来了解有关无服务器的更多信息。 除AWS以外,它还支持部署到Google Cloud Function和Azure Function。
To deploy, from the project directory in terminal, we can just type:
要进行部署,可以从终端的项目目录中键入:
sls -v deploy
This will parse the serverless YAML, create the resources on CloudFormation, upload the code to S3 bucket, provision the DynamoDB table, and handle the creation of API Gateway for our function!
这将解析无服务器的YAML,在CloudFormation上创建资源,将代码上传到S3存储桶,提供DynamoDB表,并为我们的功能处理API网关的创建!
Wait until, the deployment has completed. The output will provide us the endpoint that we can use to hit our CRUD API. We can also check the AWS Lambda web dashboard to check the status and logs of our function. Try to use POSTMAN or CURL to hit the endpoint. In my case, i already provided the iOS client app in the completed project repository which you can use to test. It is built with SwiftUI and use CoreData to sync the data.
等到部署完成。 输出将为我们提供可用于访问CRUD API的端点。 我们还可以检查AWS Lambda Web仪表板以检查功能的状态和日志。 尝试使用POSTMAN或CURL命中端点。 就我而言,我已经在完整的项目存储库中提供了iOS客户端应用程序,您可以使用它来进行测试。 它使用SwiftUI构建,并使用CoreData同步数据。
结论 (Conclusion)
That’s if for this tutorial. To summarize, we have learned to build a backend REST API with Swift and DynamoDB as persistence layer in the cloud, then deploy it to AWS Lambda using Serverless framework. There are many other various cases we can use to build serverless app, such image processing after an image has been uploaded to S3 bucket, processing notification from SNS, and many more. Keep exploring, and i hope this video will be helpful to all of you.
如果是本教程的话。 总而言之,我们学习了使用Swift和DynamoDB作为云中的持久层构建后端REST API,然后使用无服务器框架将其部署到AWS Lambda。 我们可以使用许多其他各种情况来构建无服务器应用程序,例如,在将图像上传到S3存储桶后进行图像处理,处理来自SNS的通知等等。 继续探索,希望这段视频对大家都有用。
Until the next one, let’s keep the lifelong learning goes on. Bye!
在下一课之前,让我们继续进行终身学习。 再见!
aws dynamodb