-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add append_version feature into StaticResource url resolver #2158
Changes from 8 commits
127188e
fabd128
e23feff
b510c1f
56817fa
e204474
cdd2257
fc743bf
b076eab
d229c53
e218008
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
import abc | ||
import asyncio | ||
import base64 | ||
import collections | ||
import hashlib | ||
import inspect | ||
import keyword | ||
import os | ||
|
@@ -422,11 +424,13 @@ def add_prefix(self, prefix): | |
|
||
|
||
class StaticResource(PrefixResource): | ||
VERSION_KEY = 'v' | ||
|
||
def __init__(self, prefix, directory, *, name=None, | ||
expect_handler=None, chunk_size=256*1024, | ||
expect_handler=None, chunk_size=256 * 1024, | ||
response_factory=StreamResponse, | ||
show_index=False, follow_symlinks=False): | ||
show_index=False, follow_symlinks=False, | ||
append_version=False): | ||
super().__init__(prefix, name=name) | ||
try: | ||
directory = Path(directory) | ||
|
@@ -443,24 +447,57 @@ def __init__(self, prefix, directory, *, name=None, | |
self._chunk_size = chunk_size | ||
self._follow_symlinks = follow_symlinks | ||
self._expect_handler = expect_handler | ||
self._append_version = append_version | ||
|
||
self._routes = {'GET': ResourceRoute('GET', self._handle, self, | ||
expect_handler=expect_handler), | ||
|
||
'HEAD': ResourceRoute('HEAD', self._handle, self, | ||
expect_handler=expect_handler)} | ||
|
||
def url(self, *, filename, query=None): | ||
return str(self.url_for(filename=filename).with_query(query)) | ||
|
||
def url_for(self, *, filename): | ||
def url(self, *, filename, append_version=None, query=None): | ||
# is there with_query need to be used? | ||
# with_query remove previous query options | ||
url = self.url_for(filename=filename, append_version=append_version) | ||
if query is not None: | ||
return str(url.update_query(query)) | ||
return str(url) | ||
|
||
def url_for(self, *, filename, append_version=None): | ||
if append_version is None: | ||
append_version = self._append_version | ||
if isinstance(filename, Path): | ||
filename = str(filename) | ||
while filename.startswith('/'): | ||
filename = filename[1:] | ||
filename = '/' + filename | ||
url = self._prefix + URL(filename).raw_path | ||
return URL(url) | ||
url = URL(url) | ||
if append_version is True: | ||
try: | ||
if filename.startswith('/'): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a test if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
filename = filename[1:] | ||
filepath = self._directory.joinpath(filename).resolve() | ||
if not self._follow_symlinks: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
filepath.relative_to(self._directory) | ||
except FileNotFoundError: | ||
# relatively safe | ||
return url | ||
if filepath.is_file(): | ||
# TODO cache file content | ||
# with file watcher for cache invalidation | ||
with open(str(filepath), mode='rb') as f: | ||
file_bytes = f.read() | ||
h = self._get_file_hash(file_bytes) | ||
url = url.with_query({self.VERSION_KEY: h}) | ||
return url | ||
return url | ||
|
||
def _get_file_hash(self, byte_array): | ||
m = hashlib.sha256() # todo sha256 can be configurable param | ||
m.update(byte_array) | ||
b64 = base64.urlsafe_b64encode(m.digest()) | ||
return b64.decode('ascii') | ||
|
||
def get_info(self): | ||
return {'directory': self._directory, | ||
|
@@ -828,8 +865,9 @@ def add_route(self, method, path, handler, | |
expect_handler=expect_handler) | ||
|
||
def add_static(self, prefix, path, *, name=None, expect_handler=None, | ||
chunk_size=256*1024, response_factory=StreamResponse, | ||
show_index=False, follow_symlinks=False): | ||
chunk_size=256 * 1024, response_factory=StreamResponse, | ||
show_index=False, follow_symlinks=False, | ||
append_version=False): | ||
"""Add static files view. | ||
|
||
prefix - url prefix | ||
|
@@ -845,7 +883,8 @@ def add_static(self, prefix, path, *, name=None, expect_handler=None, | |
chunk_size=chunk_size, | ||
response_factory=response_factory, | ||
show_index=show_index, | ||
follow_symlinks=follow_symlinks) | ||
follow_symlinks=follow_symlinks, | ||
append_version=append_version) | ||
self.register_resource(resource) | ||
return resource | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
add `append_version` arg into `StaticResource.url` and `StaticResource.url_for` methods | ||
for getting an url with hash (version) of the file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test for this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done