Add file duration
This commit is contained in:
@@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
@@ -27,6 +29,17 @@ func main() {
|
||||
if uploadDir == "" {
|
||||
uploadDir = "/uploads"
|
||||
}
|
||||
var fileExpires time.Duration = 7 * 24 * time.Hour
|
||||
|
||||
dryRun := strings.ToLower(os.Getenv("DRYRUN_CLEAN")) != "false"
|
||||
fileDuration := os.Getenv("FILE_DURATION")
|
||||
if fileDuration != "" {
|
||||
expires, err := time.ParseDuration(fileDuration)
|
||||
if err != nil {
|
||||
log.Fatalf("FILE_DURATION %s is invalid: %v", fileDuration, err)
|
||||
}
|
||||
fileExpires = expires
|
||||
}
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
@@ -40,6 +53,13 @@ func main() {
|
||||
http.HandleFunc("/", handleRequest)
|
||||
|
||||
log.Printf("Starting server on port %s, upload directory: %s", port, uploadDir)
|
||||
log.Printf("Files expires after: %v (DRYRUN_CLEAN=%v)", fileExpires, dryRun)
|
||||
if fileExpires != 0 {
|
||||
go cleanupProcedure(fileExpires, dryRun)
|
||||
} else {
|
||||
log.Print("Cleaning old files is disabled")
|
||||
}
|
||||
|
||||
if err := http.ListenAndServe(":"+port, nil); err != nil {
|
||||
log.Fatalf("Server failed: %v", err)
|
||||
}
|
||||
@@ -261,7 +281,7 @@ func getHost(r *http.Request) string {
|
||||
|
||||
// Check standard Forwarded header (RFC 7239)
|
||||
if forwarded := r.Header.Get("Forwarded"); forwarded != "" {
|
||||
// Parse "Forwarded: for=...; host=example.com; proto=https"
|
||||
// Parse "Forwarded: for=...; host=example.com; proto=https"
|
||||
parts := strings.SplitSeq(forwarded, ";")
|
||||
for part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
@@ -325,3 +345,95 @@ func serveFrontpage(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
indexHTML.Execute(w, pageData)
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
||||
func isDirEmpty(name string) (bool, error) {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Read exactly one entry.
|
||||
_, err = f.ReadDir(1)
|
||||
if errors.Is(err, io.EOF) {
|
||||
// EOF means there are no entries, so the directory is empty.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If err is nil, an entry was found (not empty).
|
||||
// If err is something else, a real error occurred.
|
||||
return false, err
|
||||
}
|
||||
|
||||
func cleanupProcedure(duration time.Duration, dryRun bool) {
|
||||
var oldFiles []string
|
||||
var emptyDirs []string
|
||||
|
||||
deleteIfTooOld := func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
log.Printf("Error cleaning file '%s' : %v", d.Name(), err)
|
||||
return nil
|
||||
}
|
||||
age := time.Since(info.ModTime())
|
||||
if age >= duration {
|
||||
oldFiles = append(oldFiles, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
findEmptyDirs := func(path string, d fs.DirEntry, err error) error {
|
||||
if !d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
empty, err := isDirEmpty(path)
|
||||
if empty {
|
||||
emptyDirs = append(emptyDirs, path)
|
||||
} else if err != nil {
|
||||
log.Printf("Error cleaning directory '%s' : %v", path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
filepath.WalkDir(uploadDir, deleteIfTooOld)
|
||||
for _, file := range oldFiles {
|
||||
if !dryRun {
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
log.Printf("Failed to remove expired file '%s' : %v", file, err)
|
||||
} else {
|
||||
log.Printf("Removed expired file '%s'", file)
|
||||
}
|
||||
} else {
|
||||
log.Printf("Dry run: Would remove expired file '%s'", file)
|
||||
}
|
||||
}
|
||||
|
||||
filepath.WalkDir(uploadDir, findEmptyDirs)
|
||||
for _, file := range emptyDirs {
|
||||
if !dryRun {
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
log.Printf("Failed to remove empty folder '%s' : %v", file, err)
|
||||
} else {
|
||||
log.Printf("Removed empty folder '%s'", file)
|
||||
}
|
||||
} else {
|
||||
log.Printf("Dry run: Would remove empty folder '%s'", file)
|
||||
}
|
||||
}
|
||||
time.Sleep(6 * time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user