Merge pull request #932 from lixxu/master
static files url building using url_for
This commit is contained in:
commit
d8c8ccd180
|
@ -93,7 +93,14 @@ def ignore_404s(request, exception):
|
||||||
Static files can be served globally, under the blueprint prefix.
|
Static files can be served globally, under the blueprint prefix.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
bp.static('/folder/to/serve', '/web/path')
|
|
||||||
|
# suppose bp.name == 'bp'
|
||||||
|
|
||||||
|
bp.static('/web/path', '/folder/to/serve')
|
||||||
|
# also you can pass name parameter to it for url_for
|
||||||
|
bp.static('/web/path', '/folder/to/server', name='uploads')
|
||||||
|
app.url_for('static', name='bp.uploads', filename='file.txt') == '/bp/web/path/file.txt'
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Start and stop
|
## Start and stop
|
||||||
|
|
|
@ -301,3 +301,34 @@ def handler(request):
|
||||||
# app.url_for('handler') == '/get'
|
# app.url_for('handler') == '/get'
|
||||||
# app.url_for('post_handler') == '/post'
|
# app.url_for('post_handler') == '/post'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Build URL for static files
|
||||||
|
|
||||||
|
You can use `url_for` for static file url building now.
|
||||||
|
If it's for file directly, `filename` can be ignored.
|
||||||
|
|
||||||
|
```python
|
||||||
|
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static('/static', './static')
|
||||||
|
app.static('/uploads', './uploads', name='uploads')
|
||||||
|
app.static('/the_best.png', '/home/ubuntu/test.png', name='best_png')
|
||||||
|
|
||||||
|
bp = Blueprint('bp', url_prefix='bp')
|
||||||
|
bp.static('/static', './static')
|
||||||
|
bp.static('/uploads', './uploads', name='uploads')
|
||||||
|
bp.static('/the_best.png', '/home/ubuntu/test.png', name='best_png')
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
# then build the url
|
||||||
|
app.url_for('static', filename='file.txt') == '/static/file.txt'
|
||||||
|
app.url_for('static', name='static', filename='file.txt') == '/static/file.txt'
|
||||||
|
app.url_for('static', name='uploads', filename='file.txt') == '/uploads/file.txt'
|
||||||
|
app.url_for('static', name='best_png') == '/the_best.png'
|
||||||
|
|
||||||
|
# blueprint url building
|
||||||
|
app.url_for('static', name='bp.static', filename='file.txt') == '/bp/static/file.txt'
|
||||||
|
app.url_for('static', name='bp.uploads', filename='file.txt') == '/bp/uploads/file.txt'
|
||||||
|
app.url_for('static', name='bp.best_png') == '/bp/static/the_best.png'
|
||||||
|
|
||||||
|
```
|
||||||
|
|
|
@ -6,16 +6,40 @@ filename. The file specified will then be accessible via the given endpoint.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
|
from sanic.blueprints import Blueprint
|
||||||
|
|
||||||
app = Sanic(__name__)
|
app = Sanic(__name__)
|
||||||
|
|
||||||
# Serves files from the static folder to the URL /static
|
# Serves files from the static folder to the URL /static
|
||||||
app.static('/static', './static')
|
app.static('/static', './static')
|
||||||
|
# use url_for to build the url, name defaults to 'static' and can be ignored
|
||||||
|
app.url_for('static', filename='file.txt') == '/static/file.txt'
|
||||||
|
app.url_for('static', name='static', filename='file.txt') == '/static/file.txt'
|
||||||
|
|
||||||
# Serves the file /home/ubuntu/test.png when the URL /the_best.png
|
# Serves the file /home/ubuntu/test.png when the URL /the_best.png
|
||||||
# is requested
|
# is requested
|
||||||
app.static('/the_best.png', '/home/ubuntu/test.png')
|
app.static('/the_best.png', '/home/ubuntu/test.png', name='best_png')
|
||||||
|
|
||||||
|
# you can use url_for to build the static file url
|
||||||
|
# you can ignore name and filename parameters if you don't define it
|
||||||
|
app.url_for('static', name='best_png') == '/the_best.png'
|
||||||
|
app.url_for('static', name='best_png', filename='any') == '/the_best.png'
|
||||||
|
|
||||||
|
# you need define the name for other static files
|
||||||
|
app.static('/another.png', '/home/ubuntu/another.png', name='another')
|
||||||
|
app.url_for('static', name='another') == '/another.png'
|
||||||
|
app.url_for('static', name='another', filename='any') == '/another.png'
|
||||||
|
|
||||||
|
# also, you can use static for blueprint
|
||||||
|
bp = Blueprint('bp', url_prefix='/bp')
|
||||||
|
bp.static('/static', './static')
|
||||||
|
|
||||||
|
# servers the file directly
|
||||||
|
bp.static('/the_best.png', '/home/ubuntu/test.png', name='best_png')
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
app.url_for('static', name='bp.static', filename='file.txt') == '/bp/static/file.txt'
|
||||||
|
app.url_for('static', name='bp.best_png') == '/bp/test_best.png'
|
||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000)
|
app.run(host="0.0.0.0", port=8000)
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: currently you cannot build a URL for a static file using `url_for`.
|
|
||||||
|
|
35
sanic/app.py
35
sanic/app.py
|
@ -354,13 +354,13 @@ class Sanic:
|
||||||
# Static Files
|
# Static Files
|
||||||
def static(self, uri, file_or_directory, pattern=r'/?.+',
|
def static(self, uri, file_or_directory, pattern=r'/?.+',
|
||||||
use_modified_since=True, use_content_range=False,
|
use_modified_since=True, use_content_range=False,
|
||||||
stream_large_files=False):
|
stream_large_files=False, name='static'):
|
||||||
"""Register a root to serve files from. The input can either be a
|
"""Register a root to serve files from. The input can either be a
|
||||||
file or a directory. See
|
file or a directory. See
|
||||||
"""
|
"""
|
||||||
static_register(self, uri, file_or_directory, pattern,
|
static_register(self, uri, file_or_directory, pattern,
|
||||||
use_modified_since, use_content_range,
|
use_modified_since, use_content_range,
|
||||||
stream_large_files)
|
stream_large_files, name)
|
||||||
|
|
||||||
def blueprint(self, blueprint, **options):
|
def blueprint(self, blueprint, **options):
|
||||||
"""Register a blueprint on the application.
|
"""Register a blueprint on the application.
|
||||||
|
@ -410,12 +410,32 @@ class Sanic:
|
||||||
URLBuildError
|
URLBuildError
|
||||||
"""
|
"""
|
||||||
# find the route by the supplied view name
|
# find the route by the supplied view name
|
||||||
uri, route = self.router.find_route_by_view_name(view_name)
|
kw = {}
|
||||||
|
# special static files url_for
|
||||||
|
if view_name == 'static':
|
||||||
|
kw.update(name=kwargs.pop('name', 'static'))
|
||||||
|
elif view_name.endswith('.static'): # blueprint.static
|
||||||
|
kwargs.pop('name', None)
|
||||||
|
kw.update(name=view_name)
|
||||||
|
|
||||||
if not uri or not route:
|
uri, route = self.router.find_route_by_view_name(view_name, **kw)
|
||||||
|
if not (uri and route):
|
||||||
raise URLBuildError('Endpoint with name `{}` was not found'.format(
|
raise URLBuildError('Endpoint with name `{}` was not found'.format(
|
||||||
view_name))
|
view_name))
|
||||||
|
|
||||||
|
if view_name == 'static' or view_name.endswith('.static'):
|
||||||
|
filename = kwargs.pop('filename', None)
|
||||||
|
# it's static folder
|
||||||
|
if '<file_uri:' in uri:
|
||||||
|
folder_ = uri.split('<file_uri:', 1)[0]
|
||||||
|
if folder_.endswith('/'):
|
||||||
|
folder_ = folder_[:-1]
|
||||||
|
|
||||||
|
if filename.startswith('/'):
|
||||||
|
filename = filename[1:]
|
||||||
|
|
||||||
|
uri = '{}/{}'.format(folder_, filename)
|
||||||
|
|
||||||
if uri != '/' and uri.endswith('/'):
|
if uri != '/' and uri.endswith('/'):
|
||||||
uri = uri[:-1]
|
uri = uri[:-1]
|
||||||
|
|
||||||
|
@ -438,6 +458,13 @@ class Sanic:
|
||||||
if netloc is None and external:
|
if netloc is None and external:
|
||||||
netloc = self.config.get('SERVER_NAME', '')
|
netloc = self.config.get('SERVER_NAME', '')
|
||||||
|
|
||||||
|
if external:
|
||||||
|
if not scheme:
|
||||||
|
scheme = netloc[:8].split(':', 1)[0]
|
||||||
|
|
||||||
|
if '://' in netloc[:8]:
|
||||||
|
netloc = netloc.split('://', 1)[-1]
|
||||||
|
|
||||||
for match in matched_params:
|
for match in matched_params:
|
||||||
name, _type, pattern = self.router.parse_parameter_string(
|
name, _type, pattern = self.router.parse_parameter_string(
|
||||||
match)
|
match)
|
||||||
|
|
|
@ -218,6 +218,11 @@ class Blueprint:
|
||||||
:param uri: endpoint at which the route will be accessible.
|
:param uri: endpoint at which the route will be accessible.
|
||||||
:param file_or_directory: Static asset.
|
:param file_or_directory: Static asset.
|
||||||
"""
|
"""
|
||||||
|
name = kwargs.pop('name', 'static')
|
||||||
|
if not name.startswith(self.name + '.'):
|
||||||
|
name = '{}.{}'.format(self.name, name)
|
||||||
|
|
||||||
|
kwargs.update(name=name)
|
||||||
static = FutureStatic(uri, file_or_directory, args, kwargs)
|
static = FutureStatic(uri, file_or_directory, args, kwargs)
|
||||||
self.statics.append(static)
|
self.statics.append(static)
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ class Router:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.routes_all = {}
|
self.routes_all = {}
|
||||||
self.routes_names = {}
|
self.routes_names = {}
|
||||||
|
self.routes_static_files = {}
|
||||||
self.routes_static = {}
|
self.routes_static = {}
|
||||||
self.routes_dynamic = defaultdict(list)
|
self.routes_dynamic = defaultdict(list)
|
||||||
self.routes_always_check = []
|
self.routes_always_check = []
|
||||||
|
@ -148,6 +149,7 @@ class Router:
|
||||||
provided, any method is allowed
|
provided, any method is allowed
|
||||||
:param handler: request handler function.
|
:param handler: request handler function.
|
||||||
When executed, it should provide a response object.
|
When executed, it should provide a response object.
|
||||||
|
:param name: user defined route name for url_for
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
"""
|
"""
|
||||||
if host is not None:
|
if host is not None:
|
||||||
|
@ -231,6 +233,12 @@ class Router:
|
||||||
|
|
||||||
# prefix the handler name with the blueprint name
|
# prefix the handler name with the blueprint name
|
||||||
# if available
|
# if available
|
||||||
|
# special prefix for static files
|
||||||
|
is_static = False
|
||||||
|
if name and name.startswith('_static_'):
|
||||||
|
is_static = True
|
||||||
|
name = name.split('_static_', 1)[-1]
|
||||||
|
|
||||||
if hasattr(handler, '__blueprintname__'):
|
if hasattr(handler, '__blueprintname__'):
|
||||||
handler_name = '{}.{}'.format(
|
handler_name = '{}.{}'.format(
|
||||||
handler.__blueprintname__, name or handler.__name__)
|
handler.__blueprintname__, name or handler.__name__)
|
||||||
|
@ -245,8 +253,14 @@ class Router:
|
||||||
parameters=parameters, name=handler_name, uri=uri)
|
parameters=parameters, name=handler_name, uri=uri)
|
||||||
|
|
||||||
self.routes_all[uri] = route
|
self.routes_all[uri] = route
|
||||||
pairs = self.routes_names.get(handler_name)
|
if is_static:
|
||||||
if not (pairs and (pairs[0] + '/' == uri or uri + '/' == pairs[0])):
|
pair = self.routes_static_files.get(handler_name)
|
||||||
|
if not (pair and (pair[0] + '/' == uri or uri + '/' == pair[0])):
|
||||||
|
self.routes_static_files[handler_name] = (uri, route)
|
||||||
|
|
||||||
|
else:
|
||||||
|
pair = self.routes_names.get(handler_name)
|
||||||
|
if not (pair and (pair[0] + '/' == uri or uri + '/' == pair[0])):
|
||||||
self.routes_names[handler_name] = (uri, route)
|
self.routes_names[handler_name] = (uri, route)
|
||||||
|
|
||||||
if properties['unhashable']:
|
if properties['unhashable']:
|
||||||
|
@ -274,6 +288,11 @@ class Router:
|
||||||
self.routes_names.pop(handler_name)
|
self.routes_names.pop(handler_name)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
for handler_name, pairs in self.routes_static_files.items():
|
||||||
|
if pairs[0] == uri:
|
||||||
|
self.routes_static_files.pop(handler_name)
|
||||||
|
break
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise RouteDoesNotExist("Route was not registered: {}".format(uri))
|
raise RouteDoesNotExist("Route was not registered: {}".format(uri))
|
||||||
|
|
||||||
|
@ -289,15 +308,19 @@ class Router:
|
||||||
self._get.cache_clear()
|
self._get.cache_clear()
|
||||||
|
|
||||||
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
|
@lru_cache(maxsize=ROUTER_CACHE_SIZE)
|
||||||
def find_route_by_view_name(self, view_name):
|
def find_route_by_view_name(self, view_name, name=None):
|
||||||
"""Find a route in the router based on the specified view name.
|
"""Find a route in the router based on the specified view name.
|
||||||
|
|
||||||
:param view_name: string of view name to search by
|
:param view_name: string of view name to search by
|
||||||
|
:param kwargs: additional params, usually for static files
|
||||||
:return: tuple containing (uri, Route)
|
:return: tuple containing (uri, Route)
|
||||||
"""
|
"""
|
||||||
if not view_name:
|
if not view_name:
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
|
if view_name == 'static' or view_name.endswith('.static'):
|
||||||
|
return self.routes_static_files.get(name, (None, None))
|
||||||
|
|
||||||
return self.routes_names.get(view_name, (None, None))
|
return self.routes_names.get(view_name, (None, None))
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
|
|
@ -18,7 +18,7 @@ from sanic.response import file, file_stream, HTTPResponse
|
||||||
|
|
||||||
def register(app, uri, file_or_directory, pattern,
|
def register(app, uri, file_or_directory, pattern,
|
||||||
use_modified_since, use_content_range,
|
use_modified_since, use_content_range,
|
||||||
stream_large_files):
|
stream_large_files, name='static'):
|
||||||
# TODO: Though sanic is not a file server, I feel like we should at least
|
# TODO: Though sanic is not a file server, I feel like we should at least
|
||||||
# make a good effort here. Modified-since is nice, but we could
|
# make a good effort here. Modified-since is nice, but we could
|
||||||
# also look into etags, expires, and caching
|
# also look into etags, expires, and caching
|
||||||
|
@ -39,6 +39,7 @@ def register(app, uri, file_or_directory, pattern,
|
||||||
than the file() handler to send the file
|
than the file() handler to send the file
|
||||||
If this is an integer, this represents the
|
If this is an integer, this represents the
|
||||||
threshold size to switch to file_stream()
|
threshold size to switch to file_stream()
|
||||||
|
:param name: user defined name used for url_for
|
||||||
"""
|
"""
|
||||||
# If we're not trying to match a file directly,
|
# If we're not trying to match a file directly,
|
||||||
# serve from the folder
|
# serve from the folder
|
||||||
|
@ -117,4 +118,8 @@ def register(app, uri, file_or_directory, pattern,
|
||||||
path=file_or_directory,
|
path=file_or_directory,
|
||||||
relative_url=file_uri)
|
relative_url=file_uri)
|
||||||
|
|
||||||
app.route(uri, methods=['GET', 'HEAD'])(_handler)
|
# special prefix for static files
|
||||||
|
if not name.startswith('_static_'):
|
||||||
|
name = '_static_{}'.format(name)
|
||||||
|
|
||||||
|
app.route(uri, methods=['GET', 'HEAD'], name=name)(_handler)
|
||||||
|
|
1
tests/static/bp/decode me.txt
Normal file
1
tests/static/bp/decode me.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I am just a regular static file that needs to have its uri decoded
|
BIN
tests/static/bp/python.png
Normal file
BIN
tests/static/bp/python.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
1
tests/static/bp/test.file
Normal file
1
tests/static/bp/test.file
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I am just a regular static file
|
|
@ -17,6 +17,9 @@ URL_FOR_VALUE2 = '/myurl?arg1=v1&arg1=v2#anchor'
|
||||||
URL_FOR_ARGS3 = dict(arg1='v1', _anchor='anchor', _scheme='http',
|
URL_FOR_ARGS3 = dict(arg1='v1', _anchor='anchor', _scheme='http',
|
||||||
_server='localhost:{}'.format(test_port), _external=True)
|
_server='localhost:{}'.format(test_port), _external=True)
|
||||||
URL_FOR_VALUE3 = 'http://localhost:{}/myurl?arg1=v1#anchor'.format(test_port)
|
URL_FOR_VALUE3 = 'http://localhost:{}/myurl?arg1=v1#anchor'.format(test_port)
|
||||||
|
URL_FOR_ARGS4 = dict(arg1='v1', _anchor='anchor', _external=True,
|
||||||
|
_server='http://localhost:{}'.format(test_port),)
|
||||||
|
URL_FOR_VALUE4 = 'http://localhost:{}/myurl?arg1=v1#anchor'.format(test_port)
|
||||||
|
|
||||||
|
|
||||||
def _generate_handlers_from_names(app, l):
|
def _generate_handlers_from_names(app, l):
|
||||||
|
@ -49,7 +52,8 @@ def test_simple_url_for_getting(simple_app):
|
||||||
@pytest.mark.parametrize('args,url',
|
@pytest.mark.parametrize('args,url',
|
||||||
[(URL_FOR_ARGS1, URL_FOR_VALUE1),
|
[(URL_FOR_ARGS1, URL_FOR_VALUE1),
|
||||||
(URL_FOR_ARGS2, URL_FOR_VALUE2),
|
(URL_FOR_ARGS2, URL_FOR_VALUE2),
|
||||||
(URL_FOR_ARGS3, URL_FOR_VALUE3)])
|
(URL_FOR_ARGS3, URL_FOR_VALUE3),
|
||||||
|
(URL_FOR_ARGS4, URL_FOR_VALUE4)])
|
||||||
def test_simple_url_for_getting_with_more_params(args, url):
|
def test_simple_url_for_getting_with_more_params(args, url):
|
||||||
app = Sanic('more_url_build')
|
app = Sanic('more_url_build')
|
||||||
|
|
||||||
|
|
446
tests/test_url_for_static.py
Normal file
446
tests/test_url_for_static.py
Normal file
|
@ -0,0 +1,446 @@
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from sanic import Sanic
|
||||||
|
from sanic.blueprints import Blueprint
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module')
|
||||||
|
def static_file_directory():
|
||||||
|
"""The static directory to serve"""
|
||||||
|
current_file = inspect.getfile(inspect.currentframe())
|
||||||
|
current_directory = os.path.dirname(os.path.abspath(current_file))
|
||||||
|
static_directory = os.path.join(current_directory, 'static')
|
||||||
|
return static_directory
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_path(static_file_directory, file_name):
|
||||||
|
return os.path.join(static_file_directory, file_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_content(static_file_directory, file_name):
|
||||||
|
"""The content of the static file to check"""
|
||||||
|
with open(get_file_path(static_file_directory, file_name), 'rb') as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt', 'python.png'])
|
||||||
|
def test_static_file(static_file_directory, file_name):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name))
|
||||||
|
app.static(
|
||||||
|
'/testing2.file', get_file_path(static_file_directory, file_name),
|
||||||
|
name='testing_file')
|
||||||
|
|
||||||
|
uri = app.url_for('static')
|
||||||
|
uri2 = app.url_for('static', filename='any')
|
||||||
|
uri3 = app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == uri2
|
||||||
|
assert uri2 == uri3
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name))
|
||||||
|
bp.static('/testing2.file',
|
||||||
|
get_file_path(static_file_directory, file_name),
|
||||||
|
name='testing_file')
|
||||||
|
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
uri2 = app.url_for('static', name='test_bp_static.static', filename='any')
|
||||||
|
uri3 = app.url_for('test_bp_static.static')
|
||||||
|
uri4 = app.url_for('test_bp_static.static', name='any')
|
||||||
|
uri5 = app.url_for('test_bp_static.static', filename='any')
|
||||||
|
uri6 = app.url_for('test_bp_static.static', name='any', filename='any')
|
||||||
|
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == uri2
|
||||||
|
assert uri2 == uri3
|
||||||
|
assert uri3 == uri4
|
||||||
|
assert uri4 == uri5
|
||||||
|
assert uri5 == uri6
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
# test for other parameters
|
||||||
|
uri = app.url_for('static', _external=True, _server='http://localhost')
|
||||||
|
assert uri == 'http://localhost/testing.file'
|
||||||
|
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static',
|
||||||
|
_external=True, _server='http://localhost')
|
||||||
|
assert uri == 'http://localhost/bp/testing.file'
|
||||||
|
|
||||||
|
# test for defined name
|
||||||
|
uri = app.url_for('static', name='testing_file')
|
||||||
|
assert uri == '/testing2.file'
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
uri = app.url_for('static', name='test_bp_static.testing_file')
|
||||||
|
assert uri == '/bp/testing2.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.testing_file',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
@pytest.mark.parametrize('base_uri', ['/static', '', '/dir'])
|
||||||
|
def test_static_directory(file_name, base_uri, static_file_directory):
|
||||||
|
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(base_uri, static_file_directory)
|
||||||
|
base_uri2 = base_uri + '/2'
|
||||||
|
app.static(base_uri2, static_file_directory, name='uploads')
|
||||||
|
|
||||||
|
uri = app.url_for('static', name='static', filename=file_name)
|
||||||
|
assert uri == '{}/{}'.format(base_uri, file_name)
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
uri2 = app.url_for('static', name='static', filename='/' + file_name)
|
||||||
|
uri3 = app.url_for('static', filename=file_name)
|
||||||
|
uri4 = app.url_for('static', filename='/' + file_name)
|
||||||
|
uri5 = app.url_for('static', name='uploads', filename=file_name)
|
||||||
|
uri6 = app.url_for('static', name='uploads', filename='/' + file_name)
|
||||||
|
|
||||||
|
assert uri == uri2
|
||||||
|
assert uri2 == uri3
|
||||||
|
assert uri3 == uri4
|
||||||
|
|
||||||
|
assert uri5 == '{}/{}'.format(base_uri2, file_name)
|
||||||
|
assert uri5 == uri6
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
|
||||||
|
bp.static(base_uri, static_file_directory)
|
||||||
|
bp.static(base_uri2, static_file_directory, name='uploads')
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename=file_name)
|
||||||
|
uri2 = app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='/' + file_name)
|
||||||
|
|
||||||
|
uri4 = app.url_for('static', name='test_bp_static.uploads',
|
||||||
|
filename=file_name)
|
||||||
|
uri5 = app.url_for('static', name='test_bp_static.uploads',
|
||||||
|
filename='/' + file_name)
|
||||||
|
|
||||||
|
assert uri == '/bp{}/{}'.format(base_uri, file_name)
|
||||||
|
assert uri == uri2
|
||||||
|
|
||||||
|
assert uri4 == '/bp{}/{}'.format(base_uri2, file_name)
|
||||||
|
assert uri4 == uri5
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_head_request(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.head(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Accept-Ranges' in response.headers
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(
|
||||||
|
get_file_content(static_file_directory, file_name))
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.head(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Accept-Ranges' in response.headers
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(
|
||||||
|
get_file_content(static_file_directory, file_name))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_content_range_correct(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Range': 'bytes=12-19'
|
||||||
|
}
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[12:19]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[12:19]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_content_range_front(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Range': 'bytes=12-'
|
||||||
|
}
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[12:]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[12:]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_content_range_back(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Range': 'bytes=-12'
|
||||||
|
}
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[-12:]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
static_content = bytes(get_file_content(
|
||||||
|
static_file_directory, file_name))[-12:]
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_content_range_empty(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' not in response.headers
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||||
|
assert response.body == bytes(
|
||||||
|
get_file_content(static_file_directory, file_name))
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri)
|
||||||
|
assert response.status == 200
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' not in response.headers
|
||||||
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||||
|
assert response.body == bytes(
|
||||||
|
get_file_content(static_file_directory, file_name))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
|
def test_static_content_range_error(file_name, static_file_directory):
|
||||||
|
app = Sanic('test_static')
|
||||||
|
app.static(
|
||||||
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
|
||||||
|
bp = Blueprint('test_bp_static', url_prefix='/bp')
|
||||||
|
bp.static('/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
use_content_range=True)
|
||||||
|
app.blueprint(bp)
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'Range': 'bytes=1-0'
|
||||||
|
}
|
||||||
|
uri = app.url_for('static')
|
||||||
|
assert uri == '/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='static')
|
||||||
|
assert uri == app.url_for('static', name='static', filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 416
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
assert response.headers['Content-Range'] == "bytes */%s" % (
|
||||||
|
len(get_file_content(static_file_directory, file_name)),)
|
||||||
|
|
||||||
|
# blueprint
|
||||||
|
uri = app.url_for('static', name='test_bp_static.static')
|
||||||
|
assert uri == '/bp/testing.file'
|
||||||
|
assert uri == app.url_for('static', name='test_bp_static.static',
|
||||||
|
filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', filename='any')
|
||||||
|
assert uri == app.url_for('test_bp_static.static', name='any',
|
||||||
|
filename='any')
|
||||||
|
|
||||||
|
request, response = app.test_client.get(uri, headers=headers)
|
||||||
|
assert response.status == 416
|
||||||
|
assert 'Content-Length' in response.headers
|
||||||
|
assert 'Content-Range' in response.headers
|
||||||
|
assert response.headers['Content-Range'] == "bytes */%s" % (
|
||||||
|
len(get_file_content(static_file_directory, file_name)),)
|
Loading…
Reference in New Issue
Block a user