Skip to content

Commit

Permalink
chore(gensupport): add idempotency header (#1916)
Browse files Browse the repository at this point in the history
This header will allow GCS object uploads to be idempotent by
default. For other products, it will have no effect.


---------

Co-authored-by: Noah Dietz <noahdietz@users.noreply.github.com>
  • Loading branch information
tritone and noahdietz committed Mar 21, 2023
1 parent 649bfb9 commit be028cf
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
9 changes: 7 additions & 2 deletions internal/gensupport/resumable.go
Expand Up @@ -43,8 +43,8 @@ type ResumableUpload struct {
// retries should happen.
ChunkRetryDeadline time.Duration

// Track current request invocation ID and attempt count for retry metric
// headers.
// Track current request invocation ID and attempt count for retry metrics
// and idempotency headers.
invocationID string
attempts int
}
Expand Down Expand Up @@ -81,10 +81,15 @@ func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader,
req.Header.Set("Content-Type", rx.MediaType)
req.Header.Set("User-Agent", rx.UserAgent)

// TODO(b/274504690): Consider dropping gccl-invocation-id key since it
// duplicates the X-Goog-Gcs-Idempotency-Token header (added in v0.115.0).
baseXGoogHeader := "gl-go/" + GoVersion() + " gdcl/" + internal.Version
invocationHeader := fmt.Sprintf("gccl-invocation-id/%s gccl-attempt-count/%d", rx.invocationID, rx.attempts)
req.Header.Set("X-Goog-Api-Client", strings.Join([]string{baseXGoogHeader, invocationHeader}, " "))

// Set idempotency token header which is used by GCS uploads.
req.Header.Set("X-Goog-Gcs-Idempotency-Token", rx.invocationID)

// Google's upload endpoint uses status code 308 for a
// different purpose than the "308 Permanent Redirect"
// since-standardized in RFC 7238. Because of the conflict in
Expand Down
5 changes: 5 additions & 0 deletions internal/gensupport/send.go
Expand Up @@ -138,9 +138,14 @@ func sendAndRetry(ctx context.Context, client *http.Client, req *http.Request, r
}
return resp, ctx.Err()
}

// Set retry metrics and idempotency headers for GCS.
// TODO(b/274504690): Consider dropping gccl-invocation-id key since it
// duplicates the X-Goog-Gcs-Idempotency-Token header (added in v0.115.0).
invocationHeader := fmt.Sprintf("gccl-invocation-id/%s gccl-attempt-count/%d", invocationID, attempts)
xGoogHeader := strings.Join([]string{invocationHeader, baseXGoogHeader}, " ")
req.Header.Set("X-Goog-Api-Client", xGoogHeader)
req.Header.Set("X-Goog-Gcs-Idempotency-Token", invocationID)

resp, err = client.Do(req.WithContext(ctx))

Expand Down

0 comments on commit be028cf

Please sign in to comment.