├── .gitattributes
├── .gitignore
├── Samples
├── Avatar
│ ├── Dockerfile
│ └── Package.swift
├── JWT
│ ├── Dockerfile
│ ├── serverless.yml
│ ├── Package.swift
│ └── main.swift
├── Moderation
│ └── main.swift
└── ChatBot
│ └── main.swift
├── Dockerfile
├── Scripts
├── deploy.sh
├── package.sh
└── build-and-package.sh
├── handler.sh
├── Lambda.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── cardoso.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── GeneratedModuleMap
│ └── CBacktrace
│ │ └── module.modulemap
├── NIO_Info.plist
├── Backtrace_Info.plist
├── CBacktrace_Info.plist
├── CNIOAtomics_Info.plist
├── CNIODarwin_Info.plist
├── CNIOLinux_Info.plist
├── CNIOSHA1_Info.plist
├── Logging_Info.plist
├── NIOHTTP1_Info.plist
├── SwiftGD_Info.plist
├── AWSLambdaEvents_Info.plist
├── AWSLambdaRuntime_Info.plist
├── CNIOHTTPParser_Info.plist
├── AWSLambdaRuntimeCore_Info.plist
├── NIOConcurrencyHelpers_Info.plist
├── NIOFoundationCompat_Info.plist
└── xcshareddata
│ └── xcschemes
│ ├── Lambda.xcscheme
│ └── Lambda-Package.xcscheme
├── .github
└── workflows
│ └── swift.yml
├── serverless.yml
├── Sources
└── Lambda
│ └── main.swift
├── bootstrap
├── Package.swift
├── LICENSE
├── Package.resolved
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | * linguist-vendored
2 | *.swift linguist-vendored=false
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .build
2 | .swiftpm
3 | .serverless
4 | .DS_Store
5 | node_modules
6 |
--------------------------------------------------------------------------------
/Samples/Avatar/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM swift:5.3-amazonlinux2
2 |
3 | RUN yum -y install zip gd-devel
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM swift:5.3.1-amazonlinux2
2 |
3 | RUN yum -y install zip
4 | RUN yum -y install openssl-devel
5 |
--------------------------------------------------------------------------------
/Scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | sh ./Scripts/build-and-package.sh
2 | serverless deploy --config "./serverless.yml" --stage dev -v
3 |
--------------------------------------------------------------------------------
/Samples/JWT/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM swift:5.3.1-amazonlinux2
2 |
3 | RUN yum -y install zip
4 | RUN yum -y install openssl-devel
5 |
--------------------------------------------------------------------------------
/handler.sh:
--------------------------------------------------------------------------------
1 | function hello () {
2 | EVENT_DATA=$1
3 | echo "$EVENT_DATA" 1>&2;
4 | RESPONSE="{\"body\": {\"input\": $EVENT_DATA, \"msg\": \"Wecome to serverless!\"}}"
5 |
6 | echo $RESPONSE
7 | }
8 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/GeneratedModuleMap/CBacktrace/module.modulemap:
--------------------------------------------------------------------------------
1 | module CBacktrace {
2 | umbrella "/Users/cardoso/dev/getstream/swift-lambda/.build/checkouts/swift-backtrace/Sources/CBacktrace/include"
3 | export *
4 | }
5 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/project.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GetStream/swift-lambda/HEAD/Lambda.xcodeproj/project.xcworkspace/xcuserdata/cardoso.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: macos-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Build
17 | run: swift build
18 |
--------------------------------------------------------------------------------
/serverless.yml:
--------------------------------------------------------------------------------
1 | service: swift-lambda
2 |
3 | provider:
4 | name: aws
5 | runtime: provided
6 |
7 | package:
8 | artifact: .build/lambda/Lambda/lambda.zip
9 |
10 | functions:
11 | lambda:
12 | handler: handler.lambda
13 | events:
14 | - http:
15 | path: /
16 | method: post
17 |
--------------------------------------------------------------------------------
/Scripts/package.sh:
--------------------------------------------------------------------------------
1 | set -eu
2 |
3 | executable="Lambda"
4 |
5 | target=.build/lambda/$executable
6 | rm -rf "$target"
7 | mkdir -p "$target"
8 | cp ".build/release/$executable" "$target/"
9 | cp -Pv /usr/lib/swift/linux/lib*so* "$target"
10 | cd "$target"
11 | ln -s "$executable" "bootstrap"
12 | zip --symlinks lambda.zip *
--------------------------------------------------------------------------------
/Samples/JWT/serverless.yml:
--------------------------------------------------------------------------------
1 | service: swift-lambda
2 |
3 | provider:
4 | name: aws
5 | runtime: provided
6 |
7 | package:
8 | artifact: .build/lambda/Lambda/lambda.zip
9 |
10 | functions:
11 | lambda:
12 | handler: handler.lambda
13 | events:
14 | - http:
15 | path: /
16 | method: post
17 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Scripts/build-and-package.sh:
--------------------------------------------------------------------------------
1 | set -eu
2 |
3 | executable="Lambda"
4 |
5 | echo "preparing docker build image"
6 | docker build . -t builder
7 | echo "done"
8 |
9 | echo "building executable"
10 | docker run --rm -v "$(pwd)":/workspace -w /workspace builder bash -cl "swift build --product $executable -c release -Xswiftc -g"
11 | echo "done"
12 |
13 | echo "packaging lambda"
14 | docker run --rm -v "$(pwd)":/workspace -w /workspace builder bash -cl "./scripts/package.sh $executable"
15 |
--------------------------------------------------------------------------------
/Sources/Lambda/main.swift:
--------------------------------------------------------------------------------
1 | import AWSLambdaEvents
2 | import AWSLambdaRuntime
3 | import NIO
4 |
5 | // MARK: - Run Lambda
6 | Lambda.run(APIGatewayProxyLambda())
7 |
8 | // MARK: - Handler, Request and Response
9 | // FIXME: Use proper Event abstractions once added to AWSLambdaRuntime
10 | struct APIGatewayProxyLambda: EventLoopLambdaHandler {
11 | public typealias In = APIGateway.Request
12 | public typealias Out = APIGateway.Response
13 |
14 | public func handle(context: Lambda.Context, event: APIGateway.Request) -> EventLoopFuture {
15 | context.logger.debug("hello, api gateway!")
16 | return context.eventLoop.makeSucceededFuture(APIGateway.Response(statusCode: .ok, body: "Hello, world!"))
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/bootstrap:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -euo pipefail
4 |
5 | # Initialization - load function handler
6 | source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"
7 |
8 | # Processing
9 | while true
10 | do
11 | HEADERS="$(mktemp)"
12 | # Get an event
13 | EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
14 | REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
15 |
16 | # Execute the handler function from the script
17 | RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
18 |
19 | # Send the response
20 | curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE"
21 | done
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "Lambda",
6 | platforms: [
7 | .macOS(.v10_13),
8 | ],
9 | products: [
10 | .executable(name: "Lambda", targets: ["Lambda"]),
11 | ],
12 | dependencies: [
13 | .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", from: "0.2.0"),
14 | .package(name: "SwiftJWT", url: "https://github.com/Kitura/Swift-JWT.git", from: "3.6.2")
15 | ],
16 | targets: [
17 | .target(name: "Lambda", dependencies: [
18 | .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
19 | .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-runtime"),
20 | "SwiftJWT"
21 | ])
22 | ]
23 | )
24 |
--------------------------------------------------------------------------------
/Samples/JWT/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "Lambda",
6 | platforms: [
7 | .macOS(.v10_13),
8 | ],
9 | products: [
10 | .executable(name: "Lambda", targets: ["Lambda"]),
11 | ],
12 | dependencies: [
13 | .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", from: "0.2.0"),
14 | .package(name: "SwiftJWT", url: "https://github.com/Kitura/Swift-JWT.git", from: "3.6.2")
15 | ],
16 | targets: [
17 | .target(name: "Lambda", dependencies: [
18 | .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
19 | .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-runtime"),
20 | "SwiftJWT"
21 | ])
22 | ]
23 | )
24 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/NIO_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/Backtrace_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CBacktrace_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CNIOAtomics_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CNIODarwin_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CNIOLinux_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CNIOSHA1_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/Logging_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/NIOHTTP1_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/SwiftGD_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/AWSLambdaEvents_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/AWSLambdaRuntime_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/CNIOHTTPParser_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Samples/Avatar/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "Lambda",
6 | platforms: [
7 | .macOS(.v10_13),
8 | ],
9 | products: [
10 | .executable(name: "Lambda", targets: ["Lambda"]),
11 | ],
12 | dependencies: [
13 | .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", from: "0.2.0"),
14 | .package(url: "https://github.com/twostraws/SwiftGD.git", from: "2.5.0")
15 | ],
16 | targets: [
17 | .target(name: "Lambda", dependencies: [
18 | .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
19 | .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-runtime"),
20 | .product(name: "SwiftGD", package: "SwiftGD")
21 | ])
22 | ]
23 | )
24 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/AWSLambdaRuntimeCore_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/NIOConcurrencyHelpers_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/NIOFoundationCompat_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 cardoso
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Samples/JWT/main.swift:
--------------------------------------------------------------------------------
1 | import AWSLambdaEvents
2 | import AWSLambdaRuntime
3 | import SwiftJWT
4 | import Foundation
5 |
6 | Lambda.run { (context: Lambda.Context, event: APIGateway.Request, callback: @escaping (Result) -> Void) in
7 | guard
8 | let bodyData = event.body?.data(using: .utf8),
9 | let json = try? JSONSerialization.jsonObject(with: bodyData, options: []) as? [String: Any],
10 | let userId = json["user_id"] as? String
11 | else {
12 | callback(.success(APIGateway.Response(statusCode: .badRequest)))
13 | return
14 | }
15 |
16 | if let jwt = try? generateJWT(for: userId) {
17 | callback(.success(APIGateway.Response(statusCode: .ok, body: jwt)))
18 | } else {
19 | callback(.success(.init(statusCode: .internalServerError)))
20 | }
21 | }
22 |
23 | func generateJWT(for userId: String) throws -> String {
24 | struct ClientClaims: Claims {
25 | let user_id: String
26 | }
27 |
28 | let claims = ClientClaims(user_id: userId)
29 |
30 | var jwt = JWT(claims: claims)
31 |
32 | let key = "[replace_your_api_key_here]"
33 | let keyData = key.data(using: .utf8)!
34 |
35 | let signer = JWTSigner.hs256(key: keyData)
36 |
37 | return try jwt.sign(using: signer)
38 | }
39 |
--------------------------------------------------------------------------------
/Samples/Moderation/main.swift:
--------------------------------------------------------------------------------
1 | import AWSLambdaEvents
2 | import AWSLambdaRuntime
3 | import NIO
4 |
5 | import Foundation
6 | #if canImport(FoundationNetworking)
7 | import FoundationNetworking
8 | #endif
9 |
10 | Lambda.run { (context: Lambda.Context, event: APIGateway.Request, callback: @escaping (Result) -> Void) in
11 | guard
12 | let data = event.body?.data(using: .utf8),
13 | let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
14 | var message = json["message"] as? [String: Any]
15 | else {
16 | callback(.success(APIGateway.Response(statusCode: .ok)))
17 | return
18 | }
19 |
20 | // rewrite message's text with redacted version
21 | message["text"] = redactCreditCardNumbers(from: text)
22 |
23 | let body = ["message": message]
24 | let bodyData = try! JSONSerialization.data(withJSONObject: body)
25 | let string = String(data: bodyData, encoding: .utf8)
26 |
27 | callback(.success(APIGateway.Response(statusCode: .ok, body: string)))
28 | }
29 |
30 | func redactCreditCardNumbers(from text: String) -> String {
31 | var text = text
32 |
33 | let americanExpress = "(?:3[47][0-9]{13})";
34 | let dinersClub = "(?:3(?:0[0-5]|[68][0-9])[0-9]{11})";
35 | let discover = "(?:6(?:011|5[0-9]{2})(?:[0-9]{12}))";
36 | let jcb = "(?:(?:2131|1800|35\\d{3})\\d{11})";
37 | let maestro = "(?:(?:5[0678]\\d\\d|6304|6390|67\\d\\d)\\d{8,15})";
38 | let mastercard = "(?:(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12})";
39 | let visa = "(?:4[0-9]{12})(?:[0-9]{3})?";
40 |
41 | let all = [americanExpress, dinersClub, discover, jcb, maestro, mastercard, visa].joined(separator: "|")
42 |
43 | let regex = try! NSRegularExpression(pattern: all)
44 |
45 | let res = regex.matches(in: text, options: [], range: NSRange(location: 0, length: text.count))
46 |
47 | res.forEach {
48 | text = text.replacingCharacters(
49 | in: Range($0.range, in: text)!,
50 | with: String(repeating: "*", count: $0.range.length)
51 | )
52 | }
53 |
54 | return text
55 | }
56 |
--------------------------------------------------------------------------------
/Samples/ChatBot/main.swift:
--------------------------------------------------------------------------------
1 | import AWSLambdaEvents
2 | import AWSLambdaRuntime
3 | import NIO
4 |
5 | import Foundation
6 | #if canImport(FoundationNetworking)
7 | import FoundationNetworking
8 | #endif
9 |
10 | Lambda.run { (context: Lambda.Context, event: APIGateway.Request, callback: @escaping (Result) -> Void) in
11 | context.logger.debug("hello, api gateway!")
12 |
13 | let botId = "Agent"
14 |
15 | guard
16 | let bodyData = event.body?.data(using: .utf8),
17 | let json = try? JSONSerialization.jsonObject(with: bodyData, options: []) as? [String: Any],
18 | json["type"] as? String == "message.new",
19 | let channelType = json["channel_type"] as? String,
20 | let channelId = json["channel_id"] as? String,
21 | let message = json["message"] as? [String: Any],
22 | let user = message["user"] as? [String: Any],
23 | let userId = user["id"] as? String,
24 | userId != botId
25 | else {
26 | callback(.success(APIGateway.Response(statusCode: .ok, body: "nope!")))
27 | return
28 | }
29 |
30 | botReply(channelType: channelType, channelId: channelId, botId: botId) {
31 | callback(.success(APIGateway.Response(statusCode: .ok)))
32 | }
33 | }
34 |
35 | func botReply(channelType: String, channelId: String, botId: String, completion: @escaping () -> Void) {
36 | let apiKey = "[insert_your_api_key_here]"
37 | let jwt = "[insert_your_jwt_here]"
38 |
39 | let response = [
40 | "I am a bot",
41 | "Beep boop",
42 | "Having trouble?",
43 | "I can help"
44 | ].randomElement() ?? ""
45 |
46 | let url = URL(string: "https://chat-us-east-1.stream-io-api.com/channels/\(channelType)/\(channelId)/message?api_key=\(apiKey)")!
47 | var request = URLRequest(url: url)
48 | request.allHTTPHeaderFields = ["Authorization": jwt, "stream-auth-type": "jwt"]
49 |
50 | request.httpMethod = "POST"
51 | request.httpBody =
52 | """
53 | {
54 | "message" : {
55 | "text" : "\(response)",
56 | "silent" : false,
57 | "user_id": "\(botId)"
58 | }
59 | }
60 | """.data(using: .utf8)
61 |
62 | let task = URLSession.shared.dataTask(with: request) { _,_,_ in
63 | completion()
64 | }
65 |
66 | task.resume()
67 | }
68 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/xcshareddata/xcschemes/Lambda.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
61 |
63 |
64 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Lambda.xcodeproj/xcshareddata/xcschemes/Lambda-Package.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
61 |
63 |
64 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Cryptor",
6 | "repositoryURL": "https://github.com/Kitura/BlueCryptor.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "ee5880e031da4c609f372cf7472476ab51d5dd19",
10 | "version": "1.0.200"
11 | }
12 | },
13 | {
14 | "package": "CryptorECC",
15 | "repositoryURL": "https://github.com/Kitura/BlueECC.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "baf6ed3fc1a622675f0041b4aff7c02dd1a93818",
19 | "version": "1.2.200"
20 | }
21 | },
22 | {
23 | "package": "CryptorRSA",
24 | "repositoryURL": "https://github.com/Kitura/BlueRSA.git",
25 | "state": {
26 | "branch": null,
27 | "revision": "440f78db26d8bb073f29590f1c7bd31004da09ae",
28 | "version": "1.0.201"
29 | }
30 | },
31 | {
32 | "package": "KituraContracts",
33 | "repositoryURL": "https://github.com/Kitura/KituraContracts.git",
34 | "state": {
35 | "branch": null,
36 | "revision": "8418006e39e2efae9b31ae92721cb597ac29c617",
37 | "version": "1.2.200"
38 | }
39 | },
40 | {
41 | "package": "LoggerAPI",
42 | "repositoryURL": "https://github.com/Kitura/LoggerAPI.git",
43 | "state": {
44 | "branch": null,
45 | "revision": "e82d34eab3f0b05391082b11ea07d3b70d2f65bb",
46 | "version": "1.9.200"
47 | }
48 | },
49 | {
50 | "package": "OpenSSL",
51 | "repositoryURL": "https://github.com/Kitura/OpenSSL.git",
52 | "state": {
53 | "branch": null,
54 | "revision": "80b04f33b086fc90e28d9ae159d43705fb348e16",
55 | "version": "2.2.200"
56 | }
57 | },
58 | {
59 | "package": "swift-aws-lambda-runtime",
60 | "repositoryURL": "https://github.com/swift-server/swift-aws-lambda-runtime.git",
61 | "state": {
62 | "branch": null,
63 | "revision": "2bac89639fffd7b1197ab597473a4d10c459a230",
64 | "version": "0.2.0"
65 | }
66 | },
67 | {
68 | "package": "swift-backtrace",
69 | "repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
70 | "state": {
71 | "branch": null,
72 | "revision": "f2fd8c4845a123419c348e0bc4b3839c414077d5",
73 | "version": "1.2.0"
74 | }
75 | },
76 | {
77 | "package": "SwiftJWT",
78 | "repositoryURL": "https://github.com/Kitura/Swift-JWT.git",
79 | "state": {
80 | "branch": null,
81 | "revision": "2f2fc12ae88660e0760b04d9e6c341517b31ad7b",
82 | "version": "3.6.200"
83 | }
84 | },
85 | {
86 | "package": "swift-log",
87 | "repositoryURL": "https://github.com/apple/swift-log.git",
88 | "state": {
89 | "branch": null,
90 | "revision": "173f567a2dfec11d74588eea82cecea555bdc0bc",
91 | "version": "1.4.0"
92 | }
93 | },
94 | {
95 | "package": "swift-nio",
96 | "repositoryURL": "https://github.com/apple/swift-nio.git",
97 | "state": {
98 | "branch": null,
99 | "revision": "8a865bd15e69526cbdfcfd7c47698eb20b2ba951",
100 | "version": "2.19.0"
101 | }
102 | }
103 | ]
104 | },
105 | "version": 1
106 | }
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift Lambda λ
2 | [](https://github.com/GetStream/swift-lambda/actions?query=workflow%3ASwift)
3 | [](/LICENSE)
4 | [](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2FGetStream%2Fswift-lambda)
5 | [](https://twitter.com/intent/follow?screen_name=getstream_io)
6 |
7 | This project is a starting point for writing an HTTP service in Swift. It contains configuration files and scripts to fully automate deploying to AWS in a matter of seconds using the Serverless Framework. It is based on samples and documentation from [swift-server/swift-aws-lambda-runtime](https://github.com/swift-server/swift-aws-lambda-runtime)
8 |
9 | Built with 💘 by the folks @ [Stream](https://getstream.io).
10 |
11 |
12 |
13 |
14 | ## 🤖 Chatbot Sample
15 |
16 | In the [Samples](Samples) folder you can find a Chatbot sample built from this tutorial: [Write a Chatbot in Swift and Deploy to AWS Lambda](https://getstream.io/blog/swift-lambda-chat-bot/)
17 |
18 | ## ⚙️ Getting started
19 |
20 | ### ✅ Prerequisites
21 | - [Docker](https://docs.docker.com/docker-for-mac/install/)
22 | - [Serverless Framework](https://www.serverless.com/framework/docs/getting-started/)
23 | - [AWS Credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/)
24 |
25 | ### ✍️ Write your function
26 |
27 | Write your code in [`Sources/Lambda/main.swift`](Sources/Lambda/main.swift).
28 |
29 | ### 🚀 Deploy
30 |
31 | Run `./Scripts/deploy.sh`.
32 |
33 | ### 🔎 Verify
34 |
35 | Open the output URL in your browser.
36 |
37 | And done!
38 |
39 |
40 |
41 | ## 👩💻 Developing
42 |
43 | There is some code already present in the `Sources/Lambda/main.swift` file. It simply outputs "Hello, world!" in plain text.
44 |
45 | ```swift
46 | import AWSLambdaEvents
47 | import AWSLambdaRuntime
48 | import NIO
49 |
50 | // MARK: - Run Lambda
51 | Lambda.run(APIGatewayProxyLambda())
52 |
53 | // MARK: - Handler, Request and Response
54 | // FIXME: Use proper Event abstractions once added to AWSLambdaRuntime
55 | struct APIGatewayProxyLambda: EventLoopLambdaHandler {
56 | public typealias In = APIGateway.Request
57 | public typealias Out = APIGateway.Response
58 |
59 | public func handle(context: Lambda.Context, event: APIGateway.Request) -> EventLoopFuture {
60 | context.logger.debug("hello, api gateway!")
61 | return context.eventLoop.makeSucceededFuture(APIGateway.Response(statusCode: .ok, body: "Hello, world!"))
62 | }
63 | }
64 | ```
65 |
66 | If you want to output some HTML, just set the "Content-Type" header to "text/html; charset=UTF-8"
67 |
68 | ```swift
69 | ...
70 | return context.eventLoop.makeSucceededFuture(APIGateway.Response(
71 | statusCode: .ok,
72 | headers: ["Content-Type": "text/html; charset=UTF-8"],
73 | body: """
74 |
75 |
Hello, world! From Swift 5.2 💘
76 |
77 |
78 | \(event.requestContext.identity.userAgent ?? "")
79 | """)
80 | )
81 | ...
82 | ```
83 |
84 | 
85 |
86 | For more information on the available settings and methods, refer to the [Swift AWS Lambda Runtime README](https://github.com/swift-server/swift-aws-lambda-runtime)
87 |
88 | ## 📡 Endpoint Settings
89 |
90 | To change some characteristics of your HTTP endpoint, such as the method expected, you should modify the [`serverless.yml`](https://github.com/GetStream/swift-lambda/blob/main/serverless.yml#L70-L72) file. For more information on the available parameters, refer to the [Serverless.yml Reference](https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/).
91 |
92 | ## Contributing
93 |
94 | If you have a suggestion or bug report, please [file an issue in the Swift Lambda repository](https://github.com/GetStream/swift-lambda/issues/new). If you want to take a stab at contributing code, don't hesitate in submitting a PR. Don't forget to leave a star if you liked it :)
95 |
--------------------------------------------------------------------------------