allow default vhost

This commit is contained in:
Raphael Deem 2017-02-20 16:36:48 -08:00
parent ff5d4276bc
commit 9c72b557ec
3 changed files with 40 additions and 11 deletions

View File

@ -81,6 +81,19 @@ async def get_handler(request):
``` ```
There is also an optional `host` argument (which can be a list or a string). This restricts a route to the host or hosts provided. If there is a also a route with no host, it will be the default.
```python
@app.route('/get', methods=['GET'], host='example.com')
async def get_handler(request):
return text('GET request - {}'.format(request.args))
# if the host header doesn't match example.com, this route will be used
@app.route('/get', methods=['GET'])
async def get_handler(request):
return text('GET request in default - {}'.format(request.args))
```
There are also shorthand method decorators: There are also shorthand method decorators:
```python ```python
@ -168,8 +181,3 @@ url = app.url_for('post_handler', post_id=5, arg_one=['one', 'two'], arg_two=2,
# http://another_server:8888/posts/5?arg_one=one&arg_one=two&arg_two=2#anchor # http://another_server:8888/posts/5?arg_one=one&arg_one=two&arg_two=2#anchor
``` ```
- All valid parameters must be passed to `url_for` to build a URL. If a parameter is not supplied, or if a parameter does not match the specified type, a `URLBuildError` will be thrown. - All valid parameters must be passed to `url_for` to build a URL. If a parameter is not supplied, or if a parameter does not match the specified type, a `URLBuildError` will be thrown.

View File

@ -119,6 +119,9 @@ class Router:
for host_ in host: for host_ in host:
self.add(uri, methods, handler, host_) self.add(uri, methods, handler, host_)
return return
else:
# default host
self.hosts.add('*')
# Dict for faster lookups of if method allowed # Dict for faster lookups of if method allowed
if methods: if methods:
@ -258,16 +261,16 @@ class Router:
:param request: Request object :param request: Request object
:return: handler, arguments, keyword arguments :return: handler, arguments, keyword arguments
""" """
# Note - this means that if _any_ routes specify host, non-host routes # No virtual hosts specified; default behavior
# 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: if not self.hosts:
return self._get(request.url, request.method, '') return self._get(request.url, request.method, '')
else: # virtual hosts specified; try to match route to the host header
try:
return self._get(request.url, request.method, return self._get(request.url, request.method,
request.headers.get("Host", '')) request.headers.get("Host", ''))
# try default hosts
except NotFound:
return self._get(request.url, request.method, '')
@lru_cache(maxsize=ROUTER_CACHE_SIZE) @lru_cache(maxsize=ROUTER_CACHE_SIZE)
def _get(self, url, method, host): def _get(self, url, method, host):

View File

@ -36,3 +36,21 @@ def test_vhosts_with_list():
headers = {"Host": "world.com"} headers = {"Host": "world.com"}
request, response = app.test_client.get('/', headers=headers) request, response = app.test_client.get('/', headers=headers)
assert response.text == "Hello, world!" assert response.text == "Hello, world!"
def test_vhosts_with_defaults():
app = Sanic('test_vhosts')
@app.route('/', host="hello.com")
async def handler(request):
return text("Hello, world!")
@app.route('/')
async def handler(request):
return text("default")
headers = {"Host": "hello.com"}
request, response = app.test_client.get('/', headers=headers)
assert response.text == "Hello, world!"
request, response = app.test_client.get('/')
assert response.text == "default"