Skip to content

Commit

Permalink
feature: Allow to provide custom upload resource name
Browse files Browse the repository at this point in the history
As sometimes it is useful to allow tus upload url to be URL reversed via
`request.app[<upload_resource_name>].url_for(...)`
  • Loading branch information
playpauseandstop committed Mar 26, 2020
1 parent 95b5a17 commit b576759
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ChangeLog
- Fix resuming uploads by passing missed ``Upload-Length`` header:
`#5 <https://github.com/pylotcode/aiohttp-tus/pull/5>`_
- Add documentation about `CORS Headers <https://aiohttp-tus.readthedocs.io/en/latest/usage.html#cors-headers>`_
- Allow to provide upload resource name, which can be lately used for URL reversing

1.0.0b2 (2020-03-18)
====================
Expand Down
16 changes: 13 additions & 3 deletions aiohttp_tus/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class Config:
upload_path: Path
upload_url: str

upload_resource_name: Optional[str] = None

allow_overwrite_files: bool = False
on_upload_done: Optional["ResourceCallback"] = None

Expand All @@ -41,11 +43,19 @@ def resolve_upload_path(self, match_info: web.UrlMappingMatchInfo) -> Path:

@property
def resource_tus_resource_name(self) -> str:
return f"tus_resource_{self.upload_url_id}"
return (
f"tus_resource_{self.upload_url_id}"
if self.upload_resource_name is None
else f"{self.upload_resource_name}_resource"
)

@property
def resource_tus_upload_name(self) -> str:
return f"tus_upload_{self.upload_url_id}"
return (
f"tus_upload_{self.upload_url_id}"
if self.upload_resource_name is None
else self.upload_resource_name
)

@property
def upload_url_id(self) -> str:
Expand Down Expand Up @@ -161,7 +171,7 @@ def get_config(request: web.Request) -> Config:
info = route.get_info()

config_key = info.get("formatter") or info["path"]
if route.resource.name.startswith("tus_resource_"):
if config_key.endswith(r"/{resource_uid}"):
config_key = get_upload_url(config_key)

try:
Expand Down
6 changes: 6 additions & 0 deletions aiohttp_tus/tus.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def setup_tus(
*,
upload_path: Path,
upload_url: str = "/uploads",
upload_resource_name: str = None,
allow_overwrite_files: bool = False,
decorator: Decorator = None,
on_upload_done: ResourceCallback = None,
Expand All @@ -35,6 +36,10 @@ def setup_tus(
:param upload_url:
tus.io upload URL. Can be plain as ``/uploads`` or named as
``/users/{username}/uploads``. By default: ``"/uploads"``
:param upload_resource_name:
By default ``aiohttp-tus`` will provide auto name for the upload resource, as
well as for the chunk resource. But sometimes it might be useful to provide
exact name, which can lately be used for URL reversing.
:param allow_overwrite_files:
When enabled allow to overwrite already uploaded files. This may harm
consistency of stored data, cause please use this param with caution. By
Expand Down Expand Up @@ -78,6 +83,7 @@ def decorate(handler: Handler) -> Handler:
config = Config(
upload_path=upload_path,
upload_url=upload_url,
upload_resource_name=upload_resource_name,
allow_overwrite_files=allow_overwrite_files,
on_upload_done=on_upload_done,
json_dumps=json_dumps,
Expand Down
7 changes: 7 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@
API Reference
=============

aiohttp_tus
===========

.. autofunction:: aiohttp_tus.setup_tus

aiohttp_tus.data
================

.. autoclass:: aiohttp_tus.data.Resource
36 changes: 36 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,39 @@ achieve anonymous & authenticated uploads in same time for one
upload_url=r"/users/{username}/uploads",
decorator=upload_user_required,
)
Upload resource name
====================

In most cases there is no need to specify :class:`aiohttp.web.Resource` name for upload
resource, but when it is necessary, it is possible to specify custom
``upload_resource_name`` and lately use it for URL reversing.

Example below illustrates how to achieve it,

In ``app.py``,

.. code-block:: python
setup_tus(
web.Application(),
upload_path=(
Path(__file__).parent.parent / "uploads" / r"{username}"
),
upload_url="/user/{username}/uploads",
upload_resource_name="user_upload",
)
In ``views.py``,

.. code-block:: python
async def user_profile(request: web.Request) -> web.Response:
upload_url = request.app.router["uploads"].url_for(
username=request.match_info["username"]
)
return aiohttp_jinja2.render(
"users/profile.html",
request,
{"upload_url": upload_url},
)
15 changes: 15 additions & 0 deletions tests/test_tus.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def aiohttp_test_client(aiohttp_client):
async def factory(
*,
upload_url: str,
upload_resource_name: str = None,
upload_suffix: str = None,
allow_overwrite_files: bool = False,
on_upload_done: ResourceCallback = None,
Expand All @@ -47,6 +48,7 @@ async def factory(
web.Application(),
upload_path=base_path / upload_suffix if upload_suffix else base_path,
upload_url=upload_url,
upload_resource_name=upload_resource_name,
allow_overwrite_files=allow_overwrite_files,
on_upload_done=on_upload_done,
decorator=decorator,
Expand Down Expand Up @@ -232,3 +234,16 @@ async def test_upload_large_file(aiohttp_test_client, loop):
await loop.run_in_executor(
None, upload, handler, get_upload_url(client, TEST_UPLOAD_URL)
)


async def test_upload_resource_name(aiohttp_test_client, loop):
upload = partial(tus.upload, file_name=TEST_FILE_NAME)

async with aiohttp_test_client(
upload_url=TEST_UPLOAD_URL, upload_resource_name="upload"
) as client:
upload_url = client.app.router["upload"].url_for()
with open(TEST_FILE_PATH, "rb") as handler:
await loop.run_in_executor(
None, upload, handler, get_upload_url(client, upload_url)
)

0 comments on commit b576759

Please sign in to comment.