Skip to content

Commit c354046

Browse files
committed
simply function url request parsing
1 parent 209c840 commit c354046

File tree

2 files changed

+36
-43
lines changed

2 files changed

+36
-43
lines changed

Examples/StreamingFromEvent/README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ curl -v \
7777
http://127.0.0.1:7000/invoke
7878
```
7979

80+
Or simulate a call from a Lambda Function URL (where the body is encapsulated in a Lambda Function URL request):
81+
82+
```bash
83+
curl -v \
84+
--header "Content-Type: application/json" \
85+
--data @events/sample-request.json \
86+
http://127.0.0.1:7000/invoke
87+
```
88+
8089
## Deploy with the AWS CLI
8190

8291
Here is how to deploy using the `aws` command line.
@@ -242,11 +251,12 @@ Value https://gaudpin2zjqizfujfnqxstnv6u0czrfu.lambda-url.us-east-
242251
Once the function is deployed, you can invoke it with `curl`, similarly to what you did when deploying with the AWS CLI.
243252

244253
```bash
245-
curl "$URL" \
254+
curl -X POST -d @events/sample-request.json" \
246255
--user "$ACCESS_KEY":"$SECRET_KEY" \
247256
--aws-sigv4 "aws:amz:${REGION}:lambda" \
248257
-H "x-amz-security-token: $AWS_SESSION_TOKEN" \
249-
--no-buffer
258+
--no-buffer \
259+
"$URL"
250260
```
251261
252262
### Undeploy with SAM

Sources/AWSLambdaRuntime/LambdaStreaming+Codable.swift

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -82,51 +82,39 @@ public struct StreamingLambdaCodableAdapter<
8282
context: LambdaContext
8383
) async throws {
8484

85-
// try to decode the event as a FunctionURLRequest
86-
if let functionUrlEvent1 = isFunctionURLRequest(event) {
85+
// try to decode the event as a FunctionURLRequest and extract it's body
86+
let urlRequestBody = bodyFromFunctionURLRequest(event)
8787

88-
// for some reasons I don't understand the "body" param contains the complete FunctionURL request
89-
// so, 1/ we decode the event we receive, 2/ we base64 decode the body, 3/ we decode a FunctionURLRequest again,
90-
// then 4/ we can access the actual payload body, decode it pass it to the handler
91-
if let base64EncodedString = functionUrlEvent1.body,
88+
// otherwise, decode the event as a user-provided JSON event
89+
let decodedEvent = try self.decoder.decode(Handler.Event.self, from: urlRequestBody ?? event)
90+
try await self.handler.handle(decodedEvent, responseWriter: responseWriter, context: context)
91+
}
92+
93+
/// Extract the body payload from the event.
94+
/// This function checks if the event is a valid `FunctionURLRequest` and decodes the body if it is base64 encoded.
95+
/// If the event is not a valid `FunctionURLRequest`, it returns nil.
96+
/// - Parameter event: The raw ByteBuffer event to check.
97+
/// - Returns: the base64 decodeded body of the FunctionURLRequest if it is a valid FunctionURLRequest, otherwise nil.
98+
@inlinable
99+
package func bodyFromFunctionURLRequest(_ event: ByteBuffer) -> ByteBuffer? {
100+
do {
101+
// try to decode as a FunctionURLRequest
102+
let request = try self.decoder.decode(FunctionURLRequest.self, from: event)
103+
104+
// if the body is encoded in base64, decode it
105+
if request.isBase64Encoded,
106+
let base64EncodedString = request.body,
92107
// this is the minimal way to base64 decode without importing new dependencies
93108
let decodedData = Data(base64Encoded: base64EncodedString),
94109
let decodedString = String(data: decodedData, encoding: .utf8)
95110
{
96111

97-
// decode the FunctionURL event inside the body
98-
let functionUrlEvent2 = try self.decoder.decode(
99-
FunctionURLRequest.self,
100-
from: ByteBuffer(string: decodedString)
101-
)
102-
103-
// finally decode the actual payload passed by the caller
104-
let decodedEvent = try self.decoder.decode(
105-
Handler.Event.self,
106-
from: ByteBuffer(string: functionUrlEvent2.body ?? "")
107-
)
108-
109-
// and invoke the user-provided handler
110-
try await self.handler.handle(decodedEvent, responseWriter: responseWriter, context: context)
112+
return ByteBuffer(string: decodedString)
111113
} else {
112-
context.logger.trace("Can't decode FunctionURLRequest's body", metadata: ["Event": "\(event)"])
114+
return ByteBuffer(string: request.body ?? "")
113115
}
114-
115-
} else {
116-
// otherwise, decode the event as a user-provided JSON event
117-
let decodedEvent = try self.decoder.decode(Handler.Event.self, from: event)
118-
try await self.handler.handle(decodedEvent, responseWriter: responseWriter, context: context)
119-
}
120-
}
121-
122-
/// Check if the payload is an FunctionURLlRequest or a direct invocation
123-
/// - Parameter event: The raw ByteBuffer event to check.
124-
/// - Returns: the FunctionURLRequest if the event is a FunctionURLRequest, nil otherwise
125-
@inlinable
126-
package func isFunctionURLRequest(_ event: ByteBuffer) -> FunctionURLRequest? {
127-
do {
128-
return try self.decoder.decode(FunctionURLRequest.self, from: event)
129116
} catch {
117+
// not a FunctionURLRequest, return nil
130118
return nil
131119
}
132120
}
@@ -160,11 +148,6 @@ public struct StreamingFromEventClosureHandler<Event: Decodable>: StreamingLambd
160148
}
161149

162150
#if FoundationJSONSupport
163-
#if canImport(FoundationEssentials)
164-
import FoundationEssentials
165-
#else
166-
import class Foundation.JSONDecoder
167-
#endif
168151

169152
extension StreamingLambdaCodableAdapter {
170153
/// Initialize with a JSON decoder and handler.

0 commit comments

Comments
 (0)