@@ -64,7 +64,7 @@ func (rx *ResumableUpload) Progress() int64 {
64
64
// off specifies the offset in rx.Media from which data is drawn.
65
65
// size is the number of bytes in data.
66
66
// final specifies whether data is the final chunk to be uploaded.
67
- func (rx * ResumableUpload ) doUploadRequest (ctx context.Context , data io.Reader , off , size int64 , final bool ) (* http.Response , error ) {
67
+ func (rx * ResumableUpload ) doUploadRequest (ctx context.Context , invocationID string , attempts int , data io.Reader , off , size int64 , final bool ) (* http.Response , error ) {
68
68
req , err := http .NewRequest ("POST" , rx .URI , data )
69
69
if err != nil {
70
70
return nil , err
@@ -88,11 +88,11 @@ func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader,
88
88
// TODO(b/274504690): Consider dropping gccl-invocation-id key since it
89
89
// duplicates the X-Goog-Gcs-Idempotency-Token header (added in v0.115.0).
90
90
baseXGoogHeader := "gl-go/" + GoVersion () + " gdcl/" + internal .Version
91
- invocationHeader := fmt .Sprintf ("gccl-invocation-id/%s gccl-attempt-count/%d" , rx . invocationID , rx . attempts )
91
+ invocationHeader := fmt .Sprintf ("gccl-invocation-id/%s gccl-attempt-count/%d" , invocationID , attempts )
92
92
req .Header .Set ("X-Goog-Api-Client" , strings .Join ([]string {baseXGoogHeader , invocationHeader }, " " ))
93
93
94
94
// Set idempotency token header which is used by GCS uploads.
95
- req .Header .Set ("X-Goog-Gcs-Idempotency-Token" , rx . invocationID )
95
+ req .Header .Set ("X-Goog-Gcs-Idempotency-Token" , invocationID )
96
96
97
97
// Google's upload endpoint uses status code 308 for a
98
98
// different purpose than the "308 Permanent Redirect"
@@ -127,14 +127,27 @@ func (rx *ResumableUpload) reportProgress(old, updated int64) {
127
127
}
128
128
129
129
// transferChunk performs a single HTTP request to upload a single chunk.
130
- // It uses a goroutine to perform the upload and a timer to enforce ChunkTransferTimeout or ChunkRetryDeadline.
131
- func (rx * ResumableUpload ) transferChunk (ctx context.Context , chunkRetryDeadline time.Duration , chunk io.Reader , off , size int64 , done bool ) (* http.Response , error ) {
132
- if rx .ChunkTransferTimeout != 0 {
133
- chunkRetryDeadline = rx .ChunkTransferTimeout
130
+ // It uses a goroutine to perform the upload and a timer to enforce ChunkTransferTimeout.
131
+ func (rx * ResumableUpload ) transferChunk (ctx context.Context , invocationID string , attempts int , chunk io.Reader , off , size int64 , done bool ) (* http.Response , error ) {
132
+ // If no timeout is specified, perform the request synchronously without a timer.
133
+ if rx .ChunkTransferTimeout == 0 {
134
+ res , err := rx .doUploadRequest (ctx , invocationID , attempts , chunk , off , size , done )
135
+ if err != nil {
136
+ return res , err
137
+ }
138
+ // We sent "X-GUploader-No-308: yes" (see comment elsewhere in
139
+ // this file), so we don't expect to get a 308.
140
+ if res .StatusCode == 308 {
141
+ return nil , errors .New ("unexpected 308 response status code" )
142
+ }
143
+ if res .StatusCode == http .StatusOK {
144
+ rx .reportProgress (off , off + int64 (size ))
145
+ }
146
+ return res , nil
134
147
}
135
148
136
- // Start a timer for the configured duration.
137
- timer := time .NewTimer (chunkRetryDeadline )
149
+ // Start a timer for the ChunkTransferTimeout duration.
150
+ timer := time .NewTimer (rx . ChunkTransferTimeout )
138
151
139
152
// A struct to hold the result from the goroutine.
140
153
type uploadResult struct {
@@ -154,7 +167,7 @@ func (rx *ResumableUpload) transferChunk(ctx context.Context, chunkRetryDeadline
154
167
155
168
// Starting the chunk upload in parallel.
156
169
go func () {
157
- res , err := rx .doUploadRequest (rCtx , chunk , off , size , done )
170
+ res , err := rx .doUploadRequest (rCtx , invocationID , attempts , chunk , off , size , done )
158
171
resultCh <- uploadResult {res : res , err : err }
159
172
}()
160
173
@@ -267,7 +280,7 @@ func (rx *ResumableUpload) uploadChunkWithRetries(ctx context.Context, chunk io.
267
280
io .Copy (io .Discard , resp .Body )
268
281
resp .Body .Close ()
269
282
}
270
- resp , err = rx .transferChunk (ctx , chunkRetryDeadline , chunk , off , size , done )
283
+ resp , err = rx .transferChunk (ctx , rx . invocationID , rx . attempts , chunk , off , size , done )
271
284
status := 0
272
285
if resp != nil {
273
286
status = resp .StatusCode
0 commit comments