diff --git a/google/config.go b/google/config.go index 5d0da33..d854bd0 100644 --- a/google/config.go +++ b/google/config.go @@ -15,6 +15,7 @@ import ( // Kind represents the name of the location/storage type. const Kind = "google" +const Protocol = "gs" const ( // The service account json blob diff --git a/google/container.go b/google/container.go index f52f2d5..bad274c 100644 --- a/google/container.go +++ b/google/container.go @@ -150,10 +150,7 @@ func merge(metadata ...map[string]string) map[string]string { } func (c *Container) convertToStowItem(attr *storage.ObjectAttrs) (stow.Item, error) { - u, err := prepUrl(attr.MediaLink) - if err != nil { - return nil, err - } + u := prepUrl(attr) mdParsed, err := parseMetadata(attr.Metadata) if err != nil { diff --git a/google/item.go b/google/item.go index a6b7e94..6c3952e 100644 --- a/google/item.go +++ b/google/item.go @@ -75,15 +75,21 @@ func (i *Item) StorageObject() *storage.ObjectAttrs { return i.object } -// prepUrl takes a MediaLink string and returns a url -func prepUrl(str string) (*url.URL, error) { - u, err := url.Parse(str) - if err != nil { - return nil, err +// prepUrl takes ObjectAttrs and returns a url constructed from the bucket and name. +// We don't use attr.MediaLink because it is in the format +// `google://storage.googleapis.com/download/storage/v1/b/some-bucket/...` instead of +// `gs://some-bucket/...`. +// Otherwise, when using stow to list a bucket `gs://...`, the resulting objects +// `google://storage.googleapis.com/download/storage/v1/b/...` could not be found +// using the same stow client. +func prepUrl(attr *storage.ObjectAttrs) *url.URL { + u := url.URL{ + Scheme: Protocol, + Host: attr.Bucket, + Path: attr.Name, } - u.Scheme = "google" // Discard the query string u.RawQuery = "" - return u, nil + return &u } diff --git a/google/location.go b/google/location.go index 0497876..da3d13f 100644 --- a/google/location.go +++ b/google/location.go @@ -113,22 +113,34 @@ func (l *Location) RemoveContainer(id string) error { // ItemByURL retrieves a stow.Item by parsing the URL, in this // case an item is an object. func (l *Location) ItemByURL(url *url.URL) (stow.Item, error) { - if url.Scheme != Kind { - return nil, errors.New("not valid google storage URL") - } + if url.Scheme == Kind { + // Url in the form: google://storage.googleapis.com/download/storage/v1/b/some-bucket + pieces := strings.SplitN(url.Path, "/", 8) - // /download/storage/v1/b/stowtesttoudhratik/o/a_first%2Fthe%20item - pieces := strings.SplitN(url.Path, "/", 8) + c, err := l.Container(pieces[5]) + if err != nil { + return nil, stow.ErrNotFound + } - c, err := l.Container(pieces[5]) - if err != nil { - return nil, stow.ErrNotFound - } + i, err := c.Item(pieces[7]) + if err != nil { + return nil, stow.ErrNotFound + } + return i, nil - i, err := c.Item(pieces[7]) - if err != nil { - return nil, stow.ErrNotFound - } + } else if url.Scheme == Protocol { + // Url in the form: gs://some-bucket + c, err := l.Container(url.Host) + if err != nil { + return nil, stow.ErrNotFound + } - return i, nil + i, err := c.Item(url.Path) + if err != nil { + return nil, stow.ErrNotFound + } + return i, nil + } else { + return nil, errors.New("not valid google storage URL") + } }