Skip to content

Commit af6035f

Browse files
authored
fix: don't set content-range on empty uploads (#1070)
1 parent 30eff9d commit af6035f

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

googleapiclient/http.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,13 +1026,17 @@ def next_chunk(self, http=None, num_retries=0):
10261026
chunk_end = self.resumable_progress + len(data) - 1
10271027

10281028
headers = {
1029-
"Content-Range": "bytes %d-%d/%s"
1030-
% (self.resumable_progress, chunk_end, size),
10311029
# Must set the content-length header here because httplib can't
10321030
# calculate the size when working with _StreamSlice.
10331031
"Content-Length": str(chunk_end - self.resumable_progress + 1),
10341032
}
10351033

1034+
# An empty file results in chunk_end = -1 and size = 0
1035+
# sending "bytes 0--1/0" results in an invalid request
1036+
# Only add header "Content-Range" if chunk_end != -1
1037+
if chunk_end != -1:
1038+
headers["Content-Range"] = "bytes %d-%d/%s" % (self.resumable_progress, chunk_end, size)
1039+
10361040
for retry_num in range(num_retries + 1):
10371041
if retry_num > 0:
10381042
self._sleep(self._rand() * 2 ** retry_num)

tests/test_http.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,33 @@ def test_media_io_base_next_chunk_no_retry_403_not_configured(self):
443443
request._sleep.assert_not_called()
444444

445445

446+
def test_media_io_base_empty_file(self):
447+
fd = BytesIO()
448+
upload = MediaIoBaseUpload(
449+
fd=fd, mimetype="image/png", chunksize=500, resumable=True
450+
)
451+
452+
http = HttpMockSequence(
453+
[
454+
({"status": "200", "location": "https://www.googleapis.com/someapi/v1/upload?foo=bar"}, "{}"),
455+
({"status": "200", "location": "https://www.googleapis.com/someapi/v1/upload?foo=bar"}, "{}")
456+
]
457+
)
458+
459+
model = JsonModel()
460+
uri = u"https://www.googleapis.com/someapi/v1/upload/?foo=bar"
461+
method = u"POST"
462+
request = HttpRequest(
463+
http, model.response, uri, method=method, headers={}, resumable=upload
464+
)
465+
466+
request.execute()
467+
468+
# Check that "Content-Range" header is not set in the PUT request
469+
self.assertTrue("Content-Range" not in http.request_sequence[-1][-1])
470+
self.assertEqual("0", http.request_sequence[-1][-1]["Content-Length"])
471+
472+
446473
class TestMediaIoBaseDownload(unittest.TestCase):
447474
def setUp(self):
448475
http = HttpMock(datafile("zoo.json"), {"status": "200"})

0 commit comments

Comments
 (0)