mirror of https://github.com/jlelse/GoBlog
Add Cloudflare as image compression service
This commit is contained in:
parent
adb6a31b3d
commit
a24cad5699
11
config.go
11
config.go
|
@ -170,11 +170,12 @@ type configMicropub struct {
|
|||
}
|
||||
|
||||
type configMicropubMedia struct {
|
||||
MediaURL string `mapstructure:"mediaUrl"`
|
||||
BunnyStorageKey string `mapstructure:"bunnyStorageKey"`
|
||||
BunnyStorageName string `mapstructure:"bunnyStorageName"`
|
||||
TinifyKey string `mapstructure:"tinifyKey"`
|
||||
ShortPixelKey string `mapstructure:"shortPixelKey"`
|
||||
MediaURL string `mapstructure:"mediaUrl"`
|
||||
BunnyStorageKey string `mapstructure:"bunnyStorageKey"`
|
||||
BunnyStorageName string `mapstructure:"bunnyStorageName"`
|
||||
TinifyKey string `mapstructure:"tinifyKey"`
|
||||
ShortPixelKey string `mapstructure:"shortPixelKey"`
|
||||
CloudflareCompressionEnabled bool `mapstructure:"cloudflareCompressionEnabled"`
|
||||
}
|
||||
|
||||
type configRegexRedirect struct {
|
||||
|
|
|
@ -78,9 +78,10 @@ micropub:
|
|||
# BunnyCDN storage (optional)
|
||||
bunnyStorageKey: BUNNY-STORAGE-KEY # Secret key for BunnyCDN storage
|
||||
bunnyStorageName: storagename # BunnyCDN storage name
|
||||
# Image compression (optional, you can define no, one or both)
|
||||
tinifyKey: TINIFY-KEY # Secret key for the Tinify.com API
|
||||
# Image compression (optional, you can define no, one or multiple services, disabled when private mode enabled)
|
||||
shortPixelKey: SHORT-PIXEL-KEY # Secret key for the ShortPixel API
|
||||
tinifyKey: TINIFY-KEY # Secret key for the Tinify.com API (first fallback)
|
||||
cloudflareCompressionEnabled: true # Use Cloudflare's compression as a second fallback
|
||||
# MicroPub parameters (defaults already set, set to overwrite)
|
||||
# You can set parameters via the UI of your MicroPub editor or via front matter in the content
|
||||
categoryParam: tags
|
||||
|
|
|
@ -149,3 +149,47 @@ func shortPixel(url string, config *configMicropubMedia) (location string, err e
|
|||
location, err = uploadFile(fileName+"."+fileExtension, tmpFile)
|
||||
return
|
||||
}
|
||||
|
||||
func cloudflare(url string) (location string, err error) {
|
||||
// Check url
|
||||
_, allowed := compressionIsSupported(url, "jpg", "jpeg", "png")
|
||||
if !allowed {
|
||||
return "", nil
|
||||
}
|
||||
// Force jpeg
|
||||
fileExtension := "jpeg"
|
||||
// Compress
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://www.cloudflare.com/cdn-cgi/image/f=jpeg,q=75,metadata=none,fit=scale-down,w=%d,h=%d/%s", defaultCompressionWidth, defaultCompressionHeight, url), nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp, err := appHttpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
return "", fmt.Errorf("cloudflare failed to compress image, status code %d", resp.StatusCode)
|
||||
}
|
||||
tmpFile, err := os.CreateTemp("", "tiny-*."+fileExtension)
|
||||
if err != nil {
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
_ = tmpFile.Close()
|
||||
_ = os.Remove(tmpFile.Name())
|
||||
}()
|
||||
if _, err = io.Copy(tmpFile, resp.Body); err != nil {
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
return "", err
|
||||
}
|
||||
fileName, err := getSHA256(tmpFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Upload compressed file
|
||||
location, err = uploadFile(fileName+"."+fileExtension, tmpFile)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -60,31 +60,42 @@ func serveMicropubMedia(w http.ResponseWriter, r *http.Request) {
|
|||
serveError(w, r, "failed to save original file: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Try to compress file
|
||||
if ms := appConfig.Micropub.MediaStorage; ms != nil {
|
||||
// Try to compress file (only when not in private mode)
|
||||
if pm := appConfig.PrivateMode; !(pm != nil && pm.Enabled) {
|
||||
serveCompressionError := func(ce error) {
|
||||
serveError(w, r, "failed to compress file: "+ce.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
var compressedLocation string
|
||||
var compressionErr error
|
||||
// Default ShortPixel
|
||||
if ms.ShortPixelKey != "" {
|
||||
compressedLocation, compressionErr = shortPixel(location, ms)
|
||||
}
|
||||
if compressionErr != nil {
|
||||
serveCompressionError(compressionErr)
|
||||
return
|
||||
}
|
||||
// Fallback Tinify
|
||||
if compressedLocation == "" && ms.TinifyKey != "" {
|
||||
compressedLocation, compressionErr = tinify(location, ms)
|
||||
}
|
||||
if compressionErr != nil {
|
||||
serveCompressionError(compressionErr)
|
||||
return
|
||||
}
|
||||
if compressedLocation != "" {
|
||||
location = compressedLocation
|
||||
if ms := appConfig.Micropub.MediaStorage; ms != nil {
|
||||
// Default ShortPixel
|
||||
if ms.ShortPixelKey != "" {
|
||||
compressedLocation, compressionErr = shortPixel(location, ms)
|
||||
}
|
||||
if compressionErr != nil {
|
||||
serveCompressionError(compressionErr)
|
||||
return
|
||||
}
|
||||
// Fallback Tinify
|
||||
if compressedLocation == "" && ms.TinifyKey != "" {
|
||||
compressedLocation, compressionErr = tinify(location, ms)
|
||||
}
|
||||
if compressionErr != nil {
|
||||
serveCompressionError(compressionErr)
|
||||
return
|
||||
}
|
||||
// Fallback Cloudflare
|
||||
if compressedLocation == "" && ms.CloudflareCompressionEnabled {
|
||||
compressedLocation, compressionErr = cloudflare(location)
|
||||
}
|
||||
if compressionErr != nil {
|
||||
serveCompressionError(compressionErr)
|
||||
return
|
||||
}
|
||||
// Overwrite location
|
||||
if compressedLocation != "" {
|
||||
location = compressedLocation
|
||||
}
|
||||
}
|
||||
}
|
||||
http.Redirect(w, r, location, http.StatusCreated)
|
||||
|
|
Loading…
Reference in New Issue