diff --git a/lib/galaxy/webapps/galaxy/api/uploads.py b/lib/galaxy/webapps/galaxy/api/uploads.py index dbb49ddeb09..ad3e7eebd60 100644 --- a/lib/galaxy/webapps/galaxy/api/uploads.py +++ b/lib/galaxy/webapps/galaxy/api/uploads.py @@ -23,40 +23,45 @@ class UploadsAPIController(BaseGalaxyAPIController): READ_CHUNK_SIZE = 2 ** 16 @expose_api_raw_anonymous - def tus(self, trans, **kwargs): + def tus(self, trans, payload, session_id=None, **kwargs): """ PATCH /api/upload/resumable_upload/{filename} """ - upload_path = kwargs.get('payload') - with open(f"{upload_path}.info") as info: - metadata = json.load(info) - trans.response.headers['upload-offset'] = metadata['upload_length'] - if trans.user or trans.session: - # This is a hack that works nicely with tusc - # e.g tusc client /api/upload/resumable_upload -r -H 'x-api-key: ' - # I believe we can put arbitrary values in the metadata for history_id, dbkey, file_type, etc - upload_metadata = metadata['upload_metadata'] - filename = upload_metadata.get('filename', 'Uploaded dataset') - dbkey = upload_metadata.get('dbkey', '?') - history_id = upload_metadata.get('history_id') - ext = 'auto' - for key in ['ext', 'file_type', 'extension']: - if key in upload_metadata: - ext = upload_metadata[key] - break - _create = trans.webapp.api_controllers['tools']._create - payload = { - "file_count": 1, - "dbkey": dbkey, - "file_type": "auto", - "files_0|type": "upload_dataset", - "files_0|NAME": filename, - "files_0|to_posix_lines": "Yes", - "files_0|dbkey": dbkey, - "files_0|file_type": ext, - "files_0|file_data": {"session_id": kwargs['tmpfile'], "name": filename}} - payload = {'tool_id': 'upload1', 'inputs': payload, 'history_id': history_id} - _create(trans, payload) + if isinstance(payload, str): + # WSGI middleware + with open(f"{payload}.info") as info: + payload = json.load(info) + metadata = payload['upload_metadata'] + size = payload['upload_length'] + else: + # tusd server hook + metadata = payload['Upload']['MetaData'] + session_id = payload['Upload']['ID'] + size = payload['Upload']['Size'] + trans.response.headers['upload-offset'] = size + filename = metadata.get('filename', 'Uploaded dataset') + dbkey = metadata.get('dbkey', '?') + history_id = metadata.get('history_id') + if not history_id and not trans.session: + raise exceptions.RequestParameterMissingException("history_id or galaxy session required") + ext = 'auto' + for key in ['ext', 'file_type', 'extension']: + if key in metadata: + ext = metadata[key] + break + _create = trans.webapp.api_controllers['tools']._create + inputs = { + "file_count": 1, + "dbkey": dbkey, + "file_type": "auto", + "files_0|type": "upload_dataset", + "files_0|NAME": filename, + "files_0|to_posix_lines": "Yes", + "files_0|dbkey": dbkey, + "files_0|file_type": ext, + "files_0|file_data": {"session_id": session_id, "name": filename}} + tool_payload = {'tool_id': 'upload1', 'inputs': inputs, 'history_id': history_id} + _create(trans, tool_payload) trans.response.status = 204 @legacy_expose_api_anonymous diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index aa7044a4e37..8fa1c05cca2 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -385,7 +385,8 @@ def populate_api_routes(webapp, app): webapp.mapper.resource('form', 'forms', path_prefix='/api') webapp.mapper.resource('role', 'roles', path_prefix='/api') webapp.mapper.resource('upload', 'uploads', path_prefix='/api') - webapp.mapper.connect('/api/upload/resumable_upload/{tmpfile}', controller="uploads", action="tus", conditions=dict(method=["PATCH"])) + webapp.mapper.connect('/api/upload/resumable_upload/{session_id}', controller="uploads", action="tus", conditions=dict(method=["PATCH"])) + webapp.mapper.connect('/api/upload/_resumable_upload', controller="uploads", action="tus", conditions=dict(method=["POST"])) webapp.mapper.connect('/api/ftp_files', controller='remote_files') webapp.mapper.connect('/api/remote_files', action='index', controller='remote_files', conditions=dict(method=["GET"])) webapp.mapper.connect('/api/remote_files/plugins', action='plugins', controller='remote_files', conditions=dict(method=["GET"])) diff --git a/scripts/resumable_upload.py b/scripts/resumable_upload.py index 8b91b248ff4..2a29020564f 100644 --- a/scripts/resumable_upload.py +++ b/scripts/resumable_upload.py @@ -3,13 +3,12 @@ import os import aiotus import asyncclick as click -creation_url = "http://localhost:8000/" UPLOAD_ENDPOINT = '/api/upload/resumable_upload' @click.command() @click.option("--url", default='http://localhost:8080', help="URL of Galaxy instance") -@click.option("--api_key", envvar="GALAXY_API_KEY", help="API key for Galaxy instance") +@click.option("--api_key", envvar="GALAXY_API_KEY", required=True, help="API key for Galaxy instance") @click.option('--history_id', type=str, required=True, help="Target History ID") @click.option('--file_type', default="auto", type=str, help="Galaxy file type to use") @click.option('--dbkey', default="?", type=str, help="Genome Build for dataset")