mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-10-03 18:05:50 +02:00
Implement fallback images in a similar fashion to watermarks. (#374)
* 220. Implement fallback images in a similar fashion to watermarks. * 220. Fix error formatting. * 220. Fixes based on @darthsim's feedback.
This commit is contained in:
@@ -224,6 +224,10 @@ type config struct {
|
|||||||
WatermarkURL string
|
WatermarkURL string
|
||||||
WatermarkOpacity float64
|
WatermarkOpacity float64
|
||||||
|
|
||||||
|
FallbackImageData string
|
||||||
|
FallbackImagePath string
|
||||||
|
FallbackImageURL string
|
||||||
|
|
||||||
NewRelicAppName string
|
NewRelicAppName string
|
||||||
NewRelicKey string
|
NewRelicKey string
|
||||||
|
|
||||||
@@ -377,6 +381,10 @@ func configure() error {
|
|||||||
strEnvConfig(&conf.WatermarkURL, "IMGPROXY_WATERMARK_URL")
|
strEnvConfig(&conf.WatermarkURL, "IMGPROXY_WATERMARK_URL")
|
||||||
floatEnvConfig(&conf.WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
|
floatEnvConfig(&conf.WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
|
||||||
|
|
||||||
|
strEnvConfig(&conf.FallbackImageData, "IMGPROXY_FALLBACK_IMAGE_DATA")
|
||||||
|
strEnvConfig(&conf.FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
|
||||||
|
strEnvConfig(&conf.FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
|
||||||
|
|
||||||
strEnvConfig(&conf.NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
|
strEnvConfig(&conf.NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
|
||||||
strEnvConfig(&conf.NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
|
strEnvConfig(&conf.NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
|
||||||
|
|
||||||
|
@@ -9,35 +9,51 @@ import (
|
|||||||
|
|
||||||
func getWatermarkData() (*imageData, error) {
|
func getWatermarkData() (*imageData, error) {
|
||||||
if len(conf.WatermarkData) > 0 {
|
if len(conf.WatermarkData) > 0 {
|
||||||
return base64WatermarkData(conf.WatermarkData)
|
return base64ImageData(conf.WatermarkData)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(conf.WatermarkPath) > 0 {
|
if len(conf.WatermarkPath) > 0 {
|
||||||
return fileWatermarkData(conf.WatermarkPath)
|
return fileImageData(conf.WatermarkPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(conf.WatermarkURL) > 0 {
|
if len(conf.WatermarkURL) > 0 {
|
||||||
return remoteWatermarkData(conf.WatermarkURL)
|
return remoteImageData(conf.WatermarkURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func base64WatermarkData(encoded string) (*imageData, error) {
|
func getFallbackImageData() (*imageData, error) {
|
||||||
|
if len(conf.FallbackImageData) > 0 {
|
||||||
|
return base64ImageData(conf.FallbackImageData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(conf.FallbackImagePath) > 0 {
|
||||||
|
return fileImageData(conf.FallbackImagePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(conf.FallbackImageURL) > 0 {
|
||||||
|
return remoteImageData(conf.FallbackImageURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func base64ImageData(encoded string) (*imageData, error) {
|
||||||
data, err := base64.StdEncoding.DecodeString(encoded)
|
data, err := base64.StdEncoding.DecodeString(encoded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't decode watermark data: %s", err)
|
return nil, fmt.Errorf("Can't decode image data: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
imgtype, err := checkTypeAndDimensions(bytes.NewReader(data))
|
imgtype, err := checkTypeAndDimensions(bytes.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't decode watermark: %s", err)
|
return nil, fmt.Errorf("Can't decode image: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &imageData{Data: data, Type: imgtype}, nil
|
return &imageData{Data: data, Type: imgtype}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileWatermarkData(path string) (*imageData, error) {
|
func fileImageData(path string) (*imageData, error) {
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't read watermark: %s", err)
|
return nil, fmt.Errorf("Can't read watermark: %s", err)
|
||||||
@@ -56,18 +72,18 @@ func fileWatermarkData(path string) (*imageData, error) {
|
|||||||
return imgdata, err
|
return imgdata, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func remoteWatermarkData(imageURL string) (*imageData, error) {
|
func remoteImageData(imageURL string) (*imageData, error) {
|
||||||
res, err := requestImage(imageURL)
|
res, err := requestImage(imageURL)
|
||||||
if res != nil {
|
if res != nil {
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't download watermark: %s", err)
|
return nil, fmt.Errorf("Can't download image: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
imgdata, err := readAndCheckImage(res.Body, int(res.ContentLength))
|
imgdata, err := readAndCheckImage(res.Body, int(res.ContentLength))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't download watermark: %s", err)
|
return nil, fmt.Errorf("Can't download image: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return imgdata, err
|
return imgdata, err
|
@@ -16,6 +16,7 @@ var (
|
|||||||
processingSem chan struct{}
|
processingSem chan struct{}
|
||||||
|
|
||||||
headerVaryValue string
|
headerVaryValue string
|
||||||
|
fallback *imageData
|
||||||
)
|
)
|
||||||
|
|
||||||
func initProcessingHandler() error {
|
func initProcessingHandler() error {
|
||||||
@@ -45,6 +46,10 @@ func initProcessingHandler() error {
|
|||||||
|
|
||||||
headerVaryValue = strings.Join(vary, ", ")
|
headerVaryValue = strings.Join(vary, ", ")
|
||||||
|
|
||||||
|
if err := loadFallback(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +158,12 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) {
|
|||||||
if prometheusEnabled {
|
if prometheusEnabled {
|
||||||
incrementPrometheusErrorsTotal("download")
|
incrementPrometheusErrorsTotal("download")
|
||||||
}
|
}
|
||||||
panic(err)
|
if fallback != nil {
|
||||||
|
logError("Could not load image. Using fallback image: %s", err.Error())
|
||||||
|
ctx = context.WithValue(ctx, imageDataCtxKey, fallback)
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkTimeout(ctx)
|
checkTimeout(ctx)
|
||||||
@@ -186,3 +196,11 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
respondWithImage(ctx, reqID, r, rw, imageData)
|
respondWithImage(ctx, reqID, r, rw, imageData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadFallback() (err error) {
|
||||||
|
fallback, err = getFallbackImageData()
|
||||||
|
if err != nil {
|
||||||
|
logError("Could not load fallback data. Fallback images will not be available: %s", err.Error())
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user