diff --git a/sanic/request.py b/sanic/request.py index 013a27ea..67c78b46 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -1,16 +1,10 @@ -import json import sys - +import json from cgi import parse_header from collections import namedtuple from http.cookies import SimpleCookie -from urllib.parse import parse_qs, urlunparse - from httptools import parse_url - -from sanic.exceptions import InvalidUsage -from sanic.log import error_logger, logger - +from urllib.parse import parse_qs, urlunparse try: from ujson import loads as json_loads @@ -24,6 +18,8 @@ except ImportError: else: json_loads = json.loads +from sanic.exceptions import InvalidUsage +from sanic.log import error_logger, logger DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream" @@ -71,6 +67,7 @@ class Request(dict): "_port", "__weakref__", "raw_url", + "_match_info", ) def __init__(self, url_bytes, headers, version, method, transport): @@ -93,6 +90,7 @@ class Request(dict): self.uri_template = None self._cookies = None self.stream = None + self._match_info = None def __repr__(self): if self.method is None or not self.path: @@ -273,8 +271,14 @@ class Request(dict): @property def match_info(self): """return matched info after resolving route""" + if self._match_info is not None: + return self._match_info return self.app.router.get(self)[2] + @match_info.setter + def match_info(self, value): + self._match_info = value + @property def path(self): return self._parsed_url.path.decode("utf-8") diff --git a/sanic/router.py b/sanic/router.py index 78a90346..e538d65c 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -1,15 +1,13 @@ import re import uuid - from collections import defaultdict, namedtuple from collections.abc import Iterable from functools import lru_cache from urllib.parse import unquote -from sanic.exceptions import MethodNotSupported, NotFound +from sanic.exceptions import NotFound, MethodNotSupported from sanic.views import CompositionView - Route = namedtuple( "Route", ["handler", "methods", "pattern", "parameters", "name", "uri"] ) @@ -393,15 +391,20 @@ class Router: """ # No virtual hosts specified; default behavior if not self.hosts: - return self._get(request.path, request.method, "") + processed = self._get(request.path, request.method, "") # virtual hosts specified; try to match route to the host header try: - return self._get( + processed = self._get( request.path, request.method, request.headers.get("Host", "") ) # try default hosts except NotFound: - return self._get(request.path, request.method, "") + processed = self._get(request.path, request.method, "") + + handler, args, kwargs, uri = processed + kwargs = kwargs if request._match_info is None else request._match_info + + return handler, args, kwargs, uri def get_supported_methods(self, url): """Get a list of supported methods for a url and optional host. @@ -479,4 +482,4 @@ class Router: handler.view_class, request.method.lower() ): handler = getattr(handler.view_class, request.method.lower()) - return hasattr(handler, "is_stream") + return hasattr(handler, "is_stream") \ No newline at end of file