package surf import ( "net/http" "strings" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/lagoon/attach" "git.golem15.com/golem15/summercms/modules/pact" "gocloud.dev/blob" "gorm.io/gorm" ) // uploadsPluginID owns the framework uploads route in the route table. const uploadsPluginID = "summercms.surf" // defaultUploadsPrefix matches the prefix attach.OpenBucket records when // storage.uploads.public_path_prefix is empty. const defaultUploadsPrefix = "/storage/uploads" // mountUploads registers GET {storage.uploads.public_path_prefix}/{path...} // when storage.uploads.serve is true. The handler delegates to // attach.StaticHandlerPublic, so missing rows and is_public=false rows 404, // and adds X-Content-Type-Options: nosniff because the files are served on // the app origin. The bucket and the database are looked up per request: // boot and route:list build the router before serve publishes either. // With the key false or absent nothing is registered. func mountUploads(r *Router, app *backpack.App) error { if r == nil || app == nil || app.Config == nil { return nil } if !app.Config.Bool("storage.uploads.serve") { return nil } prefix := strings.TrimSuffix(strings.TrimSpace(app.Config.String("storage.uploads.public_path_prefix")), "/") if prefix == "" { prefix = defaultUploadsPrefix } handler := uploadsHandler(app, prefix) r.BindPlugin(uploadsPluginID) r.GroupRaw(prefix, nil, func(g pact.Router) { g.Get("/{path...}", handler) }) return nil } // uploadsHandler resolves the published bucket and database on every request // and answers 404 while either is missing. func uploadsHandler(app *backpack.App, prefix string) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") bucket, ok := app.Lookup[*blob.Bucket]() if !ok || bucket == nil { http.NotFound(w, req) return } gdb, ok := app.Lookup[*gorm.DB]() if !ok || gdb == nil { http.NotFound(w, req) return } attach.StaticHandlerPublic(bucket, prefix, gdb).ServeHTTP(w, req) } }