mirror of
https://github.com/willnorris/imageproxy.git
synced 2025-01-06 22:40:34 -05:00
0fe3656939
also include all transitive dependencies of gcscache, which seems to bring in the entire world of Google Cloud Platform.
112 lines
2.2 KiB
Go
112 lines
2.2 KiB
Go
package gcscache
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"cloud.google.com/go/storage"
|
|
"golang.org/x/net/context"
|
|
"golang.org/x/oauth2/google"
|
|
"google.golang.org/api/option"
|
|
)
|
|
|
|
type Cache struct {
|
|
pathPrefix string
|
|
bucket *storage.BucketHandle
|
|
}
|
|
|
|
func (c *Cache) Get(key string) (resp []byte, ok bool) {
|
|
obj := c.bucket.Object(c.url(key))
|
|
|
|
rdr, err := obj.NewReader(context.Background())
|
|
if err != nil {
|
|
return []byte{}, false
|
|
}
|
|
defer rdr.Close()
|
|
|
|
resp, err = ioutil.ReadAll(rdr)
|
|
if err != nil {
|
|
log.Printf("gcscache.Get failed: %s", err)
|
|
}
|
|
|
|
return resp, err == nil
|
|
}
|
|
|
|
func (c *Cache) Set(key string, resp []byte) {
|
|
obj := c.bucket.Object(c.url(key))
|
|
|
|
contentType := http.DetectContentType(resp)
|
|
|
|
w := obj.NewWriter(context.Background())
|
|
w.ContentType = contentType
|
|
w.ObjectAttrs.ContentType = contentType
|
|
|
|
_, err := w.Write(resp)
|
|
if err != nil {
|
|
log.Printf("gcscache.Set failed: %s", err)
|
|
}
|
|
|
|
err = w.Close()
|
|
if err != nil {
|
|
log.Printf("gcscache.Set failed: %s", err)
|
|
}
|
|
}
|
|
|
|
func (c *Cache) Delete(key string) {
|
|
obj := c.bucket.Object(c.url(key))
|
|
|
|
err := obj.Delete(context.Background())
|
|
if err != nil {
|
|
log.Printf("gcscache.Delete failed: %s", err)
|
|
}
|
|
}
|
|
|
|
func (c *Cache) url(key string) string {
|
|
key = cacheKeyToObjectKey(key)
|
|
if strings.HasSuffix(c.pathPrefix, "/") {
|
|
return c.pathPrefix + key
|
|
}
|
|
return c.pathPrefix + "/" + key
|
|
}
|
|
|
|
func cacheKeyToObjectKey(key string) string {
|
|
h := md5.New()
|
|
io.WriteString(h, key)
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
func New(bucketURL string) *Cache {
|
|
cfg, err := google.JWTConfigFromJSON([]byte(os.Getenv("GCP_PRIVATE_KEY")), storage.ScopeReadWrite)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ts := cfg.TokenSource(context.Background())
|
|
opt := option.WithTokenSource(ts)
|
|
|
|
client, err := storage.NewClient(context.Background(), opt)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
r := regexp.MustCompile("gcs://([^/]+)(/(.+)?)?$")
|
|
if !r.MatchString(bucketURL) {
|
|
panic("Invalid bucket string format. Must match: gcs://bucket-name/path/prefix")
|
|
}
|
|
|
|
match := r.FindStringSubmatch(bucketURL)
|
|
|
|
bucketName := match[1]
|
|
pathPrefix := match[3]
|
|
|
|
return &Cache{
|
|
pathPrefix: pathPrefix,
|
|
bucket: client.Bucket(bucketName),
|
|
}
|
|
}
|