Repository navigation
Description
NewRangerReaderuses the XML api to download files.conditionsQuery()uses the JSON API to configure preconditionsNewRangerReadercallsconditionsQuery()rather than setting the expected precondition headers.
ObjectHandle.NewReader() calls NewRangeReader:
google-cloud-go/storage/reader.go
Lines 79 to 81 in 5ac09d9
| func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) { | |
| return o.NewRangeReader(ctx, 0, -1) | |
| } |
This eventually sets req.URL.RawQuery = conditionsQuery(gen, o.conds):
google-cloud-go/storage/reader.go
Lines 151 to 152 in 5ac09d9
| // We wait to assign conditions here because the generation number can change in between reopen() runs. | |
| req.URL.RawQuery = conditionsQuery(gen, o.conds) |
conditionsQuery() appends the applicable JSON API URL parameters:
google-cloud-go/storage/storage.go
Lines 1620 to 1633 in 5ac09d9
| switch { | |
| case conds.GenerationMatch != 0: | |
| appendParam("ifGenerationMatch=", conds.GenerationMatch) | |
| case conds.GenerationNotMatch != 0: | |
| appendParam("ifGenerationNotMatch=", conds.GenerationNotMatch) | |
| case conds.DoesNotExist: | |
| appendParam("ifGenerationMatch=", 0) | |
| } | |
| switch { | |
| case conds.MetagenerationMatch != 0: | |
| appendParam("ifMetagenerationMatch=", conds.MetagenerationMatch) | |
| case conds.MetagenerationNotMatch != 0: | |
| appendParam("ifMetagenerationNotMatch=", conds.MetagenerationNotMatch) | |
| } |
However, the readHost is not the json api, it is the xml api:
google-cloud-go/storage/storage.go
Line 118 in 5ac09d9
| readHost = "storage.googleapis.com" |
The xml API expects an x-goog-if-generation-match header. It does not recognize the JSON API's url parameters.
Thus the following will always work and never return the expected preconditon error:
client := storage.NewClient()
r, err := client.Bucket("whatever").Object("some/object").If(&storage.Conditions{GenerationMatch: 666}).NewReader(context.Background())
if err == nil {
panic("should have failed")
}
gerr, ok := err.(*googleapi.Error)
if !ok {
panic("should have returned a googleapi error")
}
if gerr.Code != http.PreconditionFailed {
panic("should have return a precondition failed error")
}
// congrats! This bug no longer repros.
Activity
fix(storage): revise Reader to send XML preconditions (#4479)
chore: release storage 1.16.1 (#4441)