@@ -224,4 +224,154 @@ struct APIGatewayV2Tests {
224224 _ = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
225225 }
226226 }
227+
228+ // MARK: Codable Helpers Tests
229+
230+ @Test func decodeBodyWithNilBody( ) throws {
231+ let data = APIGatewayV2Tests . exampleGetEventBodyNilHeaders. data ( using: . utf8) !
232+ let request = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
233+
234+ let decodedBody = try request. decodeBody ( )
235+ #expect( decodedBody == nil )
236+ }
237+
238+ @Test func decodeBodyWithPlainTextBody( ) throws {
239+ let requestWithBody = """
240+ {
241+ " routeKey " : " POST /hello " ,
242+ " version " : " 2.0 " ,
243+ " rawPath " : " /hello " ,
244+ " rawQueryString " : " " ,
245+ " requestContext " :{
246+ " timeEpoch " :1587750461466,
247+ " domainPrefix " : " hello " ,
248+ " accountId " : " 0123456789 " ,
249+ " stage " : " $default " ,
250+ " domainName " : " hello.test.com " ,
251+ " apiId " : " pb5dg6g3rg " ,
252+ " requestId " : " LgLpnibOFiAEPCA= " ,
253+ " http " :{
254+ " path " : " /hello " ,
255+ " userAgent " : " test " ,
256+ " method " : " POST " ,
257+ " protocol " : " HTTP/1.1 " ,
258+ " sourceIp " : " 127.0.0.1 "
259+ },
260+ " time " : " 24/Apr/2020:17:47:41 +0000 "
261+ },
262+ " isBase64Encoded " :false,
263+ " body " : " Hello World! "
264+ }
265+ """
266+
267+ let data = requestWithBody. data ( using: . utf8) !
268+ let request = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
269+
270+ let decodedBody = try request. decodeBody ( )
271+ let expectedBody = " Hello World! " . data ( using: . utf8)
272+ #expect( decodedBody == expectedBody)
273+ }
274+
275+ @Test func decodeBodyWithBase64EncodedBody( ) throws {
276+ let requestWithBase64Body = """
277+ {
278+ " routeKey " : " POST /hello " ,
279+ " version " : " 2.0 " ,
280+ " rawPath " : " /hello " ,
281+ " rawQueryString " : " " ,
282+ " requestContext " :{
283+ " timeEpoch " :1587750461466,
284+ " domainPrefix " : " hello " ,
285+ " accountId " : " 0123456789 " ,
286+ " stage " : " $default " ,
287+ " domainName " : " hello.test.com " ,
288+ " apiId " : " pb5dg6g3rg " ,
289+ " requestId " : " LgLpnibOFiAEPCA= " ,
290+ " http " :{
291+ " path " : " /hello " ,
292+ " userAgent " : " test " ,
293+ " method " : " POST " ,
294+ " protocol " : " HTTP/1.1 " ,
295+ " sourceIp " : " 127.0.0.1 "
296+ },
297+ " time " : " 24/Apr/2020:17:47:41 +0000 "
298+ },
299+ " isBase64Encoded " :true,
300+ " body " : " SGVsbG8gV29ybGQh "
301+ }
302+ """
303+
304+ let data = requestWithBase64Body. data ( using: . utf8) !
305+ let request = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
306+
307+ let decodedBody = try request. decodeBody ( )
308+ let expectedBody = " Hello World! " . data ( using: . utf8)
309+ #expect( decodedBody == expectedBody)
310+ }
311+
312+ @Test func decodeBodyAsDecodableType( ) throws {
313+ struct TestPayload : Codable , Equatable {
314+ let message : String
315+ let count : Int
316+ }
317+
318+ // Use the fullExamplePayload which already has a simple JSON body
319+ let data = APIGatewayV2Tests . fullExamplePayload. data ( using: . utf8) !
320+ let request = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
321+
322+ // Test that we can decode the body as String
323+ // The fullExamplePayload has body: "Hello from Lambda" which is not valid JSON, so this should fail
324+ #expect( throws: DecodingError . self) {
325+ _ = try request. decodeBody ( TestPayload . self)
326+ }
327+ }
328+
329+ @Test func decodeBodyAsDecodableTypeWithCustomDecoder( ) throws {
330+ struct TestPayload : Codable , Equatable {
331+ let messageText : String
332+ let count : Int
333+
334+ enum CodingKeys : String , CodingKey {
335+ case messageText = " message_text "
336+ case count
337+ }
338+ }
339+
340+ let testPayload = TestPayload ( messageText: " test " , count: 42 )
341+
342+ let requestWithBase64JSONBody = """
343+ {
344+ " routeKey " : " POST /hello " ,
345+ " version " : " 2.0 " ,
346+ " rawPath " : " /hello " ,
347+ " rawQueryString " : " " ,
348+ " requestContext " :{
349+ " timeEpoch " :1587750461466,
350+ " domainPrefix " : " hello " ,
351+ " accountId " : " 0123456789 " ,
352+ " stage " : " $default " ,
353+ " domainName " : " hello.test.com " ,
354+ " apiId " : " pb5dg6g3rg " ,
355+ " requestId " : " LgLpnibOFiAEPCA= " ,
356+ " http " :{
357+ " path " : " /hello " ,
358+ " userAgent " : " test " ,
359+ " method " : " POST " ,
360+ " protocol " : " HTTP/1.1 " ,
361+ " sourceIp " : " 127.0.0.1 "
362+ },
363+ " time " : " 24/Apr/2020:17:47:41 +0000 "
364+ },
365+ " isBase64Encoded " :true,
366+ " body " : " eyJtZXNzYWdlX3RleHQiOiJ0ZXN0IiwiY291bnQiOjQyfQ== " ,
367+ " headers " :{}
368+ }
369+ """
370+
371+ let data = requestWithBase64JSONBody. data ( using: . utf8) !
372+ let request = try JSONDecoder ( ) . decode ( APIGatewayV2Request . self, from: data)
373+
374+ let decodedPayload = try request. decodeBody ( TestPayload . self)
375+ #expect( decodedPayload == testPayload)
376+ }
227377}
0 commit comments