Allow empty paths, notifying if no valid files are found
This commit is contained in:
parent
ccff56d28d
commit
5167ff457e
|
@ -9,7 +9,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yosssi/gohtml"
|
||||
|
@ -25,21 +24,17 @@ var (
|
|||
ErrNoMediaFound = errors.New("no supported media formats found which match all criteria")
|
||||
)
|
||||
|
||||
func newErrorPage(title, body string) string {
|
||||
var htmlBody strings.Builder
|
||||
|
||||
htmlBody.WriteString(`<!DOCTYPE html><html lang="en"><head>`)
|
||||
htmlBody.WriteString(faviconHtml)
|
||||
htmlBody.WriteString(`<style>html,body,a{display:block;height:100%;width:100%;text-decoration:none;color:inherit;cursor:auto;}</style>`)
|
||||
htmlBody.WriteString(fmt.Sprintf("<title>%s</title></head>", title))
|
||||
htmlBody.WriteString(fmt.Sprintf("<body><a href=\"/\">%s</a></body></html>", body))
|
||||
|
||||
return htmlBody.String()
|
||||
}
|
||||
|
||||
func notFound(w http.ResponseWriter, r *http.Request, path string) error {
|
||||
startTime := time.Now()
|
||||
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
|
||||
_, err := io.WriteString(w, gohtml.Format(newPage("Not Found", "404 Page not found")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if Verbose {
|
||||
fmt.Printf("%s | ERROR: Unavailable file %s requested by %s\n",
|
||||
startTime.Format(logDate),
|
||||
|
@ -48,20 +43,16 @@ func notFound(w http.ResponseWriter, r *http.Request, path string) error {
|
|||
)
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
|
||||
_, err := io.WriteString(w, gohtml.Format(newErrorPage("Not Found", "404 Page not found")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func serverError(w http.ResponseWriter, r *http.Request, i interface{}) {
|
||||
startTime := time.Now()
|
||||
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
|
||||
io.WriteString(w, gohtml.Format(newPage("Server Error", "An error has occurred. Please try again.")))
|
||||
|
||||
if Verbose {
|
||||
fmt.Printf("%s | ERROR: Invalid request for %s from %s\n",
|
||||
startTime.Format(logDate),
|
||||
|
@ -69,10 +60,6 @@ func serverError(w http.ResponseWriter, r *http.Request, i interface{}) {
|
|||
r.RemoteAddr,
|
||||
)
|
||||
}
|
||||
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
|
||||
io.WriteString(w, gohtml.Format(newErrorPage("Server Error", "An error has occurred. Please try again.")))
|
||||
}
|
||||
|
||||
func serverErrorHandler() func(http.ResponseWriter, *http.Request, interface{}) {
|
||||
|
|
20
cmd/files.go
20
cmd/files.go
|
@ -10,6 +10,7 @@ import (
|
|||
"io/fs"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"slices"
|
||||
|
||||
"crypto/rand"
|
||||
|
@ -205,6 +206,10 @@ func pathIsValid(path string, paths []string) bool {
|
|||
}
|
||||
|
||||
func hasSupportedFiles(path string, formats types.Types) (bool, error) {
|
||||
if AllowEmpty {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
hasRegisteredFiles := make(chan bool, 1)
|
||||
|
||||
err := filepath.WalkDir(path, func(p string, info os.DirEntry, err error) error {
|
||||
|
@ -463,7 +468,7 @@ Poll:
|
|||
filesMatched+filesSkipped,
|
||||
directoriesMatched,
|
||||
directoriesMatched+directoriesSkipped,
|
||||
time.Since(startTime),
|
||||
time.Since(startTime)-100*time.Millisecond,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -514,7 +519,10 @@ func fileList(paths []string, filters *filters, sort string, index *fileIndex, f
|
|||
func pickFile(list []string) (string, error) {
|
||||
fileCount := len(list)
|
||||
|
||||
if fileCount < 1 {
|
||||
switch {
|
||||
case fileCount < 1 && AllowEmpty:
|
||||
return "", nil
|
||||
case fileCount < 1:
|
||||
return "", ErrNoMediaFound
|
||||
}
|
||||
|
||||
|
@ -531,6 +539,14 @@ func pickFile(list []string) (string, error) {
|
|||
return list[val], nil
|
||||
}
|
||||
|
||||
func preparePath(prefix, path string) string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return fmt.Sprintf("%s/%s", prefix, filepath.ToSlash(path))
|
||||
}
|
||||
|
||||
return prefix + path
|
||||
}
|
||||
|
||||
func normalizePath(path string) (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
|
|
|
@ -14,12 +14,13 @@ import (
|
|||
|
||||
const (
|
||||
AllowedCharacters string = `^[A-z0-9.\-_]+$`
|
||||
ReleaseVersion string = "3.7.2"
|
||||
ReleaseVersion string = "3.8.0"
|
||||
)
|
||||
|
||||
var (
|
||||
AdminPrefix string
|
||||
All bool
|
||||
AllowEmpty bool
|
||||
Audio bool
|
||||
BinaryPrefix bool
|
||||
Bind string
|
||||
|
@ -111,6 +112,7 @@ func Execute() {
|
|||
func init() {
|
||||
rootCmd.Flags().StringVar(&AdminPrefix, "admin-prefix", "", "string to prepend to administrative paths")
|
||||
rootCmd.Flags().BoolVarP(&All, "all", "a", false, "enable all supported file types")
|
||||
rootCmd.Flags().BoolVar(&AllowEmpty, "allow-empty", false, "allow specifying paths containing no supported files")
|
||||
rootCmd.Flags().BoolVar(&Audio, "audio", false, "enable support for audio files")
|
||||
rootCmd.Flags().BoolVar(&BinaryPrefix, "binary-prefix", false, "use IEC binary prefixes instead of SI decimal prefixes")
|
||||
rootCmd.Flags().StringVarP(&Bind, "bind", "b", "0.0.0.0", "address to bind to")
|
||||
|
|
31
cmd/web.go
31
cmd/web.go
|
@ -42,12 +42,31 @@ const (
|
|||
timeout time.Duration = 10 * time.Second
|
||||
)
|
||||
|
||||
func preparePath(prefix, path string) string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return fmt.Sprintf("%s/%s", prefix, filepath.ToSlash(path))
|
||||
func newPage(title, body string) string {
|
||||
var htmlBody strings.Builder
|
||||
|
||||
htmlBody.WriteString(`<!DOCTYPE html><html lang="en"><head>`)
|
||||
htmlBody.WriteString(faviconHtml)
|
||||
htmlBody.WriteString(`<style>html,body,a{display:block;height:100%;width:100%;text-decoration:none;color:inherit;cursor:auto;}</style>`)
|
||||
htmlBody.WriteString(fmt.Sprintf("<title>%s</title></head>", title))
|
||||
htmlBody.WriteString(fmt.Sprintf("<body><a href=\"/\">%s</a></body></html>", body))
|
||||
|
||||
return htmlBody.String()
|
||||
}
|
||||
|
||||
return prefix + path
|
||||
func noFiles(w http.ResponseWriter, r *http.Request) {
|
||||
startTime := time.Now()
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
|
||||
w.Write([]byte("No files found in the specified path(s).\n"))
|
||||
|
||||
if Verbose {
|
||||
fmt.Printf("%s | SERVE: Empty path notice served to %s\n",
|
||||
startTime.Format(logDate),
|
||||
r.RemoteAddr,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func serveStaticFile(paths []string, index *fileIndex, errorChannel chan<- error) httprouter.Handle {
|
||||
|
@ -210,6 +229,10 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
|
|||
|
||||
path, err = newFile(list, sortOrder, regexes, formats)
|
||||
switch {
|
||||
case path == "":
|
||||
noFiles(w, r)
|
||||
|
||||
return
|
||||
case err != nil && err == ErrNoMediaFound:
|
||||
notFound(w, r, path)
|
||||
|
||||
|
|
Loading…
Reference in New Issue