11from utils.variant import Variant
2- from collections import Dict, Optional
2+ from collections import Dict, List, Optional
33from collections.dict import _DictEntryIter
44
55from lightbug_http import NotFound, OK , HTTPService, HTTPRequest, HTTPResponse
6- from lightbug_http.strings import RequestMethod
6+ from lightbug_http.http import RequestMethod
7+ from lightbug_http.uri import URIDelimiters
78
89alias MAX_SUB_ROUTER_DEPTH = 20
910
@@ -14,15 +15,84 @@ struct RouterErrors:
1415 alias INVALID_PATH_FRAGMENT_ERROR = " INVALID_PATH_FRAGMENT_ERROR"
1516
1617
17- alias HTTPHandler = fn (req: HTTPRequest) - > HTTPResponse
18+ alias HTTPHandlerWrapper = fn (req: HTTPRequest) raises escaping - > HTTPResponse
19+
20+ # TODO : Placeholder type, what can the JSON container look like
21+ alias JSONType = Dict[String, String]
22+
23+ alias HandlerResponse = Variant[HTTPResponse, String, JSONType]
24+
25+
26+ trait FromReq (Movable , Copyable ):
27+ fn __init__ (out self , request : HTTPRequest, json : JSONType):
28+ ...
29+
30+ fn from_request (mut self , req : HTTPRequest) raises -> Self:
31+ ...
32+
33+ fn __str__ (self ) -> String:
34+ ...
1835
1936
2037@value
21- struct HandlerMeta :
22- var handler : HTTPHandler
38+ struct BaseRequest :
39+ var request : HTTPRequest
40+ var json : JSONType
41+
42+ fn __init__ (out self , request : HTTPRequest, json : JSONType):
43+ self .request = request
44+ self .json = json
2345
46+ fn __str__ (self ) -> String:
47+ return str (" " )
2448
25- alias HTTPHandlersMap = Dict[String, HandlerMeta]
49+ fn from_request (mut self , req : HTTPRequest) raises -> Self:
50+ return self
51+
52+
53+ @value
54+ struct RouteHandler[T: FromReq](CollectionElement):
55+ var handler : fn (T) raises - > HandlerResponse
56+
57+ fn __init__ (inout self , h : fn (T) raises - > HandlerResponse):
58+ self .handler = h
59+
60+ fn _encode_response (self , res : HandlerResponse) raises -> HTTPResponse:
61+ if res.isa[HTTPResponse]():
62+ return res[HTTPResponse]
63+ elif res.isa[String]():
64+ return OK(res[String])
65+ elif res.isa[JSONType]():
66+ return OK(self ._serialize_json(res[JSONType]))
67+ else :
68+ raise Error(" Unsupported response type" )
69+
70+ fn _serialize_json (self , json : JSONType) raises -> String:
71+ # TODO : Placeholder json serialize implementation
72+ fn ser (j : JSONType) raises -> String:
73+ var str_frags = List[String]()
74+ for kv in j.items():
75+ str_frags.append(
76+ ' "' + str (kv[].key) + ' ": "' + str (kv[].value) + ' "'
77+ )
78+
79+ var str_res = str (" {" ) + str (" ," ).join(str_frags) + str (" }" )
80+ return str_res
81+
82+ return ser(json)
83+
84+ fn _deserialize_json (self , req : HTTPRequest) raises -> JSONType:
85+ # TODO : Placeholder json deserialize implementation
86+ return JSONType()
87+
88+ fn handle (self , req : HTTPRequest) raises -> HTTPResponse:
89+ var payload = T(request = req, json = self ._deserialize_json(req))
90+ payload = payload.from_request(req)
91+ var handler_response = self .handler(payload)
92+ return self ._encode_response(handler_response^ )
93+
94+
95+ alias HTTPHandlersMap = Dict[String, HTTPHandlerWrapper]
2696
2797
2898@value
@@ -54,7 +124,7 @@ struct RouterBase[is_main_app: Bool = False](HTTPService):
54124
55125 fn _route (
56126 mut self , partial_path : String, method : String, depth : Int = 0
57- ) raises -> HandlerMeta :
127+ ) raises -> HTTPHandlerWrapper :
58128 if depth > MAX_SUB_ROUTER_DEPTH :
59129 raise Error(RouterErrors.ROUTE_NOT_FOUND_ERROR )
60130
@@ -63,8 +133,7 @@ struct RouterBase[is_main_app: Bool = False](HTTPService):
63133 var handler_path = partial_path
64134
65135 if partial_path:
66- # TODO : (Hrist) Update to lightbug_http.uri.URIDelimiters.PATH when available
67- var fragments = partial_path.split(" /" , 1 )
136+ var fragments = partial_path.split(URIDelimiters.PATH , 1 )
68137
69138 sub_router_name = fragments[0 ]
70139 if len (fragments) == 2 :
@@ -73,8 +142,7 @@ struct RouterBase[is_main_app: Bool = False](HTTPService):
73142 remaining_path = " "
74143
75144 else :
76- # TODO : (Hrist) Update to lightbug_http.uri.URIDelimiters.PATH when available
77- handler_path = " /"
145+ handler_path = URIDelimiters.PATH
78146
79147 if sub_router_name in self .sub_routers:
80148 return self .sub_routers[sub_router_name]._route(
@@ -87,17 +155,16 @@ struct RouterBase[is_main_app: Bool = False](HTTPService):
87155
88156 fn func (mut self , req : HTTPRequest) raises -> HTTPResponse:
89157 var uri = req.uri
90- # TODO : (Hrist) Update to lightbug_http.uri.URIDelimiters.PATH when available
91- var path = uri.path.split(" /" , 1 )[1 ]
92- var route_handler_meta : HandlerMeta
158+ var path = uri.path.split(URIDelimiters.PATH , 1 )[1 ]
159+ var route_handler_meta : HTTPHandlerWrapper
93160 try :
94161 route_handler_meta = self ._route(path, req.method)
95162 except e:
96163 if str (e) == RouterErrors.ROUTE_NOT_FOUND_ERROR :
97164 return NotFound(uri.path)
98165 raise e
99166
100- return route_handler_meta.handler (req)
167+ return route_handler_meta(req)
101168
102169 fn _validate_path_fragment (self , path_fragment : String) -> Bool:
103170 # TODO : Validate fragment
@@ -110,31 +177,51 @@ struct RouterBase[is_main_app: Bool = False](HTTPService):
110177 fn add_router (mut self , owned router : RouterBase[False ]) raises -> None :
111178 self .sub_routers[router.path_fragment] = router
112179
113- fn add_route (
180+ # fn register[T: FromReq](inout self, path: String, handler: fn(T) raises):
181+ #
182+ # fn handle(req: Request) raises:
183+ # RouteHandler[T](handler).handle(req)
184+ #
185+ # self.routes[path] = handle
186+ #
187+ # fn route(self, path: String, req: Request) raises:
188+ # if path in self.routes:
189+ # self.routes[path](req)
190+ # else:
191+
192+ fn add_route [
193+ T : FromReq
194+ ](
114195 mut self ,
115196 partial_path : String,
116- handler : HTTPHandler ,
197+ handler : fn (T) raises - > HandlerResponse ,
117198 method : RequestMethod = RequestMethod.get,
118199 ) raises -> None :
119200 if not self ._validate_path(partial_path):
120201 raise Error(RouterErrors.INVALID_PATH_ERROR )
121- var handler_meta = HandlerMeta(handler)
122202
123- self .routes[method.value][partial_path] = handler_meta^
203+ fn handle (req : HTTPRequest) raises -> HTTPResponse:
204+ return RouteHandler[T](handler).handle(req)
205+
206+ self .routes[method.value][partial_path] = handle^
124207
125- fn get (
208+ fn get [
209+ T : FromReq = BaseRequest
210+ ](
126211 inout self ,
127212 path : String,
128- handler : HTTPHandler ,
213+ handler : fn (T) raises - > HandlerResponse ,
129214 ) raises :
130- self .add_route(path, handler, RequestMethod.get)
215+ self .add_route[T] (path, handler, RequestMethod.get)
131216
132- fn post (
217+ fn post [
218+ T : FromReq = BaseRequest
219+ ](
133220 inout self ,
134221 path : String,
135- handler : HTTPHandler ,
222+ handler : fn (T) raises - > HandlerResponse ,
136223 ) raises :
137- self .add_route(path, handler, RequestMethod.post)
224+ self .add_route[T] (path, handler, RequestMethod.post)
138225
139226
140227alias RootRouter = RouterBase[True ]
0 commit comments