mirror of https://github.com/jlelse/GoBlog
Local media storage
This commit is contained in:
parent
b2c618f300
commit
4c87a95e73
|
@ -247,10 +247,10 @@ func initConfig() error {
|
|||
if appConfig.Micropub.MediaStorage.MediaURL == "" ||
|
||||
appConfig.Micropub.MediaStorage.BunnyStorageKey == "" ||
|
||||
appConfig.Micropub.MediaStorage.BunnyStorageName == "" {
|
||||
appConfig.Micropub.MediaStorage = nil
|
||||
} else {
|
||||
appConfig.Micropub.MediaStorage.MediaURL = strings.TrimSuffix(appConfig.Micropub.MediaStorage.MediaURL, "/")
|
||||
appConfig.Micropub.MediaStorage.BunnyStorageKey = ""
|
||||
appConfig.Micropub.MediaStorage.BunnyStorageName = ""
|
||||
}
|
||||
appConfig.Micropub.MediaStorage.MediaURL = strings.TrimSuffix(appConfig.Micropub.MediaStorage.MediaURL, "/")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
7
http.go
7
http.go
|
@ -103,9 +103,7 @@ func buildHandler() (http.Handler, error) {
|
|||
mpRouter.Use(checkIndieAuth, middleware.NoCache, minifier.Middleware)
|
||||
mpRouter.Get("/", serveMicropubQuery)
|
||||
mpRouter.Post("/", serveMicropubPost)
|
||||
if appConfig.Micropub.MediaStorage != nil {
|
||||
mpRouter.Post(micropubMediaSubPath, serveMicropubMedia)
|
||||
}
|
||||
mpRouter.Post(micropubMediaSubPath, serveMicropubMedia)
|
||||
})
|
||||
|
||||
// Editor
|
||||
|
@ -182,6 +180,9 @@ func buildHandler() (http.Handler, error) {
|
|||
r.With(cacheMiddleware).Get(path, serveStaticFile)
|
||||
}
|
||||
|
||||
// Media files
|
||||
r.With(cacheMiddleware).Get(`/m/{file:[0-9a-fA-F]+(\.[0-9a-zA-Z]+)?}`, serveMediaFile)
|
||||
|
||||
// Short paths
|
||||
r.With(cacheMiddleware).Get("/s/{id:[0-9a-fA-F]+}", redirectToLongPath)
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
)
|
||||
|
||||
const mediaFilePath = "data/media"
|
||||
|
||||
func saveMediaFile(filename string, mediaFile io.Reader) (string, error) {
|
||||
err := os.MkdirAll(mediaFilePath, 0644)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
newFile, err := os.Create(filepath.Join(mediaFilePath, filename))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = io.Copy(newFile, mediaFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "/m/" + filename, nil
|
||||
}
|
||||
|
||||
func serveMediaFile(w http.ResponseWriter, r *http.Request) {
|
||||
f := filepath.Join(mediaFilePath, chi.URLParam(r, "file"))
|
||||
_, err := os.Stat(f)
|
||||
if err != nil {
|
||||
serve404(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Cache-Control", "public,max-age=31536000,immutable")
|
||||
http.ServeFile(w, r, f)
|
||||
}
|
|
@ -26,11 +26,9 @@ func serveMicropubQuery(w http.ResponseWriter, r *http.Request) {
|
|||
case "config":
|
||||
w.Header().Add(contentType, contentTypeJSONUTF8)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
mc := µpubConfig{}
|
||||
if appConfig.Micropub.MediaStorage != nil {
|
||||
mc.MediaEndpoint = appConfig.Server.PublicAddress + micropubPath + micropubMediaSubPath
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(mc)
|
||||
_ = json.NewEncoder(w).Encode(µpubConfig{
|
||||
MediaEndpoint: appConfig.Server.PublicAddress + micropubPath + micropubMediaSubPath,
|
||||
})
|
||||
case "source":
|
||||
var mf interface{}
|
||||
if urlString := r.URL.Query().Get("url"); urlString != "" {
|
||||
|
|
|
@ -63,34 +63,53 @@ func serveMicropubMedia(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
fileName += strings.ToLower(fileExtension)
|
||||
location, err := appConfig.Micropub.MediaStorage.uploadToBunny(fileName, file)
|
||||
// Save file
|
||||
location, err := uploadFile(fileName, file)
|
||||
if err != nil {
|
||||
serveError(w, r, "failed to upload original file: "+err.Error(), http.StatusInternalServerError)
|
||||
serveError(w, r, "failed to save original file: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if appConfig.Micropub.MediaStorage.TinifyKey != "" {
|
||||
compressedLocation, err := appConfig.Micropub.MediaStorage.tinify(location)
|
||||
// Try to compress file
|
||||
if ms := appConfig.Micropub.MediaStorage; ms != nil && ms.TinifyKey != "" {
|
||||
compressedLocation, err := tinify(location, ms)
|
||||
if err != nil {
|
||||
serveError(w, r, "failed to compress file: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else if compressedLocation != "" {
|
||||
location = compressedLocation
|
||||
} else {
|
||||
serveError(w, r, "No compressed location", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
http.Redirect(w, r, location, http.StatusCreated)
|
||||
}
|
||||
|
||||
func (mediaConf *configMicropubMedia) uploadToBunny(filename string, file multipart.File) (location string, err error) {
|
||||
req, _ := http.NewRequest(http.MethodPut, fmt.Sprintf("https://storage.bunnycdn.com/%s/%s", url.PathEscape(mediaConf.BunnyStorageName), url.PathEscape(filename)), file)
|
||||
req.Header.Add("AccessKey", mediaConf.BunnyStorageKey)
|
||||
func uploadFile(filename string, f io.Reader) (string, error) {
|
||||
ms := appConfig.Micropub.MediaStorage
|
||||
if ms != nil && ms.BunnyStorageKey != "" && ms.BunnyStorageName != "" {
|
||||
return uploadToBunny(filename, f, ms)
|
||||
}
|
||||
loc, err := saveMediaFile(filename, f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ms != nil && ms.MediaURL != "" {
|
||||
return ms.MediaURL + loc, nil
|
||||
}
|
||||
return loc, nil
|
||||
}
|
||||
|
||||
func uploadToBunny(filename string, f io.Reader, config *configMicropubMedia) (location string, err error) {
|
||||
req, _ := http.NewRequest(http.MethodPut, fmt.Sprintf("https://storage.bunnycdn.com/%s/%s", url.PathEscape(config.BunnyStorageName), url.PathEscape(filename)), f)
|
||||
req.Header.Add("AccessKey", config.BunnyStorageKey)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil || resp.StatusCode != http.StatusCreated {
|
||||
return "", errors.New("failed to upload file to BunnyCDN")
|
||||
}
|
||||
return mediaConf.MediaURL + "/" + filename, nil
|
||||
return config.MediaURL + "/" + filename, nil
|
||||
}
|
||||
|
||||
func (mediaConf *configMicropubMedia) tinify(url string) (location string, err error) {
|
||||
func tinify(url string, config *configMicropubMedia) (location string, err error) {
|
||||
fileExtension := func() string {
|
||||
spliced := strings.Split(url, ".")
|
||||
return spliced[len(spliced)-1]
|
||||
|
@ -101,7 +120,7 @@ func (mediaConf *configMicropubMedia) tinify(url string) (location string, err e
|
|||
if !(i < len(supportedTypes) && supportedTypes[i] == strings.ToLower(fileExtension)) {
|
||||
return "", nil
|
||||
}
|
||||
tfgo.SetKey(mediaConf.TinifyKey)
|
||||
tfgo.SetKey(config.TinifyKey)
|
||||
s, err := tfgo.FromUrl(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -134,7 +153,7 @@ func (mediaConf *configMicropubMedia) tinify(url string) (location string, err e
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
location, err = mediaConf.uploadToBunny(fileName+"."+fileExtension, file)
|
||||
location, err = uploadFile(fileName+"."+fileExtension, file)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue