New media upload scheme that uses only /upload and the new uploadType parameter.
Committed TBR review at http://codereview.appspot.com/5704049/.
This commit is contained in:
@@ -85,7 +85,9 @@ def _write_headers(self):
|
|||||||
|
|
||||||
|
|
||||||
def _add_query_parameter(url, name, value):
|
def _add_query_parameter(url, name, value):
|
||||||
"""Adds a query parameter to a url
|
"""Adds a query parameter to a url.
|
||||||
|
|
||||||
|
Replaces the current value if it already exists in the URL.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
url: string, url to add the query parameter to.
|
url: string, url to add the query parameter to.
|
||||||
@@ -99,8 +101,8 @@ def _add_query_parameter(url, name, value):
|
|||||||
return url
|
return url
|
||||||
else:
|
else:
|
||||||
parsed = list(urlparse.urlparse(url))
|
parsed = list(urlparse.urlparse(url))
|
||||||
q = parse_qsl(parsed[4])
|
q = dict(parse_qsl(parsed[4]))
|
||||||
q.append((name, value))
|
q[name] = value
|
||||||
parsed[4] = urllib.urlencode(q)
|
parsed[4] = urllib.urlencode(q)
|
||||||
return urlparse.urlunparse(parsed)
|
return urlparse.urlunparse(parsed)
|
||||||
|
|
||||||
@@ -333,8 +335,10 @@ def createResource(http, baseUrl, model, requestBuilder,
|
|||||||
maxSize = 0
|
maxSize = 0
|
||||||
if 'mediaUpload' in methodDesc:
|
if 'mediaUpload' in methodDesc:
|
||||||
mediaUpload = methodDesc['mediaUpload']
|
mediaUpload = methodDesc['mediaUpload']
|
||||||
mediaPathUrl = mediaUpload['protocols']['simple']['path']
|
# TODO(jcgregorio) Use URLs from discovery once it is updated.
|
||||||
mediaResumablePathUrl = mediaUpload['protocols']['resumable']['path']
|
parsed = list(urlparse.urlparse(baseUrl))
|
||||||
|
basePath = parsed[2]
|
||||||
|
mediaPathUrl = '/upload' + basePath + pathUrl
|
||||||
accept = mediaUpload['accept']
|
accept = mediaUpload['accept']
|
||||||
maxSize = _media_size_to_long(mediaUpload.get('maxSize', ''))
|
maxSize = _media_size_to_long(mediaUpload.get('maxSize', ''))
|
||||||
|
|
||||||
@@ -491,11 +495,10 @@ def createResource(http, baseUrl, model, requestBuilder,
|
|||||||
raise MediaUploadSizeError("Media larger than: %s" % maxSize)
|
raise MediaUploadSizeError("Media larger than: %s" % maxSize)
|
||||||
|
|
||||||
# Use the media path uri for media uploads
|
# Use the media path uri for media uploads
|
||||||
if media_upload.resumable():
|
expanded_url = uritemplate.expand(mediaPathUrl, params)
|
||||||
expanded_url = uritemplate.expand(mediaResumablePathUrl, params)
|
|
||||||
else:
|
|
||||||
expanded_url = uritemplate.expand(mediaPathUrl, params)
|
|
||||||
url = urlparse.urljoin(self._baseUrl, expanded_url + query)
|
url = urlparse.urljoin(self._baseUrl, expanded_url + query)
|
||||||
|
if media_upload.resumable():
|
||||||
|
url = _add_query_parameter(url, 'uploadType', 'resumable')
|
||||||
|
|
||||||
if media_upload.resumable():
|
if media_upload.resumable():
|
||||||
# This is all we need to do for resumable, if the body exists it gets
|
# This is all we need to do for resumable, if the body exists it gets
|
||||||
@@ -507,6 +510,7 @@ def createResource(http, baseUrl, model, requestBuilder,
|
|||||||
# This is a simple media upload
|
# This is a simple media upload
|
||||||
headers['content-type'] = media_upload.mimetype()
|
headers['content-type'] = media_upload.mimetype()
|
||||||
body = media_upload.getbytes(0, media_upload.size())
|
body = media_upload.getbytes(0, media_upload.size())
|
||||||
|
url = _add_query_parameter(url, 'uploadType', 'media')
|
||||||
else:
|
else:
|
||||||
# This is a multipart/related upload.
|
# This is a multipart/related upload.
|
||||||
msgRoot = MIMEMultipart('related')
|
msgRoot = MIMEMultipart('related')
|
||||||
@@ -530,6 +534,7 @@ def createResource(http, baseUrl, model, requestBuilder,
|
|||||||
multipart_boundary = msgRoot.get_boundary()
|
multipart_boundary = msgRoot.get_boundary()
|
||||||
headers['content-type'] = ('multipart/related; '
|
headers['content-type'] = ('multipart/related; '
|
||||||
'boundary="%s"') % multipart_boundary
|
'boundary="%s"') % multipart_boundary
|
||||||
|
url = _add_query_parameter(url, 'uploadType', 'multipart')
|
||||||
|
|
||||||
logging.info('URL being requested: %s' % url)
|
logging.info('URL being requested: %s' % url)
|
||||||
return self._requestBuilder(self._http,
|
return self._requestBuilder(self._http,
|
||||||
|
|||||||
@@ -312,6 +312,9 @@ class Discovery(unittest.TestCase):
|
|||||||
request = zoo.animals().insert(media_body=datafile('small.png'))
|
request = zoo.animals().insert(media_body=datafile('small.png'))
|
||||||
self.assertEquals('image/png', request.headers['content-type'])
|
self.assertEquals('image/png', request.headers['content-type'])
|
||||||
self.assertEquals('PNG', request.body[1:4])
|
self.assertEquals('PNG', request.body[1:4])
|
||||||
|
self.assertEqual(
|
||||||
|
'https://www.googleapis.com/upload/zoo/animals?uploadType=media&alt=json',
|
||||||
|
request.uri)
|
||||||
|
|
||||||
def test_multipart_media_raise_correct_exceptions(self):
|
def test_multipart_media_raise_correct_exceptions(self):
|
||||||
self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
|
self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
|
||||||
@@ -337,6 +340,9 @@ class Discovery(unittest.TestCase):
|
|||||||
self.assertTrue(request.headers['content-type'].startswith(
|
self.assertTrue(request.headers['content-type'].startswith(
|
||||||
'multipart/related'))
|
'multipart/related'))
|
||||||
self.assertEquals('--==', request.body[0:4])
|
self.assertEquals('--==', request.body[0:4])
|
||||||
|
self.assertEqual(
|
||||||
|
'https://www.googleapis.com/upload/zoo/animals?uploadType=multipart&alt=json',
|
||||||
|
request.uri)
|
||||||
|
|
||||||
def test_media_capable_method_without_media(self):
|
def test_media_capable_method_without_media(self):
|
||||||
self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
|
self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
|
||||||
@@ -452,6 +458,9 @@ class Discovery(unittest.TestCase):
|
|||||||
|
|
||||||
media_upload = MediaFileUpload(datafile('small.png'), resumable=True)
|
media_upload = MediaFileUpload(datafile('small.png'), resumable=True)
|
||||||
request = zoo.animals().insert(media_body=media_upload, body=None)
|
request = zoo.animals().insert(media_body=media_upload, body=None)
|
||||||
|
self.assertEqual(
|
||||||
|
'https://www.googleapis.com/upload/zoo/animals?uploadType=resumable&alt=json',
|
||||||
|
request.uri)
|
||||||
|
|
||||||
http = HttpMockSequence([
|
http = HttpMockSequence([
|
||||||
({'status': '200',
|
({'status': '200',
|
||||||
|
|||||||
Reference in New Issue
Block a user