Repository: fsouza/fake-gcs-server (go)

Issue:
Resuming a resumable upload from GCS C++ client does not work: fake-gcs-server rejects “Content-Range: bytes */*”
When resuming a resumable upload using `gcs::RestoreResumableUploadSession()`, the C++ client sends `Content-Range: bytes */*`:
https://github.com/googleapis/google-cloud-cpp/blob/1178ef9bbb0257e940dc2d9af475802d8bb37038/google/cloud/storage/internal/rest_client.cc#L699

fake-gcs-server rejects this: https://github.com/fsouza/fake-gcs-server/blob/e2d2de125a3c14829c3f063681f37aa7e8095444/fakestorage/upload.go#L594

AFAIK this syntax is valid.

Pull request:
fakestorage/upload: handle the Content-Range used the C++ SDK
I spent some time reading about Content-Range and it does look like this is valid (though it's kinda equivalent to omitting the value?)

Related to #1149.

Patch:
diff --git a/fakestorage/upload.go b/fakestorage/upload.go
index 6e76342..40ae01d 100644
--- a/fakestorage/upload.go
+++ b/fakestorage/upload.go
@@ -545,6 +545,7 @@ func (s *Server) uploadFileContent(r *http.Request) jsonResponse {
 //	bytes 1024-2047/* (second 1024 bytes of a streaming document)
 //	bytes */4096      (The end of 4096 byte streaming document)
 //	bytes 0-*/*       (start and end of a streaming document as sent by nodeJS client lib)
+//	bytes */*         (start and end of a streaming document as sent by the C++ SDK)
 func parseContentRange(r string) (parsed contentRange, err error) {
 	invalidErr := fmt.Errorf("invalid Content-Range: %v", r)
 
@@ -589,10 +590,6 @@ func parseContentRange(r string) (parsed contentRange, err error) {
 	// Process total length
 	if parts[1] == "*" {
 		parsed.Total = -1
-
-		if parsed.Start < 0 {
-			return parsed, invalidErr
-		}
 	} else {
 		parsed.KnownTotal = true
 		parsed.Total, err = strconv.Atoi(parts[1])


Test patch:
diff --git a/fakestorage/upload_test.go b/fakestorage/upload_test.go
index 1d27e4d..2efbae3 100644
--- a/fakestorage/upload_test.go
+++ b/fakestorage/upload_test.go
@@ -747,6 +747,10 @@ func TestParseContentRange(t *testing.T) {
 			"bytes 0-1024/*", // A streaming request, unknown total
 			contentRange{KnownRange: true, Start: 0, End: 1024, Total: -1},
 		},
+		{
+			"bytes */*", // Start and end of a streaming request as sent by the C++ SDK
+			contentRange{KnownRange: false, KnownTotal: false, Start: -1, End: -1, Total: -1},
+		},
 	}
 
 	for _, test := range goodHeaderTests {
@@ -754,12 +758,12 @@ func TestParseContentRange(t *testing.T) {
 		t.Run(test.header, func(t *testing.T) {
 			t.Parallel()
 			output, err := parseContentRange(test.header)
-			if output != test.output {
-				t.Fatalf("output is different.\nexpected: %+v\n  actual: %+v\n", test.output, output)
-			}
 			if err != nil {
 				t.Fatal(err)
 			}
+			if output != test.output {
+				t.Fatalf("output is different.\nexpected: %+v\n  actual: %+v\n", test.output, output)
+			}
 		})
 	}
 
@@ -770,7 +774,6 @@ func TestParseContentRange(t *testing.T) {
 		"bytes start-20/100",  // Non-integer range start
 		"bytes 20-end/100",    // Non-integer range end
 		"bytes 100-200/total", // Non-integer size
-		"bytes */*",           // Unknown range or size
 	}
 	for _, test := range badHeaderTests {
 		test := test