Skip to content

Commit ec2b6bf

Browse files
author
Andrea Scuderi
committed
Add article and fix default config
1 parent 84e71e2 commit ec2b6bf

File tree

6 files changed

+186
-16
lines changed

6 files changed

+186
-16
lines changed

Sources/BreezeDemoHTTPApplication/BreezeDemoHTTPApplication.swift

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import AWSLambdaRuntime
1818
import AsyncHTTPClient
1919
import Logging
2020
import NIOCore
21-
import ServiceLifecycle
2221

2322
/// This is a simple example of a Breeze Lambda WebHook handler.
2423
/// It uses the BreezeHTTPClientService to make an HTTP request to example.com
@@ -57,18 +56,8 @@ struct DemoLambdaHandler: BreezeLambdaWebHookHandler, Sendable {
5756
@main
5857
struct BreezeDemoHTTPApplication {
5958

60-
static let applicationName = "BreezeDemoHTTPApplication"
61-
static let logger = Logger(label: "BreezeDemoHTTPApplication")
62-
6359
static func main() async throws {
64-
let config = BreezeHTTPClientConfig(
65-
timeout: .seconds(30),
66-
logger: logger
67-
)
68-
let app = BreezeLambdaWebHook<DemoLambdaHandler>(
69-
name: applicationName,
70-
config: config,
71-
)
72-
try await app.run()
60+
let lambda = BreezeLambdaWebHook<DemoLambdaHandler>(name: "DemoLambdaHandler")
61+
try await lambda.run()
7362
}
7463
}

Sources/BreezeLambdaWebHook/BreezeHTTPClientConfig.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ public enum BreezeClientServiceError: Error {
2323

2424
/// Configuration for the Breeze HTTP Client
2525
public struct BreezeHTTPClientConfig: Sendable {
26-
public init(timeout: TimeAmount, logger: Logger) {
26+
public init(
27+
timeout: TimeAmount = .seconds(30),
28+
logger: Logger = Logger(label: "BreezeLambdaWebHookLogger")
29+
) {
2730
self.timeout = timeout
2831
self.logger = logger
2932
}

Sources/BreezeLambdaWebHook/BreezeLambdaWebHook.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,20 @@ public struct BreezeLambdaWebHook<LambdaHandler: BreezeLambdaWebHookHandler>: Se
3030
/// - Parameters:
3131
/// - name: The name of the service.
3232
/// - config: Configuration for the Breeze HTTP Client.
33-
public init(name: String, config: BreezeHTTPClientConfig) {
33+
///
34+
/// This initializer sets up the Breeze Lambda WebHook service with a specified name and configuration.
35+
///
36+
/// - Note: If no configuration is provided, a default configuration with a 30-second timeout and a logger will be used.
37+
public init(
38+
name: String,
39+
config: BreezeHTTPClientConfig? = nil
40+
) {
3441
self.name = name
35-
self.config = config
42+
let defaultConfig = BreezeHTTPClientConfig(
43+
timeout: .seconds(30),
44+
logger: Logger(label: "\(name)")
45+
)
46+
self.config = config ?? defaultConfig
3647
}
3748

3849
/// Runs the Breeze Lambda WebHook service.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# ``BreezeLambdaWebHook``
2+
3+
@Metadata {
4+
@PageImage(purpose: icon, source: "wind")
5+
}
6+
7+
## Overview
8+
9+
BreezeLambdaWebHook is a Swift framework that simplifies the development of serverless webhook handlers for AWS Lambda.
10+
11+
It provides a clean, type-safe interface for processing HTTP requests from API Gateway and returning appropriate responses.
12+
13+
It allows you to define a handler that processes incoming webhook requests and returns appropriate responses using `AsyncHTTPClient` framework.
14+
15+
![BreezeLambdaWebHook Diagram](webhook)
16+
17+
## Key Features
18+
19+
- Serverless Architecture - Built specifically for AWS Lambda with API Gateway integration
20+
- Webhook Handling: Processes incoming requests and returns responses
21+
- Swift Concurrency: Fully compatible with Swift's async/await model
22+
- Type Safety: Leverages Swift's type system with Codable support
23+
- It supports both GET and POST requests
24+
- Minimal Configuration - Focus on business logic rather than infrastructure plumbing
25+
26+
## How it works
27+
28+
The framework handles the underlying AWS Lambda event processing, allowing you to focus on implementing your webhook logic. When a request arrives through API Gateway:
29+
30+
1. The Lambda function receives the API Gateway event
31+
2. BreezeLambdaWebHook deserializes the event into a Swift type
32+
3. The handler processes the request, performing any necessary business logic
33+
4. The handler returns a response, which is serialized back to the API Gateway format
34+
35+
## Getting Started
36+
37+
To create a webhook handler, implement the BreezeLambdaWebHookHandler protocol:
38+
39+
```swift
40+
class MyWebhook: BreezeLambdaWebHookHandler {
41+
let handlerContext: HandlerContext
42+
43+
required init(handlerContext: HandlerContext) {
44+
self.handlerContext = handlerContext
45+
}
46+
47+
func handle(context: LambdaContext, event: APIGatewayV2Request) async -> APIGatewayV2Response {
48+
// Your webhook logic here
49+
return APIGatewayV2Response(with: "Success", statusCode: .ok)
50+
}
51+
}
52+
```
53+
54+
Then, implement the `main.swift` file to run the Lambda function:
55+
```swift
56+
import BreezeLambdaWebHook
57+
import AWSLambdaEvents
58+
import AWSLambdaRuntime
59+
import AsyncHTTPClient
60+
import Logging
61+
import NIOCore
62+
63+
@main
64+
struct BreezeDemoHTTPApplication {
65+
static func main() async throws {
66+
let app = BreezeLambdaWebHook<DemoLambdaHandler>(name: "BreezeDemoHTTPApplication")
67+
try await app.run()
68+
}
69+
}
70+
```
71+
72+
## Example WebHook Handlers
73+
74+
### GET WebHook example:
75+
76+
If the parameter `github-user` is present in the query string, the value is extracted and used to get the content from GitHub, the content is returned to the response payload.
77+
78+
```swift
79+
class GetWebHook: BreezeLambdaWebHookHandler {
80+
81+
let handlerContext: HandlerContext
82+
83+
required init(handlerContext: HandlerContext) {
84+
self.handlerContext = handlerContext
85+
}
86+
87+
func handle(context: AWSLambdaRuntimeCore.LambdaContext, event: AWSLambdaEvents.APIGatewayV2Request) async -> AWSLambdaEvents.APIGatewayV2Response {
88+
do {
89+
context.logger.info("event: \(event)")
90+
guard let params = event.queryStringParameters else {
91+
throw BreezeLambdaWebHookError.invalidRequest
92+
}
93+
if let user = params["github-user"] {
94+
let url = "https://github.com/\(user)"
95+
let request = HTTPClientRequest(url: url)
96+
let response = try await httpClient.execute(request, timeout: .seconds(3))
97+
let bytes = try await response.body.collect(upTo: 1024 * 1024) // 1 MB Buffer
98+
let body = String(buffer: bytes)
99+
return APIGatewayV2Response(with: body, statusCode: .ok)
100+
} else {
101+
return APIGatewayV2Response(with: params, statusCode: .ok)
102+
}
103+
} catch {
104+
return APIGatewayV2Response(with: error, statusCode: .badRequest)
105+
}
106+
}
107+
}
108+
```
109+
110+
### PostWebHook example:
111+
112+
If the parameter `github-user` is present in the JSON payload, the value is extracted and used to get the content from GitHub, the content is returned to the response payload.
113+
114+
```swift
115+
struct PostWebHookRequest: Codable {
116+
let githubUser: String
117+
118+
enum CodingKeys: String, CodingKey {
119+
case githubUser = "github-user"
120+
}
121+
}
122+
123+
class PostWebHook: BreezeLambdaWebHookHandler {
124+
125+
let handlerContext: HandlerContext
126+
127+
required init(handlerContext: HandlerContext) {
128+
self.handlerContext = handlerContext
129+
}
130+
131+
func handle(context: AWSLambdaRuntimeCore.LambdaContext, event: AWSLambdaEvents.APIGatewayV2Request) async -> AWSLambdaEvents.APIGatewayV2Response {
132+
do {
133+
context.logger.info("event: \(event)")
134+
let incomingRequest: PostWebHookRequest = try event.bodyObject()
135+
let url = "https://github.com/\(incomingRequest.githubUser)"
136+
let request = HTTPClientRequest(url: url)
137+
let response = try await httpClient.execute(request, timeout: .seconds(3))
138+
let bytes = try await response.body.collect(upTo: 1024 * 1024) // 1 MB Buffer
139+
let body = String(buffer: bytes)
140+
return APIGatewayV2Response(with: body, statusCode: .ok)
141+
} catch {
142+
return APIGatewayV2Response(with: error, statusCode: .badRequest)
143+
}
144+
}
145+
}
146+
```
147+
148+
## Deployment
149+
150+
Deploy your Lambda function using AWS CDK, SAM, Serverless or Terraform. The Lambda requires:
151+
152+
- API Gateway integration for HTTP requests
153+
154+
For step-by-step deployment instructions and templates, see the [Breeze project repository](https://github.com/swift-serverless/Breeze) for more info on how to deploy it on AWS.
155+

Sources/BreezeLambdaWebHook/Docs.docc/Resources/webhook.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 11 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)