3 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/b64b57240149/ changeset: b64b57240149 user: nuwan_ag date: 2012-08-23 06:22:13 summary: Modified REST API to support multipart/form-data requests, to enable large file upload. affected #: 2 files diff -r dd8a939cf0a26ea9e3cb969297bbfe7d749e88f7 -r b64b572401493be2b424e7166c67473cf1f298dd lib/galaxy/tools/actions/upload_common.py --- a/lib/galaxy/tools/actions/upload_common.py +++ b/lib/galaxy/tools/actions/upload_common.py @@ -28,7 +28,7 @@ local_filename = local_filename ) elif type( f ) == dict and 'filename' and 'local_filename' not in f: raise Exception( 'Uploaded file was encoded in a way not understood by Galaxy.' ) - if upload_dataset['url_paste'].strip() != '': + if upload_dataset['url_paste'] and upload_dataset['url_paste'].strip() != '': upload_dataset['url_paste'], is_multi_byte = datatypes.sniff.stream_to_file( StringIO.StringIO( upload_dataset['url_paste'] ), prefix="strio_url_paste_" ) else: upload_dataset['url_paste'] = None diff -r dd8a939cf0a26ea9e3cb969297bbfe7d749e88f7 -r b64b572401493be2b424e7166c67473cf1f298dd lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -5,6 +5,7 @@ import pkg_resources import os, sys, time, socket, random, string +import inspect pkg_resources.require( "Cheetah" ) from Cheetah.Template import Template import base @@ -125,9 +126,25 @@ return error trans.set_user( provided_key.user ) if trans.request.body: - try: - payload = util.recursively_stringify_dictionary_keys( simplejson.loads( trans.request.body ) ) - kwargs['payload'] = payload + def extract_payload_from_request(trans, func, kwargs): + content_type = trans.request.headers['content-type'] + if content_type.startswith('multipart/form-data'): + # If the content type is a standard type such as multipart/form-data, the wsgi framework parses the request body + # and loads all field values into kwargs. However, kwargs also contains formal method parameters etc. which + # are not a part of the request body. This is a problem because it's not possible to differentiate between values + # which are a part of the request body, and therefore should be a part of the payload, and values which should not be + # in the payload. Therefore, the decorated method's formal arguments are discovered through reflection and removed from + # the payload dictionary. This helps to prevent duplicate argument conflicts in downstream methods. + payload = kwargs.copy() + named_args, _, _, _ = inspect.getargspec(func) + for arg in named_args: + payload.pop(arg, None) + else: + # When it's a non standard request body (e.g. json), the wsgi framework does not parse the request body. So do so manually. + payload = util.recursively_stringify_dictionary_keys( simplejson.loads( trans.request.body ) ) + return payload + try: + kwargs['payload'] = extract_payload_from_request(trans, func, kwargs) except ValueError: error_status = '400 Bad Request' error_message = 'Your request did not appear to be valid JSON, please consult the API documentation' https://bitbucket.org/galaxy/galaxy-central/changeset/5747b665127a/ changeset: 5747b665127a user: nuwan_ag date: 2012-08-23 07:09:20 summary: Also added support for x-www-form-urlencoded REST API requests, for consistencies sake. This way, API clients can post as either JSON, multi-part form data, or standard url form encoding. affected #: 1 file diff -r b64b572401493be2b424e7166c67473cf1f298dd -r 5747b665127a5e4f82e102783048358fca68083b lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -128,7 +128,7 @@ if trans.request.body: def extract_payload_from_request(trans, func, kwargs): content_type = trans.request.headers['content-type'] - if content_type.startswith('multipart/form-data'): + if content_type.startswith('application/x-www-form-urlencoded') or content_type.startswith('multipart/form-data'): # If the content type is a standard type such as multipart/form-data, the wsgi framework parses the request body # and loads all field values into kwargs. However, kwargs also contains formal method parameters etc. which # are not a part of the request body. This is a problem because it's not possible to differentiate between values @@ -140,7 +140,9 @@ for arg in named_args: payload.pop(arg, None) else: - # When it's a non standard request body (e.g. json), the wsgi framework does not parse the request body. So do so manually. + # Assume application/json content type and parse request body manually, since wsgi won't do it. However, the order of this check + # should ideally be in reverse, with the if clause being a check for application/json and the else clause assuming a standard encoding + # such as multipart/form-data. Leaving it as is for backward compatibility, just in case. payload = util.recursively_stringify_dictionary_keys( simplejson.loads( trans.request.body ) ) return payload try: https://bitbucket.org/galaxy/galaxy-central/changeset/6d3023815cd7/ changeset: 6d3023815cd7 user: dannon date: 2012-09-10 18:33:01 summary: Merged in nuwan_ag/galaxy-central (pull request #63) affected #: 2 files diff -r e0975c9b9bd25d44cfcacc202470bb8037da6d6f -r 6d3023815cd77ec3045bf81ff15af884b828c38d lib/galaxy/tools/actions/upload_common.py --- a/lib/galaxy/tools/actions/upload_common.py +++ b/lib/galaxy/tools/actions/upload_common.py @@ -28,7 +28,7 @@ local_filename = local_filename ) elif type( f ) == dict and 'filename' and 'local_filename' not in f: raise Exception( 'Uploaded file was encoded in a way not understood by Galaxy.' ) - if upload_dataset['url_paste'].strip() != '': + if upload_dataset['url_paste'] and upload_dataset['url_paste'].strip() != '': upload_dataset['url_paste'], is_multi_byte = datatypes.sniff.stream_to_file( StringIO.StringIO( upload_dataset['url_paste'] ), prefix="strio_url_paste_" ) else: upload_dataset['url_paste'] = None diff -r e0975c9b9bd25d44cfcacc202470bb8037da6d6f -r 6d3023815cd77ec3045bf81ff15af884b828c38d lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -5,6 +5,7 @@ import pkg_resources import os, sys, time, socket, random, string +import inspect pkg_resources.require( "Cheetah" ) from Cheetah.Template import Template import base @@ -125,9 +126,27 @@ return error trans.set_user( provided_key.user ) if trans.request.body: - try: - payload = util.recursively_stringify_dictionary_keys( simplejson.loads( trans.request.body ) ) - kwargs['payload'] = payload + def extract_payload_from_request(trans, func, kwargs): + content_type = trans.request.headers['content-type'] + if content_type.startswith('application/x-www-form-urlencoded') or content_type.startswith('multipart/form-data'): + # If the content type is a standard type such as multipart/form-data, the wsgi framework parses the request body + # and loads all field values into kwargs. However, kwargs also contains formal method parameters etc. which + # are not a part of the request body. This is a problem because it's not possible to differentiate between values + # which are a part of the request body, and therefore should be a part of the payload, and values which should not be + # in the payload. Therefore, the decorated method's formal arguments are discovered through reflection and removed from + # the payload dictionary. This helps to prevent duplicate argument conflicts in downstream methods. + payload = kwargs.copy() + named_args, _, _, _ = inspect.getargspec(func) + for arg in named_args: + payload.pop(arg, None) + else: + # Assume application/json content type and parse request body manually, since wsgi won't do it. However, the order of this check + # should ideally be in reverse, with the if clause being a check for application/json and the else clause assuming a standard encoding + # such as multipart/form-data. Leaving it as is for backward compatibility, just in case. + payload = util.recursively_stringify_dictionary_keys( simplejson.loads( trans.request.body ) ) + return payload + try: + kwargs['payload'] = extract_payload_from_request(trans, func, kwargs) except ValueError: error_status = '400 Bad Request' error_message = 'Your request did not appear to be valid JSON, please consult the API documentation' Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.