Skip to content

Commit

Permalink
feat: support request header X-Guploader-No-308 (googleapis#403)
Browse files Browse the repository at this point in the history
Fixes googleapis#402

This adds support for X-GUploader-No-308: yes - if included in resumable upload request headers, instead of returning 308: resume incomplete, return 200 to satisfy the client and add a X-HTTP-Status-Code-Override: 308 response header
  • Loading branch information
cojenco committed Sep 12, 2022
1 parent c9b92d9 commit 30d1fed
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 2 deletions.
6 changes: 5 additions & 1 deletion gcs/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,13 @@ def init_write_object_grpc(cls, db, request_iterator, context):
upload.metadata.metadata["x_emulator_no_md5"] = "true"
return upload, is_resumable

def resumable_status_rest(self):
def resumable_status_rest(self, override_308=False):
response = flask.make_response()
if len(self.media) > 1 and not self.complete:
response.headers["Range"] = "bytes=0-%d" % (len(self.media) - 1)
response.status_code = 308

if override_308:
response.headers["X-Http-Status-Code-Override"] = "308"
response.status_code = 200
return response
6 changes: 5 additions & 1 deletion testbench/rest_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,11 @@ def resumable_upload_chunk(bucket_name):
blob.rest_metadata(), projection, fields
)
else:
return upload.resumable_status_rest()
# If request header "X-GUploader-No-308: yes" is included, instead of returning 308
# Resume Incomplete, return 200 with a response header X-HTTP-Status-Code-Override: 308
# See more at https://g3doc.corp.google.com/cloud/storage/g3doc/user/scotty/faq.md?cl=head
override_308 = request.headers.get("X-Guploader-No-308") == "yes"
return upload.resumable_status_rest(override_308=override_308)


@upload.route("/b/<bucket_name>/o", methods=["DELETE"])
Expand Down
10 changes: 10 additions & 0 deletions tests/test_testbench_object_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,16 @@ def test_upload_resumable_upload_crud(self):
self.assertEqual(response.status_code, 308)
self.assertIn("range", response.headers)

# Test 200 overrides 308 with request header X-Guploader-No-308
response = self.client.put(
"/upload/storage/v1/b/bucket-name/o",
query_string={"upload_id": upload_id},
headers={
"X-Guploader-No-308": "yes",
},
)
self.assertEqual(response.status_code, 200)

response = self.client.delete(
"/upload/storage/v1/b/bucket-name/o",
query_string={"upload_id": upload_id},
Expand Down
5 changes: 5 additions & 0 deletions tests/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ def test_resumable_rest(self):
self.assertEqual(status.status_code, 308)
self.assertIn("Range", status.headers)
self.assertEqual("bytes=0-42", status.headers.get("Range", None))
# Simulate a chunk upload that requests 200 status code instead of 308
upload.media = "How vexingly quick daft zebras jump"
status = upload.resumable_status_rest(override_308=True)
self.assertEqual(status.status_code, 200)
self.assertIn("X-Http-Status-Code-Override", status.headers)

def test_init_object_write_grpc_non_resumable(self):
line = b"The quick brown fox jumps over the lazy dog\n"
Expand Down

0 comments on commit 30d1fed

Please sign in to comment.