googleapis / googleapis/gapic-showcase
FR(resumable uploads): Add ability to omit X-Goog-Upload-Status header
- Dominant language
- Go
- Stars
- 183
- Forks
- 55
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 8
Description
As requested in https://github.com/googleapis/gapic-showcase/issues/1682#issuecomment-5637628971, it would be great to have functionality in showcase to omit the `X-Goog-Upload-Status` header.
intermediate load balancers or proxies often return HTTP 429 or 5xx errors without attaching custom Google headers (`X-Goog-Upload-Status: active`). Showcase needs to simulate these proxy-level failures so clients can test their fallback recovery flows (such as querying upload progress after a raw proxy error).
## Current Behavior
Injected transient failures (e.g., `non_fatal_error_on_...`) always append the `X-Goog-Upload-Status: active` header to error responses.
## Desired Behavior
Add a boolean parameter `omit_status_header` to `X-Goog-Test-Scenario-Config`.
https://github.com/googleapis/gapic-showcase/blob/afd7bbb8e0d3e0a26cc4ac92bb281725b1ffbf1f/server/resumableupload/resumableupload.go#L42
When true, error responses use the configured code (like 429, 502, 503, or 504) but suppress the `X-Goog-Upload-Status` header.
The underlying session must remain active so recovery retries and queries can succeed.
## Proposed Fields
`omit_status_header` : (bool, default: false): Suppresses the upload status header on failure when true.
## Test Case
```
func TestProxyErrorWithoutUploadStatusOnFinalize(t *testing.T) {
mgr := resumableupload.NewManager()
handler := mgr.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}))
// 1. Init session with omit_status_header enabled
reqStart := httptest.NewRequest("POST", "http://localhost:7469/upload", strings.NewReader(`{"name":"proxy-test.txt"}`))
reqStart.Header.Set("X-Goog-Upload-Protocol", "resumable")
reqStart.Header.Set("X-Goog-Upload-Command", "start")
reqStart.Header.Set("X-Goog-Test-Scenario", "non_fatal_error_on_finalize")
reqStart.Header.Set("X-Goog-Test-Scenario-Config", `{"error_code":502,"failure_count":1,"omit_status_header":true}`)
recStart := httptest.NewRecorder()
handler.ServeHTTP(recStart, reqStart)
uploadURL := recStart.Header().Get("X-Goog-Upload-URL")
// 2. Upload chunk
reqChunk := httptest.NewRequest("POST", uploadURL, strings.NewReader("sample payload"))
reqChunk.Header.Set("X-Goog-Upload-Command", "upload")
reqChunk.Header.Set("X-Goog-Upload-Offset", "0")
recChunk := httptest.NewRecorder()
handler.ServeHTTP(recChunk, reqChunk)
// 3. Finalize fails with proxy 502 and NO X-Goog-Upload-Status header
reqFinalizeFailed := httptest.NewRequest("POST", uploadURL, nil)
reqFinalizeFailed.Header.Set("X-Goog-Upload-Command", "finalize")
recFinalizeFailed := httptest.NewRecorder()
handler.ServeHTTP(recFinalizeFailed, reqFinalizeFailed)
if recFinalizeFailed.Code != http.StatusBadGateway {
t.Fatalf("expected 502, got %d", recFinalizeFailed.Code)
}
if statusHeader := recFinalizeFailed.Header().Get("X-Goog-Upload-Status"); statusHeader != "" {
t.Fatalf("expected status header to be omitted, got %q", statusHeader)
}
// 4. Query recovers upload state
reqQuery := httptest.NewRequest("POST", uploadURL, nil)
reqQuery.Header.Set("X-Goog-Upload-Command", "query")
recQuery := httptest.NewRecorder()
handler.ServeHTTP(recQuery, reqQuery)
if got := recQuery.Header().Get("X-Goog-Upload-Size-Received"); got != "14" {
t.Fatalf("expected committed size 14, got %q", got)
}
}
```
```
partheniou@partheniou-vm-3:~/git/gapic-showcase$ go test -count=1 -v ./server/resumableupload -run "TestProxyErrorWithoutUploadStatusOnFinalize"
=== RUN TestProxyErrorWithoutUploadStatusOnFinalize
resumableupload_test.go:648: expected 502, got 200
--- FAIL: TestProxyErrorWithoutUploadStatusOnFinalize (0.00s)
FAIL
FAIL github.com/googleapis/gapic-showcase/server/resumableupload 0.012s
FAIL
```
Contributor guide
Research direction
Start in server/resumableupload/resumableupload.go, then inspect the related tests in server/resumableupload/resumableupload_test.go and run the focused test command shown in the issue. Add support for omit_status_header in X-Goog-Test-Scenario-Config while preserving the configured error code and active session state. Done means the finalize request returns 502 without X-Goog-Upload-Status and a subsequent query reports the committed upload size.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100