Move Create_Formpost to Behaviors

* Moved method create_formpost from the
  client to behaviors. As it didn't
  directly interface with the API, it
  belongs in the behaviors.
* Rearranged the imports of behaviors
  for alphabetical order.
* Modified the docstring of create_formpost
  to be a little more descriptive.
* Changed an if variable != '' to
  if variable

Change-Id: Id7b63bfeb60b81dd7a080459595464546bfdcf35
This commit is contained in:
josh7810
2015-08-12 11:38:06 -05:00
parent 769d64244b
commit a06e4a3aa5
2 changed files with 150 additions and 145 deletions

View File

@@ -14,20 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import datetime
import uuid
import json
import gzip
from StringIO import StringIO
import hmac
import json
import uuid
from copy import deepcopy
from time import sleep
from hashlib import md5, sha1
from random import choice
from hashlib import md5
from StringIO import StringIO
from time import sleep, time
from cafe.common.unicode import UNICODE_BLOCKS, BLOCK_NAMES
from cafe.engine.behaviors import BaseBehavior, behavior
from cloudcafe.objectstorage.objectstorage_api.config \
import ObjectStorageAPIConfig
from cloudcafe.common.tools.md5hash import get_md5_hash
from cloudcafe.objectstorage.objectstorage_api.client \
import ObjectStorageAPIClient
from cafe.common.unicode import UNICODE_BLOCKS, BLOCK_NAMES
from cloudcafe.objectstorage.objectstorage_api.config \
import ObjectStorageAPIConfig
class ObjectStorageAPIBehaviorException(Exception):
@@ -780,3 +784,141 @@ class ObjectStorageAPI_Behaviors(BaseBehavior):
if not key_two_response.ok:
raise Exception('Could not set TempURL key two.')
def create_formpost(self, container, files, object_prefix='',
redirect='http://example.com/formpost',
max_file_size=104857600, max_file_count=10,
expires=None, key='', signature="",
x_delete_at=None, x_delete_after=None):
"""
Creates a multipart/form-data body (RFC-2388) that can be used for
POSTs to Swift.
@param container: Name of the container to post objects to.
@type container: string
@param files: Files to post in the form. The dictionaries representing
a file should be formatted as follows:
{
'name': '<form name>',
'filename': '<filename>',
'content_type': '<content_type>',
'data': '<filedata>'
}
Where only name is required, defaults to other values
will be as follows:
filename - the value stored in name.
content_type - 'text/plain'
data - the md5 hash of the value stored in name.
@type files: list of dictionaries
@param object_prefix: prefix to be used in the name of the objects
created.
@type object_prefix: string
@param redirect: URL to be returned as the 'location' header in the
HTTP response.
@type redirect: string
@param max_file_size: The maximum file size in bytes which can be
uploaded with the form.
@type max_file_size: int
@param max_file_count: The maximum number of files allowed to be
uploaded with the form.
@type max_file_count: int
@param expires: The unix time relating to when the form expires
and will no longer allow uploads to the container.
@type expires: int
@param key: The account's X-Tempurl-Key used in creating the signatre
which authorizes the form to be POSTed.
@type key: string
@param signature: The HMAC-SHA1 signature of the form.
@type signature: string
@param x_delete_at: The unix time relating to when the object will
be deleted from the container.
@type x_delete_at: int
@param x_delete_after: The amount of time, in seconds, after which
the object will be deleted from the container.
@type x_delete_after: int
@return: Data to be POSTed in the following format:
{
'target_url': '<url to POST to>',
'headers': '<headers to be added to the request>,
'body': '<body to be posted to the target url>'
}
@rtype: dictionary
"""
base_url, account_hash = self.client.storage_url.split('/v1/')
path = '/v1/{0}/{1}'.format(account_hash, container)
if object_prefix:
path = '{0}/{1}'.format(path, object_prefix)
if not expires:
expires = int(time() + 600)
url = ''.join([base_url, path])
hmac_body = '{0}\n{1}\n{2}\n{3}\n{4}'.format(
path, redirect, max_file_size, max_file_count, expires)
if not signature:
signature = hmac.new(key, hmac_body, sha1).hexdigest()
form = []
if redirect:
form.append({
'headers':
{'Content-Disposition': 'form-data; name="redirect"'},
'data': redirect})
form.append({
'headers': {'Content-Disposition':
'form-data; name="max_file_size"'},
'data': str(max_file_size)})
form.append({
'headers': {'Content-Disposition':
'form-data; name="max_file_count"'},
'data': str(max_file_count)})
form.append({
'headers': {'Content-Disposition': 'form-data; name="expires"'},
'data': str(expires)})
if x_delete_at:
form.append({
'headers': {'Content-Disposition':
'form-data; name="x_delete_at"'},
'data': str(x_delete_at)})
if x_delete_after:
form.append({
'headers': {'Content-Disposition':
'form-data; name="x_delete_after"'},
'data': str(x_delete_after)})
form.append({
'headers': {'Content-Disposition': 'form-data; name="signature"'},
'data': signature})
for data_file in files:
form_name = data_file.get('name')
form_filename = data_file.get('filename', form_name)
form_content_type = data_file.get('content_type', 'text/plain')
form_data = data_file.get('data', get_md5_hash(form_name))
form.append({
'headers': {'Content-Disposition':
'form-data; name="{0}"; filename="{1}"'.format(
form_name, form_filename),
'Content-Type': form_content_type},
'data': form_data})
data = []
boundary = '----WebKitFormBoundary40Q4WaJHO84PBBIa'
for section in form:
data.append('--{0}\r\n'.format(boundary))
for key, value in section['headers'].iteritems():
data.append('{0}: {1}\r\n'.format(key, value))
data.append('\r\n')
data.append(section['data'])
data.append('\r\n')
data.append('\r\n--{0}'.format(boundary))
post_headers = {
'Cache-Control': 'max-age=0',
'Accept': '*/*;q=0.8',
'Content-Type': 'multipart/form-data; boundary={0}'.format(
boundary)}
return {'target_url': url, 'headers': post_headers,
'body': ''.join(data)}

