From b442d78ebb255dc109443791336526d8df8ae50c Mon Sep 17 00:00:00 2001 From: Angus Hollands Date: Tue, 14 Feb 2017 20:32:04 +0000 Subject: [PATCH 1/2] Bugfix & simplfication for host based routing (if list of hosts passed after a previous vhost route was added, previously attempted to add set to set) Add comment documenting substandard behaviour --- sanic/router.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/sanic/router.py b/sanic/router.py index 24d0438f..4346d39c 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -1,5 +1,6 @@ import re from collections import defaultdict, namedtuple +from collections.abc import Collection from functools import lru_cache from .exceptions import NotFound, InvalidUsage from .views import CompositionView @@ -68,13 +69,13 @@ class Router: self.routes_static = {} self.routes_dynamic = defaultdict(list) self.routes_always_check = [] - self.hosts = None + self.hosts = set() def parse_parameter_string(self, parameter_string): """ Parse a parameter string into its constituent name, type, and pattern For example: - `parse_parameter_string(' + `parse_parameter_string('')` -> ('param_one', str, '[A-z]') :param parameter_string: String to parse @@ -106,20 +107,17 @@ class Router: """ if host is not None: - # we want to track if there are any - # vhosts on the Router instance so that we can - # default to the behavior without vhosts - if self.hosts is None: - self.hosts = set(host) - else: - if isinstance(host, list): - host = set(host) - self.hosts.add(host) if isinstance(host, str): uri = host + uri + self.hosts.add(host) + else: - for h in host: - self.add(uri, methods, handler, h) + if not isinstance(host, Collection): + raise ValueError("Expected either string of Collection of " + "host strings, not {!r}".format(host)) + + for host_ in host: + self.add(uri, methods, handler, host_) return # Dict for faster lookups of if method allowed @@ -262,7 +260,12 @@ class Router: :param request: Request object :return: handler, arguments, keyword arguments """ - if self.hosts is None: + # Note - this means that if _any_ routes specify host, non-host routes + # will typically fail as they are looked up by host + # fix - check if host is in host-based routing table (perhaps) or + # better, get candidate of routes and then dispatch by host. + # This may have perf issues. + if not self.hosts: return self._get(request.url, request.method, '') else: return self._get(request.url, request.method, From 742d4bff7892ca59fc47ccf5521f89cf78968d65 Mon Sep 17 00:00:00 2001 From: Angus Hollands Date: Tue, 14 Feb 2017 20:46:14 +0000 Subject: [PATCH 2/2] Change to iterable as Python3.5 doesn't support Collection. We don't really need the getitem and len attributes anyway --- sanic/router.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sanic/router.py b/sanic/router.py index 4346d39c..94379577 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -1,6 +1,6 @@ import re from collections import defaultdict, namedtuple -from collections.abc import Collection +from collections.abc import Iterable from functools import lru_cache from .exceptions import NotFound, InvalidUsage from .views import CompositionView @@ -112,8 +112,8 @@ class Router: self.hosts.add(host) else: - if not isinstance(host, Collection): - raise ValueError("Expected either string of Collection of " + if not isinstance(host, Iterable): + raise ValueError("Expected either string or Iterable of " "host strings, not {!r}".format(host)) for host_ in host: