mirror of
https://github.com/willnorris/imageproxy.git
synced 2025-02-03 23:10:17 -05:00
136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
// Copyright 2017 Paul Roy All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package azurestoragecache provides an implementation of httpcache.Cache that
|
|
// stores and retrieves data using Azure Storage.
|
|
package azurestoragecache // import "github.com/PaulARoy/azurestoragecache"
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/storage"
|
|
)
|
|
|
|
// Cache stores and retrieves data using Azure Storage.
|
|
type Cache struct {
|
|
// The Azure Blob Storage Client
|
|
client storage.BlobStorageClient
|
|
|
|
// container name to use to store blobs
|
|
container string
|
|
}
|
|
|
|
var noLogErrors, _ = strconv.ParseBool(os.Getenv("NO_LOG_AZUREBSCACHE_ERRORS"))
|
|
|
|
func keyToFilename(key string) string {
|
|
h := md5.New()
|
|
io.WriteString(h, key)
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
// blob retrieves a storage.Blob reference for the specified key.
|
|
func (c *Cache) blob(key string) *storage.Blob {
|
|
return c.client.GetContainerReference(c.container).GetBlobReference(key)
|
|
}
|
|
|
|
// Get the cached value with the specified key.
|
|
func (c *Cache) Get(key string) (resp []byte, ok bool) {
|
|
key = keyToFilename(key)
|
|
rdr, err := c.blob(key).Get(nil)
|
|
if err != nil {
|
|
return []byte{}, false
|
|
}
|
|
|
|
resp, err = ioutil.ReadAll(rdr)
|
|
if err != nil {
|
|
if !noLogErrors {
|
|
log.Printf("azurestoragecache.Get failed: %s", err)
|
|
}
|
|
}
|
|
|
|
rdr.Close()
|
|
return resp, err == nil
|
|
}
|
|
|
|
// Set the cached value with the specified key.
|
|
func (c *Cache) Set(key string, value []byte) {
|
|
key = keyToFilename(key)
|
|
err := c.blob(key).CreateBlockBlobFromReader(bytes.NewReader(value), nil)
|
|
if err != nil {
|
|
if !noLogErrors {
|
|
log.Printf("azurestoragecache.Set failed: %s", err)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
// Delete the cached value with the specified key.
|
|
func (c *Cache) Delete(key string) {
|
|
key = keyToFilename(key)
|
|
res, err := c.blob(key).DeleteIfExists(nil)
|
|
if !noLogErrors {
|
|
log.Printf("azurestoragecache.Delete result: %s", res)
|
|
}
|
|
if err != nil {
|
|
if !noLogErrors {
|
|
log.Printf("azurestoragecache.Delete failed: %s", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// New returns a new Cache with underlying client for Azure Storage.
|
|
//
|
|
// accountName and accountKey are the Azure Storage credentials. If either are
|
|
// empty, the contents of the environment variables AZURESTORAGE_ACCOUNT_NAME
|
|
// and AZURESTORAGE_ACCESS_KEY will be used.
|
|
//
|
|
// containerName is the container name in which cached values will be stored.
|
|
// If not specified, "cache" will be used.
|
|
func New(accountName string, accountKey string, containerName string) (*Cache, error) {
|
|
if accountName == "" {
|
|
accountName = os.Getenv("AZURESTORAGE_ACCOUNT_NAME")
|
|
}
|
|
|
|
if accountKey == "" {
|
|
accountKey = os.Getenv("AZURESTORAGE_ACCESS_KEY")
|
|
}
|
|
|
|
if containerName == "" {
|
|
containerName = "cache"
|
|
}
|
|
|
|
client, err := storage.NewBasicClient(accountName, accountKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cache := Cache{
|
|
client: client.GetBlobService(),
|
|
container: containerName,
|
|
}
|
|
|
|
_, err = cache.client.GetContainerReference(cache.container).CreateIfNotExists(&storage.CreateContainerOptions{Access: storage.ContainerAccessTypeBlob})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &cache, nil
|
|
}
|