View File

@@ -587,143 +587,6 @@ class ObjectStorageAPIClient(HTTPClient):
return {'target_url': base_url, 'signature': sig, 'expires': expires}
def create_formpost(self, container, files, object_prefix='',
redirect='http://example.com/formpost',
max_file_size=104857600, max_file_count=10,
expires=None, key='', signature="",
x_delete_at=None, x_delete_after=None):
"""
Creates RFC-2388.
@param container: Name of the container to post objects to.
@type container: string
@param files: Files to post in the form. The dictionaries representing
a file should be formatted as follows:
{
'name': '<form name>',
'filename': '<filename>',
'content_type': '<content_type>',
'data': '<filedata>'
}
Where only name is required, defaults to other values
will be as follows:
filename - the value stored in name.
content_type - 'text/plain'
data - the md5 hash of the value stored in name.
@type files: list of dictionaries
@param object_prefix: prefix to be used in the name of the objects
created.
@type object_prefix: string
@param redirect: URL to be returned as the 'location' header in the
HTTP response.
@type redirect: string
@param max_file_size: The maximum file size in bytes which can be
uploaded with the form.
@type max_file_size: int
@param max_file_count: The maximum number of files allowed to be
uploaded with the form.
@type max_file_count: int
@param expires: The unix time relating to when the form expires
and will no longer allow uploads to the container.
@type expires: int
@param key: The account's X-Tempurl-Key used in creating the signatre
which authorizes the form to be POSTed.
@type key: string
@param signature: The HMAC-SHA1 signature of the form.
@type signature: string
@param x_delete_at: The unix time relating to when the object will
be deleted from the container.
@type x_delete_at: int
@param x_delete_after: The amount of time, in seconds, after which
the object will be deleted from the container.
@type x_delete_after: int
@return: Data to be POSTed in the following format:
{
'target_url': '<url to POST to>',
'headers': '<headers to be added to the request>,
'body': '<body to be posted to the target url>'
}
@rtype: dictionary
"""
base_url, path = self.storage_url.split('/v1')
path = '/v1{0}/{1}'.format(path, container)
if object_prefix:
path = '{0}/{1}'.format(path, object_prefix)
if not expires:
expires = int(time() + 600)
url = ''.join([base_url, path])
hmac_body = '{0}\n{1}\n{2}\n{3}\n{4}'.format(
path, redirect, max_file_size, max_file_count, expires)
if not signature:
signature = hmac.new(key, hmac_body, sha1).hexdigest()
form = []
if redirect != '':
form.append({
'headers':
{'Content-Disposition': 'form-data; name="redirect"'},
'data': redirect})
form.append({
'headers': {'Content-Disposition':
'form-data; name="max_file_size"'},
'data': str(max_file_size)})
form.append({
'headers': {'Content-Disposition':
'form-data; name="max_file_count"'},
'data': str(max_file_count)})
form.append({
'headers': {'Content-Disposition': 'form-data; name="expires"'},
'data': str(expires)})
if x_delete_at:
form.append({
'headers': {'Content-Disposition':
'form-data; name="x_delete_at"'},
'data': str(x_delete_at)})
if x_delete_after:
form.append({
'headers': {'Content-Disposition':
'form-data; name="x_delete_after"'},
'data': str(x_delete_after)})
form.append({
'headers': {'Content-Disposition': 'form-data; name="signature"'},
'data': signature})
for data_file in files:
form_name = data_file.get('name')
form_filename = data_file.get('filename', form_name)
form_content_type = data_file.get('content_type', 'text/plain')
form_data = data_file.get('data', get_md5_hash(form_name))
form.append({
'headers': {'Content-Disposition':
'form-data; name="{0}"; filename="{1}"'.format(
form_name, form_filename),
'Content-Type': form_content_type},
'data': form_data})
data = []
boundary = '----WebKitFormBoundary40Q4WaJHO84PBBIa'
for section in form:
data.append('--{0}\r\n'.format(boundary))
for key, value in section['headers'].iteritems():
data.append('{0}: {1}\r\n'.format(key, value))
data.append('\r\n')
data.append(section['data'])
data.append('\r\n')
data.append('\r\n--{0}'.format(boundary))
post_headers = {
'Cache-Control': 'max-age=0',
'Accept': '*/*;q=0.8',
'Content-Type': 'multipart/form-data; boundary={0}'.format(
boundary)}
return {'target_url': url, 'headers': post_headers,
'body': ''.join(data)}
def create_archive(self, object_names, compression_type,
archive_name=BULK_ARCHIVE_NAME):
"""