51
51
# API GW/ALB decode non-safe URI chars; we must support them too
52
52
_UNSAFE_URI = r"%<> \[\]{}|^"
53
53
_NAMED_GROUP_BOUNDARY_PATTERN = rf"(?P\1[{ _SAFE_URI } { _UNSAFE_URI } \\w]+)"
54
+ _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION = "Successful Response"
54
55
_ROUTE_REGEX = "^{}$"
55
56
56
57
if TYPE_CHECKING :
@@ -203,9 +204,13 @@ def __init__(
203
204
cors : bool ,
204
205
compress : bool ,
205
206
cache_control : Optional [str ],
206
- middlewares : Optional [List [ Callable [..., Response ]] ],
207
+ summary : Optional [str ],
207
208
description : Optional [str ],
209
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]],
210
+ response_description : Optional [str ],
208
211
tags : Optional [List ["Tag" ]],
212
+ operation_id : Optional [str ],
213
+ middlewares : Optional [List [Callable [..., Response ]]],
209
214
):
210
215
"""
211
216
@@ -214,10 +219,10 @@ def __init__(
214
219
215
220
method: str
216
221
The HTTP method, example "GET"
217
- rule: Pattern
218
- The route rule, example "/my/path"
219
222
path: str
220
223
The path of the route
224
+ rule: Pattern
225
+ The route rule, example "/my/path"
221
226
func: Callable
222
227
The route handler function
223
228
cors: bool
@@ -226,12 +231,20 @@ def __init__(
226
231
Whether or not to enable gzip compression for this route
227
232
cache_control: Optional[str]
228
233
The cache control header value, example "max-age=3600"
229
- middlewares : Optional[List[Callable[..., Response]] ]
230
- The list of route middlewares to be called in order.
234
+ summary : Optional[str ]
235
+ The OpenAPI summary for this route
231
236
description: Optional[str]
232
237
The OpenAPI description for this route
238
+ responses: Optional[Dict[Union[int, str], Dict[str, Any]]]
239
+ The OpenAPI responses for this route
240
+ response_description: Optional[str]
241
+ The OpenAPI response description for this route
233
242
tags: Optional[List[Tag]]
234
243
The list of OpenAPI tags to be used for this route
244
+ operation_id: Optional[str]
245
+ The OpenAPI operationId for this route
246
+ middlewares: Optional[List[Callable[..., Response]]]
247
+ The list of route middlewares to be called in order.
235
248
"""
236
249
self .method = method .upper ()
237
250
self .path = path
@@ -241,10 +254,13 @@ def __init__(
241
254
self .cors = cors
242
255
self .compress = compress
243
256
self .cache_control = cache_control
244
- self .middlewares = middlewares or []
257
+ self .summary = summary
245
258
self .description = description
259
+ self .responses = responses
260
+ self .response_description = response_description
246
261
self .tags = tags or []
247
- self .operation_id = self .method .title () + self .func .__name__ .title ()
262
+ self .middlewares = middlewares or []
263
+ self .operation_id = operation_id or (self .method .title () + self .func .__name__ .title ())
248
264
249
265
# _middleware_stack_built is used to ensure the middleware stack is only built once.
250
266
self ._middleware_stack_built = False
@@ -372,7 +388,7 @@ def _get_openapi_path(
372
388
373
389
responses = operation .setdefault ("responses" , {})
374
390
success_response = responses .setdefault ("200" , {})
375
- success_response ["description" ] = "Success"
391
+ success_response ["description" ] = self . response_description or _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION
376
392
success_response ["content" ] = {"application/json" : {"schema" : {}}}
377
393
json_response = success_response ["content" ].setdefault ("application/json" , {})
378
394
@@ -391,7 +407,7 @@ def _get_openapi_path(
391
407
return path , definitions
392
408
393
409
def _openapi_operation_summary (self ) -> str :
394
- return f"{ self .method .upper ()} { self .path } "
410
+ return self . summary or f"{ self .method .upper ()} { self .path } "
395
411
396
412
def _openapi_operation_metadata (self , operation_ids : Set [str ]) -> Dict [str , Any ]:
397
413
operation : Dict [str , Any ] = {}
@@ -598,8 +614,12 @@ def route(
598
614
cors : Optional [bool ] = None ,
599
615
compress : bool = False ,
600
616
cache_control : Optional [str ] = None ,
617
+ summary : Optional [str ] = None ,
601
618
description : Optional [str ] = None ,
619
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
620
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
602
621
tags : Optional [List ["Tag" ]] = None ,
622
+ operation_id : Optional [str ] = None ,
603
623
middlewares : Optional [List [Callable [..., Any ]]] = None ,
604
624
):
605
625
raise NotImplementedError ()
@@ -651,9 +671,13 @@ def get(
651
671
cors : Optional [bool ] = None ,
652
672
compress : bool = False ,
653
673
cache_control : Optional [str ] = None ,
654
- middlewares : Optional [List [ Callable [..., Any ]] ] = None ,
674
+ summary : Optional [str ] = None ,
655
675
description : Optional [str ] = None ,
676
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
677
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
656
678
tags : Optional [List ["Tag" ]] = None ,
679
+ operation_id : Optional [str ] = None ,
680
+ middlewares : Optional [List [Callable [..., Any ]]] = None ,
657
681
):
658
682
"""Get route decorator with GET `method`
659
683
@@ -677,17 +701,34 @@ def lambda_handler(event, context):
677
701
return app.resolve(event, context)
678
702
```
679
703
"""
680
- return self .route (rule , "GET" , cors , compress , cache_control , description , tags , middlewares )
704
+ return self .route (
705
+ rule ,
706
+ "GET" ,
707
+ cors ,
708
+ compress ,
709
+ cache_control ,
710
+ summary ,
711
+ description ,
712
+ responses ,
713
+ response_description ,
714
+ tags ,
715
+ operation_id ,
716
+ middlewares ,
717
+ )
681
718
682
719
def post (
683
720
self ,
684
721
rule : str ,
685
722
cors : Optional [bool ] = None ,
686
723
compress : bool = False ,
687
724
cache_control : Optional [str ] = None ,
688
- middlewares : Optional [List [ Callable [..., Any ]] ] = None ,
725
+ summary : Optional [str ] = None ,
689
726
description : Optional [str ] = None ,
727
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
728
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
690
729
tags : Optional [List ["Tag" ]] = None ,
730
+ operation_id : Optional [str ] = None ,
731
+ middlewares : Optional [List [Callable [..., Any ]]] = None ,
691
732
):
692
733
"""Post route decorator with POST `method`
693
734
@@ -712,17 +753,34 @@ def lambda_handler(event, context):
712
753
return app.resolve(event, context)
713
754
```
714
755
"""
715
- return self .route (rule , "POST" , cors , compress , cache_control , description , tags , middlewares )
756
+ return self .route (
757
+ rule ,
758
+ "POST" ,
759
+ cors ,
760
+ compress ,
761
+ cache_control ,
762
+ summary ,
763
+ description ,
764
+ responses ,
765
+ response_description ,
766
+ tags ,
767
+ operation_id ,
768
+ middlewares ,
769
+ )
716
770
717
771
def put (
718
772
self ,
719
773
rule : str ,
720
774
cors : Optional [bool ] = None ,
721
775
compress : bool = False ,
722
776
cache_control : Optional [str ] = None ,
723
- middlewares : Optional [List [ Callable [..., Any ]] ] = None ,
777
+ summary : Optional [str ] = None ,
724
778
description : Optional [str ] = None ,
779
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
780
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
725
781
tags : Optional [List ["Tag" ]] = None ,
782
+ operation_id : Optional [str ] = None ,
783
+ middlewares : Optional [List [Callable [..., Any ]]] = None ,
726
784
):
727
785
"""Put route decorator with PUT `method`
728
786
@@ -747,17 +805,34 @@ def lambda_handler(event, context):
747
805
return app.resolve(event, context)
748
806
```
749
807
"""
750
- return self .route (rule , "PUT" , cors , compress , cache_control , description , tags , middlewares )
808
+ return self .route (
809
+ rule ,
810
+ "PUT" ,
811
+ cors ,
812
+ compress ,
813
+ cache_control ,
814
+ summary ,
815
+ description ,
816
+ responses ,
817
+ response_description ,
818
+ tags ,
819
+ operation_id ,
820
+ middlewares ,
821
+ )
751
822
752
823
def delete (
753
824
self ,
754
825
rule : str ,
755
826
cors : Optional [bool ] = None ,
756
827
compress : bool = False ,
757
828
cache_control : Optional [str ] = None ,
758
- middlewares : Optional [List [ Callable [..., Any ]] ] = None ,
829
+ summary : Optional [str ] = None ,
759
830
description : Optional [str ] = None ,
831
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
832
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
760
833
tags : Optional [List ["Tag" ]] = None ,
834
+ operation_id : Optional [str ] = None ,
835
+ middlewares : Optional [List [Callable [..., Any ]]] = None ,
761
836
):
762
837
"""Delete route decorator with DELETE `method`
763
838
@@ -781,17 +856,34 @@ def lambda_handler(event, context):
781
856
return app.resolve(event, context)
782
857
```
783
858
"""
784
- return self .route (rule , "DELETE" , cors , compress , cache_control , description , tags , middlewares )
859
+ return self .route (
860
+ rule ,
861
+ "DELETE" ,
862
+ cors ,
863
+ compress ,
864
+ cache_control ,
865
+ summary ,
866
+ description ,
867
+ responses ,
868
+ response_description ,
869
+ tags ,
870
+ operation_id ,
871
+ middlewares ,
872
+ )
785
873
786
874
def patch (
787
875
self ,
788
876
rule : str ,
789
877
cors : Optional [bool ] = None ,
790
878
compress : bool = False ,
791
879
cache_control : Optional [str ] = None ,
792
- middlewares : Optional [List [ Callable ] ] = None ,
880
+ summary : Optional [str ] = None ,
793
881
description : Optional [str ] = None ,
882
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
883
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
794
884
tags : Optional [List ["Tag" ]] = None ,
885
+ operation_id : Optional [str ] = None ,
886
+ middlewares : Optional [List [Callable ]] = None ,
795
887
):
796
888
"""Patch route decorator with PATCH `method`
797
889
@@ -818,7 +910,20 @@ def lambda_handler(event, context):
818
910
return app.resolve(event, context)
819
911
```
820
912
"""
821
- return self .route (rule , "PATCH" , cors , compress , cache_control , description , tags , middlewares )
913
+ return self .route (
914
+ rule ,
915
+ "PATCH" ,
916
+ cors ,
917
+ compress ,
918
+ cache_control ,
919
+ summary ,
920
+ description ,
921
+ responses ,
922
+ response_description ,
923
+ tags ,
924
+ operation_id ,
925
+ middlewares ,
926
+ )
822
927
823
928
def _push_processed_stack_frame (self , frame : str ):
824
929
"""
@@ -1204,8 +1309,12 @@ def route(
1204
1309
cors : Optional [bool ] = None ,
1205
1310
compress : bool = False ,
1206
1311
cache_control : Optional [str ] = None ,
1312
+ summary : Optional [str ] = None ,
1207
1313
description : Optional [str ] = None ,
1314
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
1315
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
1208
1316
tags : Optional [List ["Tag" ]] = None ,
1317
+ operation_id : Optional [str ] = None ,
1209
1318
middlewares : Optional [List [Callable [..., Any ]]] = None ,
1210
1319
):
1211
1320
"""Route decorator includes parameter `method`"""
@@ -1225,9 +1334,13 @@ def register_resolver(func: Callable):
1225
1334
cors_enabled ,
1226
1335
compress ,
1227
1336
cache_control ,
1228
- middlewares ,
1337
+ summary ,
1229
1338
description ,
1339
+ responses ,
1340
+ response_description ,
1230
1341
tags ,
1342
+ operation_id ,
1343
+ middlewares ,
1231
1344
)
1232
1345
1233
1346
# The more specific route wins.
@@ -1628,15 +1741,31 @@ def route(
1628
1741
cors : Optional [bool ] = None ,
1629
1742
compress : bool = False ,
1630
1743
cache_control : Optional [str ] = None ,
1744
+ summary : Optional [str ] = None ,
1631
1745
description : Optional [str ] = None ,
1746
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
1747
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
1632
1748
tags : Optional [List ["Tag" ]] = None ,
1749
+ operation_id : Optional [str ] = None ,
1633
1750
middlewares : Optional [List [Callable [..., Any ]]] = None ,
1634
1751
):
1635
1752
def register_route (func : Callable ):
1636
1753
# Convert methods to tuple. It needs to be hashable as its part of the self._routes dict key
1637
1754
methods = (method ,) if isinstance (method , str ) else tuple (method )
1638
1755
1639
- route_key = (rule , methods , cors , compress , cache_control , description , tags )
1756
+ route_key = (
1757
+ rule ,
1758
+ methods ,
1759
+ cors ,
1760
+ compress ,
1761
+ cache_control ,
1762
+ summary ,
1763
+ description ,
1764
+ responses ,
1765
+ response_description ,
1766
+ tags ,
1767
+ operation_id ,
1768
+ )
1640
1769
1641
1770
# Collate Middleware for routes
1642
1771
if middlewares is not None :
@@ -1676,12 +1805,29 @@ def route(
1676
1805
cors : Optional [bool ] = None ,
1677
1806
compress : bool = False ,
1678
1807
cache_control : Optional [str ] = None ,
1808
+ summary : Optional [str ] = None ,
1679
1809
description : Optional [str ] = None ,
1810
+ responses : Optional [Dict [Union [int , str ], Dict [str , Any ]]] = None ,
1811
+ response_description : Optional [str ] = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION ,
1680
1812
tags : Optional [List ["Tag" ]] = None ,
1813
+ operation_id : Optional [str ] = None ,
1681
1814
middlewares : Optional [List [Callable [..., Any ]]] = None ,
1682
1815
):
1683
1816
# NOTE: see #1552 for more context.
1684
- return super ().route (rule .rstrip ("/" ), method , cors , compress , cache_control , description , tags , middlewares )
1817
+ return super ().route (
1818
+ rule .rstrip ("/" ),
1819
+ method ,
1820
+ cors ,
1821
+ compress ,
1822
+ cache_control ,
1823
+ summary ,
1824
+ description ,
1825
+ responses ,
1826
+ response_description ,
1827
+ tags ,
1828
+ operation_id ,
1829
+ middlewares ,
1830
+ )
1685
1831
1686
1832
# Override _compile_regex to exclude trailing slashes for route resolution
1687
1833
@staticmethod
0 commit comments