88"""
99
1010try :
11- from typing import Callable , Protocol , Union , List , Tuple
11+ from typing import Callable , Protocol , Union , List , Set , Tuple
1212 from socket import socket
1313 from socketpool import SocketPool
1414except ImportError :
@@ -51,20 +51,28 @@ def __init__(
5151 self ._auths = []
5252 self ._buffer = bytearray (1024 )
5353 self ._timeout = 1
54- self .routes = _Routes ()
54+ self ._routes = _Routes ()
5555 self ._socket_source = socket_source
5656 self ._sock = None
5757 self .root_path = root_path
5858 self .stopped = False
5959
6060 self .debug = debug
6161
62- def route (self , path : str , methods : Union [str , List [str ]] = GET ) -> Callable :
62+ def route (
63+ self ,
64+ path : str ,
65+ methods : Union [str , Set [str ]] = GET ,
66+ * ,
67+ append_slash : bool = False ,
68+ ) -> Callable :
6369 """
6470 Decorator used to add a route.
6571
6672 :param str path: URL path
6773 :param str methods: HTTP method(s): ``"GET"``, ``"POST"``, ``["GET", "POST"]`` etc.
74+ :param bool append_slash: If True, the route will be accessible with and without a
75+ trailing slash
6876
6977 Example::
7078
@@ -78,6 +86,14 @@ def route_func(request):
7886 def route_func(request):
7987 ...
8088
89+ # If you want to access URL with and without trailing slash, use append_slash=True
90+ @server.route("/example-with-slash", append_slash=True)
91+ # which is equivalent to
92+ @server.route("/example-with-slash")
93+ @server.route("/example-with-slash/")
94+ def route_func(request):
95+ ...
96+
8197 # Multiple methods can be specified
8298 @server.route("/example", [GET, POST])
8399 def route_func(request):
@@ -88,12 +104,13 @@ def route_func(request):
88104 def route_func(request, my_parameter):
89105 ...
90106 """
91- if isinstance (methods , str ):
92- methods = [methods ]
107+ if path .endswith ("/" ) and append_slash :
108+ raise ValueError ("Cannot use append_slash=True when path ends with /" )
109+
110+ methods = methods if isinstance (methods , set ) else {methods }
93111
94112 def route_decorator (func : Callable ) -> Callable :
95- for method in methods :
96- self .routes .add (_Route (path , method ), func )
113+ self ._routes .add (_Route (path , methods , append_slash ), func )
97114 return func
98115
99116 return route_decorator
@@ -294,7 +311,9 @@ def poll(self):
294311 _debug_incoming_request (request )
295312
296313 # Find a handler for the route
297- handler = self .routes .find_handler (_Route (request .path , request .method ))
314+ handler = self ._routes .find_handler (
315+ _Route (request .path , request .method )
316+ )
298317
299318 # Handle the request
300319 self ._handle_request (request , handler )
0 commit comments