2
2
import json
3
3
import zlib
4
4
from pathlib import Path
5
+ from typing import Dict , Tuple
5
6
6
7
import pytest
7
8
8
- from aws_lambda_powertools .event_handler .api_gateway import ApiGatewayResolver , ProxyEventType
9
+ from aws_lambda_powertools .event_handler .api_gateway import ApiGatewayResolver , ProxyEventType , Response
9
10
from aws_lambda_powertools .utilities .data_classes import ALBEvent , APIGatewayProxyEvent , APIGatewayProxyEventV2
10
11
11
12
@@ -25,77 +26,96 @@ def read_media(file_name: str) -> bytes:
25
26
26
27
27
28
def test_alb_event ():
29
+ # GIVEN a Application Load Balancer proxy type event
28
30
app = ApiGatewayResolver (proxy_type = ProxyEventType .alb_event )
29
31
30
32
@app .get ("/lambda" )
31
- def foo ():
33
+ def foo () -> Tuple [ int , str , str ] :
32
34
assert isinstance (app .current_event , ALBEvent )
33
35
assert app .lambda_context == {}
34
36
return 200 , TEXT_HTML , "foo"
35
37
38
+ # WHEN
36
39
result = app (load_event ("albEvent.json" ), {})
37
40
41
+ # THEN process event correctly
42
+ # AND set the current_event type as ALBEvent
38
43
assert result ["statusCode" ] == 200
39
44
assert result ["headers" ]["Content-Type" ] == TEXT_HTML
40
45
assert result ["body" ] == "foo"
41
46
42
47
43
48
def test_api_gateway_v1 ():
49
+ # GIVEN a Http API V1 proxy type event
44
50
app = ApiGatewayResolver (proxy_type = ProxyEventType .http_api_v1 )
45
51
46
52
@app .get ("/my/path" )
47
- def get_lambda ():
53
+ def get_lambda () -> Tuple [ int , str , str ] :
48
54
assert isinstance (app .current_event , APIGatewayProxyEvent )
49
55
assert app .lambda_context == {}
50
56
return 200 , APPLICATION_JSON , json .dumps ({"foo" : "value" })
51
57
58
+ # WHEN
52
59
result = app (LOAD_GW_EVENT , {})
53
60
61
+ # THEN process event correctly
62
+ # AND set the current_event type as APIGatewayProxyEvent
54
63
assert result ["statusCode" ] == 200
55
64
assert result ["headers" ]["Content-Type" ] == APPLICATION_JSON
56
65
57
66
58
67
def test_api_gateway ():
68
+ # GIVEN a Rest API Gateway proxy type event
59
69
app = ApiGatewayResolver (proxy_type = ProxyEventType .api_gateway )
60
70
61
71
@app .get ("/my/path" )
62
- def get_lambda ():
72
+ def get_lambda () -> Tuple [ int , str , str ] :
63
73
assert isinstance (app .current_event , APIGatewayProxyEvent )
64
74
return 200 , TEXT_HTML , "foo"
65
75
76
+ # WHEN
66
77
result = app (LOAD_GW_EVENT , {})
67
78
79
+ # THEN process event correctly
80
+ # AND set the current_event type as APIGatewayProxyEvent
68
81
assert result ["statusCode" ] == 200
69
82
assert result ["headers" ]["Content-Type" ] == TEXT_HTML
70
83
assert result ["body" ] == "foo"
71
84
72
85
73
86
def test_api_gateway_v2 ():
87
+ # GIVEN a Http API V2 proxy type event
74
88
app = ApiGatewayResolver (proxy_type = ProxyEventType .http_api_v2 )
75
89
76
90
@app .post ("/my/path" )
77
- def my_path ():
91
+ def my_path () -> Tuple [ int , str , str ] :
78
92
assert isinstance (app .current_event , APIGatewayProxyEventV2 )
79
93
post_data = app .current_event .json_body
80
94
return 200 , "plain/text" , post_data ["username" ]
81
95
96
+ # WHEN
82
97
result = app (load_event ("apiGatewayProxyV2Event.json" ), {})
83
98
99
+ # THEN process event correctly
100
+ # AND set the current_event type as APIGatewayProxyEventV2
84
101
assert result ["statusCode" ] == 200
85
102
assert result ["headers" ]["Content-Type" ] == "plain/text"
86
103
assert result ["body" ] == "tom"
87
104
88
105
89
106
def test_include_rule_matching ():
107
+ # GIVEN
90
108
app = ApiGatewayResolver ()
91
109
92
110
@app .get ("/<name>/<my_id>" )
93
- def get_lambda (my_id : str , name : str ):
111
+ def get_lambda (my_id : str , name : str ) -> Tuple [ int , str , str ] :
94
112
assert name == "my"
95
113
return 200 , "plain/html" , my_id
96
114
115
+ # WHEN
97
116
result = app (LOAD_GW_EVENT , {})
98
117
118
+ # THEN
99
119
assert result ["statusCode" ] == 200
100
120
assert result ["headers" ]["Content-Type" ] == "plain/html"
101
121
assert result ["body" ] == "path"
@@ -153,7 +173,7 @@ def test_cors():
153
173
app = ApiGatewayResolver ()
154
174
155
175
@app .get ("/my/path" , cors = True )
156
- def with_cors ():
176
+ def with_cors () -> Tuple [ int , str , str ] :
157
177
return 200 , TEXT_HTML , "test"
158
178
159
179
def handler (event , context ):
@@ -176,7 +196,7 @@ def test_compress():
176
196
app = ApiGatewayResolver ()
177
197
178
198
@app .get ("/my/request" , compress = True )
179
- def with_compression ():
199
+ def with_compression () -> Tuple [ int , str , str ] :
180
200
return 200 , APPLICATION_JSON , expected_value
181
201
182
202
def handler (event , context ):
@@ -197,7 +217,7 @@ def test_base64_encode():
197
217
app = ApiGatewayResolver ()
198
218
199
219
@app .get ("/my/path" , compress = True )
200
- def read_image ():
220
+ def read_image () -> Tuple [ int , str , bytes ] :
201
221
return 200 , "image/png" , read_media ("idempotent_sequence_exception.png" )
202
222
203
223
mock_event = {"path" : "/my/path" , "httpMethod" : "GET" , "headers" : {"Accept-Encoding" : "deflate, gzip" }}
@@ -211,62 +231,100 @@ def read_image():
211
231
212
232
213
233
def test_compress_no_accept_encoding ():
234
+ # GIVEN a function with compress=True
235
+ # AND the request has no "Accept-Encoding" set to include gzip
214
236
app = ApiGatewayResolver ()
215
237
expected_value = "Foo"
216
238
217
239
@app .get ("/my/path" , compress = True )
218
- def return_text ():
240
+ def return_text () -> Tuple [ int , str , str ] :
219
241
return 200 , "text/plain" , expected_value
220
242
243
+ # WHEN calling the event handler
221
244
result = app ({"path" : "/my/path" , "httpMethod" : "GET" , "headers" : {}}, None )
222
245
246
+ # THEN don't perform any gzip compression
223
247
assert result ["isBase64Encoded" ] is False
224
248
assert result ["body" ] == expected_value
225
249
226
250
227
251
def test_cache_control_200 ():
252
+ # GIVEN a function with cache_control set
228
253
app = ApiGatewayResolver ()
229
254
230
255
@app .get ("/success" , cache_control = "max-age=600" )
231
- def with_cache_control ():
256
+ def with_cache_control () -> Tuple [ int , str , str ] :
232
257
return 200 , TEXT_HTML , "has 200 response"
233
258
234
259
def handler (event , context ):
235
260
return app .resolve (event , context )
236
261
262
+ # WHEN calling the event handler
263
+ # AND the function returns a 200 status code
237
264
result = handler ({"path" : "/success" , "httpMethod" : "GET" }, None )
238
265
266
+ # THEN return the set Cache-Control
239
267
headers = result ["headers" ]
240
268
assert headers ["Content-Type" ] == TEXT_HTML
241
269
assert headers ["Cache-Control" ] == "max-age=600"
242
270
243
271
244
272
def test_cache_control_non_200 ():
273
+ # GIVEN a function with cache_control set
245
274
app = ApiGatewayResolver ()
246
275
247
276
@app .delete ("/fails" , cache_control = "max-age=600" )
248
- def with_cache_control_has_500 ():
277
+ def with_cache_control_has_500 () -> Tuple [ int , str , str ] :
249
278
return 503 , TEXT_HTML , "has 503 response"
250
279
251
280
def handler (event , context ):
252
281
return app .resolve (event , context )
253
282
283
+ # WHEN calling the event handler
284
+ # AND the function returns a 503 status code
254
285
result = handler ({"path" : "/fails" , "httpMethod" : "DELETE" }, None )
255
286
287
+ # THEN return a Cache-Control of "no-cache"
256
288
headers = result ["headers" ]
257
289
assert headers ["Content-Type" ] == TEXT_HTML
258
290
assert headers ["Cache-Control" ] == "no-cache"
259
291
260
292
261
293
def test_rest_api ():
294
+ # GIVEN a function that returns a Dict
262
295
app = ApiGatewayResolver (proxy_type = ProxyEventType .http_api_v1 )
263
296
264
297
@app .get ("/my/path" )
265
- def rest_func ():
298
+ def rest_func () -> Dict :
266
299
return {"foo" : "value" }
267
300
301
+ # WHEN calling the event handler
268
302
result = app (LOAD_GW_EVENT , {})
269
303
304
+ # THEN automatically process this as a json rest api response
270
305
assert result ["statusCode" ] == 200
271
306
assert result ["headers" ]["Content-Type" ] == APPLICATION_JSON
272
307
assert result ["body" ] == json .dumps ({"foo" : "value" })
308
+
309
+
310
+ def test_handling_response_type ():
311
+ # GIVEN a function that returns Response
312
+ app = ApiGatewayResolver (proxy_type = ProxyEventType .http_api_v1 )
313
+
314
+ @app .get ("/my/path" )
315
+ def rest_func () -> Response :
316
+ return Response (
317
+ status_code = 404 ,
318
+ content_type = "used-if-not-set-in-header" ,
319
+ body = "Not found" ,
320
+ headers = {"Content-Type" : "header-content-type-wins" , "custom" : "value" },
321
+ )
322
+
323
+ # WHEN calling the event handler
324
+ result = app (LOAD_GW_EVENT , {})
325
+
326
+ # THEN the result can include some additional field control like overriding http headers
327
+ assert result ["statusCode" ] == 404
328
+ assert result ["headers" ]["Content-Type" ] == "header-content-type-wins"
329
+ assert result ["headers" ]["custom" ] == "value"
330
+ assert result ["body" ] == "Not found"
0 commit comments