Add the URLFor optional method to the storagedriver api

We now also have a storagedriver error variable for identifying
api calls that are not implemented by drivers (the URLFor method
is not implemented by either the filesystem or inmemory drivers)
This commit is contained in:
Andrey Kostov 2015-01-07 18:31:38 +02:00
parent fadd5dfcfb
commit a2b294f444
5 changed files with 57 additions and 0 deletions

View file

@ -265,6 +265,12 @@ func (d *Driver) Delete(subPath string) error {
return err return err
} }
// URLFor returns a URL which may be used to retrieve the content stored at the given path.
// May return an UnsupportedMethodErr in certain StorageDriver implementations.
func (d *Driver) URLFor(path string) (string, error) {
return "", storagedriver.ErrUnsupportedMethod
}
// fullPath returns the absolute path of a key within the Driver's storage. // fullPath returns the absolute path of a key within the Driver's storage.
func (d *Driver) fullPath(subPath string) string { func (d *Driver) fullPath(subPath string) string {
return path.Join(d.rootDirectory, subPath) return path.Join(d.rootDirectory, subPath)

View file

@ -251,3 +251,9 @@ func (d *Driver) Delete(path string) error {
return err return err
} }
} }
// URLFor returns a URL which may be used to retrieve the content stored at the given path.
// May return an UnsupportedMethodErr in certain StorageDriver implementations.
func (d *Driver) URLFor(path string) (string, error) {
return "", storagedriver.ErrUnsupportedMethod
}

View file

@ -580,6 +580,16 @@ func (d *Driver) Delete(path string) error {
return nil return nil
} }
// URLFor returns a URL which may be used to retrieve the content stored at the given path.
// May return an UnsupportedMethodErr in certain StorageDriver implementations.
func (d *Driver) URLFor(path string) (string, error) {
if !storagedriver.PathRegexp.MatchString(path) {
return "", storagedriver.InvalidPathError{Path: path}
}
return d.Bucket.SignedURL(d.s3Path(path), time.Now().Add(24*time.Hour)), nil
}
func (d *Driver) s3Path(path string) string { func (d *Driver) s3Path(path string) string {
return strings.TrimLeft(strings.TrimRight(d.rootDirectory, "/")+path, "/") return strings.TrimLeft(strings.TrimRight(d.rootDirectory, "/")+path, "/")
} }

View file

@ -1,6 +1,7 @@
package storagedriver package storagedriver
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"regexp" "regexp"
@ -69,6 +70,10 @@ type StorageDriver interface {
// Delete recursively deletes all objects stored at "path" and its subpaths. // Delete recursively deletes all objects stored at "path" and its subpaths.
Delete(path string) error Delete(path string) error
// URLFor returns a URL which may be used to retrieve the content stored at the given path.
// May return an UnsupportedMethodErr in certain StorageDriver implementations.
URLFor(path string) (string, error)
} }
// PathRegexp is the regular expression which each file path must match. // PathRegexp is the regular expression which each file path must match.
@ -78,6 +83,9 @@ type StorageDriver interface {
// a period, underscore, or hyphen. // a period, underscore, or hyphen.
var PathRegexp = regexp.MustCompile(`^(/[a-z0-9]+([._-][a-z0-9]+)*)+$`) var PathRegexp = regexp.MustCompile(`^(/[a-z0-9]+([._-][a-z0-9]+)*)+$`)
// UnsupportedMethodErr may be returned in the case where a StorageDriver implementation does not support an optional method.
var ErrUnsupportedMethod = errors.New("Unsupported method")
// PathNotFoundError is returned when operating on a nonexistent path. // PathNotFoundError is returned when operating on a nonexistent path.
type PathNotFoundError struct { type PathNotFoundError struct {
Path string Path string

View file

@ -6,6 +6,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"net/http"
"os" "os"
"path" "path"
"sort" "sort"
@ -580,6 +581,32 @@ func (suite *DriverSuite) TestDelete(c *check.C) {
c.Assert(err, check.FitsTypeOf, storagedriver.PathNotFoundError{}) c.Assert(err, check.FitsTypeOf, storagedriver.PathNotFoundError{})
} }
// TestURLFor checks that the URLFor method functions properly, but only if it
// is implemented
func (suite *DriverSuite) TestURLFor(c *check.C) {
filename := randomPath(32)
contents := randomContents(32)
defer suite.StorageDriver.Delete(firstPart(filename))
err := suite.StorageDriver.PutContent(filename, contents)
c.Assert(err, check.IsNil)
url, err := suite.StorageDriver.URLFor(filename)
if err == storagedriver.ErrUnsupportedMethod {
return
}
c.Assert(err, check.IsNil)
response, err := http.Get(url)
c.Assert(err, check.IsNil)
defer response.Body.Close()
read, err := ioutil.ReadAll(response.Body)
c.Assert(err, check.IsNil)
c.Assert(read, check.DeepEquals, contents)
}
// TestDeleteNonexistent checks that removing a nonexistent key fails. // TestDeleteNonexistent checks that removing a nonexistent key fails.
func (suite *DriverSuite) TestDeleteNonexistent(c *check.C) { func (suite *DriverSuite) TestDeleteNonexistent(c *check.C) {
filename := randomPath(32) filename := randomPath(32)