|
1 |
| -import os |
2 |
| - |
3 |
| -from .abstract import AbstractRouter |
4 |
| -from .http import HTTP, Stream |
5 |
| - |
6 |
| - |
7 |
| -class Router(AbstractRouter): |
8 |
| - """User should never construct Router""" |
9 |
| - |
10 |
| - # todo: I may want to change the constructor |
11 |
| - def __init__(self, default_get): |
12 |
| - self._routes = { |
13 |
| - 'GET': {}, |
14 |
| - 'POST': {} |
15 |
| - } |
16 |
| - self.default_get = default_get |
17 |
| - |
18 |
| - def register(self, method: str, route: str, handler): |
19 |
| - assert method in ['GET', 'POST'] # 这只是目前为了测试而加的限制 |
20 |
| - self._routes[method][route] = handler |
21 |
| - |
22 |
| - def find_match(self, path: str): |
23 |
| - """ |
24 |
| - 'user/{userId}' should match 'user/abc' |
25 |
| - userId = abc |
26 |
| - return a tuple (matched, parameters) |
27 |
| - matched is the route which matches the incoming path |
28 |
| - parameters is a dict of parameters and their values |
29 |
| - """ |
30 |
| - # todo: now the problem is how to implement it |
31 |
| - # todo: pattern matching should be independent from :method, |
32 |
| - # todo: but the current implementation doesn't support it. Should improve it later. |
33 |
| - for routes_of_this_method in self._routes.values(): |
34 |
| - for route in routes_of_this_method: |
35 |
| - matched, parameters = self._match(route, path) |
36 |
| - # this function returns the first match, not the best match |
37 |
| - if matched: |
38 |
| - return route, parameters |
39 |
| - return None, None |
40 |
| - |
41 |
| - @classmethod |
42 |
| - def _match(cls, route, path): |
43 |
| - # '/something/xxx/' to 'something/xxx'. Get rid of '/' at the left and the right end of a string |
44 |
| - route = route.lstrip('/').rstrip('/').split('/') |
45 |
| - path = path.lstrip('/').rstrip('/').split('/') |
46 |
| - print(route, path) |
47 |
| - if len(route) != len(path): |
48 |
| - return False, None |
49 |
| - else: |
50 |
| - # todo: implement it |
51 |
| - parameters = {} |
52 |
| - for r, p in zip(route, path): |
53 |
| - if r == p == '': |
54 |
| - return True, None |
55 |
| - if r[0] == '{' and r[-1] == '}': |
56 |
| - parameters[r[1:-1]] = p |
57 |
| - elif r != p: |
58 |
| - return False, None |
59 |
| - print('out of for loop') |
60 |
| - return True, parameters |
61 |
| - |
62 |
| - # async |
63 |
| - async def handle_route(self, http: HTTP, stream: Stream): |
64 |
| - print('app.App.handle_route') |
65 |
| - |
66 |
| - path = stream.headers[':path'] |
67 |
| - method = stream.headers[':method'] |
68 |
| - |
69 |
| - route, parameters = self.find_match(path) |
70 |
| - |
71 |
| - # 如果没有任何匹配,就默认为静态文件读取 |
72 |
| - if route is None: |
73 |
| - if method == 'GET': |
74 |
| - print('GET') |
75 |
| - handler = self.default_get |
76 |
| - else: |
77 |
| - handler = None |
78 |
| - else: |
79 |
| - handler = self._routes[method].get(route, None) |
80 |
| - |
81 |
| - if handler is not None: |
82 |
| - print('handle') |
83 |
| - print(handler) |
84 |
| - await handler(http, stream, parameters) |
85 |
| - else: |
86 |
| - # maybe raise an error? |
87 |
| - raise Exception(path, 'is not a valid request path') |
| 1 | +import os |
| 2 | + |
| 3 | +from .abstract import AbstractRouter |
| 4 | +from .http import HTTP, Stream |
| 5 | + |
| 6 | + |
| 7 | +class Router(AbstractRouter): |
| 8 | + """User should never construct Router""" |
| 9 | + |
| 10 | + # todo: I may want to change the constructor |
| 11 | + def __init__(self, default_get): |
| 12 | + self._routes = { |
| 13 | + 'GET': {}, |
| 14 | + 'POST': {} |
| 15 | + } |
| 16 | + self.default_get = default_get |
| 17 | + |
| 18 | + def register(self, method: str, route: str, handler): |
| 19 | + assert method in ['GET', 'POST'] # 这只是目前为了测试而加的限制 |
| 20 | + self._routes[method][route] = handler |
| 21 | + |
| 22 | + def find_match(self, path: str): |
| 23 | + """ |
| 24 | + 'user/{userId}' should match 'user/abc' |
| 25 | + userId = abc |
| 26 | + return a tuple (matched, parameters) |
| 27 | + matched is the route which matches the incoming path |
| 28 | + parameters is a dict of parameters and their values |
| 29 | + """ |
| 30 | + # todo: now the problem is how to implement it |
| 31 | + # todo: pattern matching should be independent from :method, |
| 32 | + # todo: but the current implementation doesn't support it. Should improve it later. |
| 33 | + for routes_of_this_method in self._routes.values(): |
| 34 | + for route in routes_of_this_method: |
| 35 | + matched, parameters = self._match(route, path) |
| 36 | + # this function returns the first match, not the best match |
| 37 | + if matched: |
| 38 | + return route, parameters |
| 39 | + return None, None |
| 40 | + |
| 41 | + @classmethod |
| 42 | + def _match(cls, route, path): |
| 43 | + # '/something/xxx/' to 'something/xxx'. Get rid of '/' at the left and the right end of a string |
| 44 | + route = route.lstrip('/').rstrip('/').split('/') |
| 45 | + path = path.lstrip('/').rstrip('/').split('/') |
| 46 | + print(route, path) |
| 47 | + if len(route) != len(path): |
| 48 | + return False, None |
| 49 | + else: |
| 50 | + # todo: optimize the logic |
| 51 | + parameters = {} |
| 52 | + for r, p in zip(route, path): |
| 53 | + if r == p == '': |
| 54 | + return True, None |
| 55 | + if r == '' and r != p: |
| 56 | + return False, None |
| 57 | + if r[0] == '{' and r[-1] == '}': |
| 58 | + parameters[r[1:-1]] = p |
| 59 | + elif r != p: |
| 60 | + return False, None |
| 61 | + print('out of for loop') |
| 62 | + return True, parameters |
| 63 | + |
| 64 | + # async |
| 65 | + async def handle_route(self, http: HTTP, stream: Stream): |
| 66 | + print('app.App.handle_route') |
| 67 | + |
| 68 | + path = stream.headers[':path'] |
| 69 | + method = stream.headers[':method'] |
| 70 | + |
| 71 | + route, parameters = self.find_match(path) |
| 72 | + |
| 73 | + # 如果没有任何匹配,就默认为静态文件读取 |
| 74 | + if route is None: |
| 75 | + if method == 'GET': |
| 76 | + print('GET') |
| 77 | + handler = self.default_get |
| 78 | + else: |
| 79 | + handler = None |
| 80 | + else: |
| 81 | + handler = self._routes[method].get(route, None) |
| 82 | + |
| 83 | + if handler is not None: |
| 84 | + print('handle') |
| 85 | + print(handler) |
| 86 | + await handler(http, stream, parameters) |
| 87 | + else: |
| 88 | + # maybe raise an error? |
| 89 | + raise Exception(path, 'is not a valid request path') |
0 commit comments