Add concurrency limits; add optional admin path prefix
This commit is contained in:
parent
fef51438c0
commit
14adbdf742
|
@ -16,6 +16,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
ErrInvalidAdminPrefix = errors.New("admin path must not contain a '/'")
|
||||||
|
ErrInvalidConcurrency = errors.New("concurrency limit must be between 1 and 8192 inclusive")
|
||||||
ErrInvalidFileCountRange = errors.New("maximum file count limit must be greater than or equal to minimum file count limit")
|
ErrInvalidFileCountRange = errors.New("maximum file count limit must be greater than or equal to minimum file count limit")
|
||||||
ErrInvalidFileCountValue = errors.New("file count limits must be non-negative integers no greater than 2147483647")
|
ErrInvalidFileCountValue = errors.New("file count limits must be non-negative integers no greater than 2147483647")
|
||||||
ErrInvalidPort = errors.New("listen port must be an integer between 1 and 65535 inclusive")
|
ErrInvalidPort = errors.New("listen port must be an integer between 1 and 65535 inclusive")
|
||||||
|
|
15
cmd/files.go
15
cmd/files.go
|
@ -226,7 +226,13 @@ func hasSupportedFiles(path string, formats types.Types) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkPath(path string, fileChannel chan<- string, stats *scanStatsChannels, formats types.Types) error {
|
func walkPath(path string, fileChannel chan<- string, stats *scanStatsChannels, limit chan int, formats types.Types) error {
|
||||||
|
limit <- 1
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
<-limit
|
||||||
|
}()
|
||||||
|
|
||||||
errorChannel := make(chan error)
|
errorChannel := make(chan error)
|
||||||
done := make(chan bool, 1)
|
done := make(chan bool, 1)
|
||||||
|
|
||||||
|
@ -277,7 +283,7 @@ func walkPath(path string, fileChannel chan<- string, stats *scanStatsChannels,
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case node.IsDir() && Recursive:
|
case node.IsDir() && Recursive:
|
||||||
err := walkPath(fullPath, fileChannel, stats, formats)
|
err := walkPath(fullPath, fileChannel, stats, limit, formats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
|
||||||
|
@ -398,6 +404,8 @@ func scanPaths(paths []string, sort string, index *fileIndex, formats types.Type
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
limit := make(chan int, Concurrency)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for i := 0; i < len(paths); i++ {
|
for i := 0; i < len(paths); i++ {
|
||||||
|
@ -407,7 +415,8 @@ func scanPaths(paths []string, sort string, index *fileIndex, formats types.Type
|
||||||
defer func() {
|
defer func() {
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
err := walkPath(paths[i], fileChannel, statsChannels, formats)
|
|
||||||
|
err := walkPath(paths[i], fileChannel, statsChannels, limit, formats)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
|
16
cmd/info.go
16
cmd/info.go
|
@ -305,19 +305,19 @@ func serveEnabledMediaTypes(formats types.Types, errorChannel chan<- error) http
|
||||||
|
|
||||||
func registerInfoHandlers(mux *httprouter.Router, args []string, index *fileIndex, formats types.Types, errorChannel chan<- error) {
|
func registerInfoHandlers(mux *httprouter.Router, args []string, index *fileIndex, formats types.Types, errorChannel chan<- error) {
|
||||||
if Index {
|
if Index {
|
||||||
registerHandler(mux, Prefix+"/index/html", serveIndexHtml(args, index, false))
|
registerHandler(mux, Prefix+AdminPrefix+"/index/html", serveIndexHtml(args, index, false))
|
||||||
if PageLength != 0 {
|
if PageLength != 0 {
|
||||||
registerHandler(mux, Prefix+"/index/html/:page", serveIndexHtml(args, index, true))
|
registerHandler(mux, Prefix+AdminPrefix+"/index/html/:page", serveIndexHtml(args, index, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
registerHandler(mux, Prefix+"/index/json", serveIndexJson(args, index, errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/index/json", serveIndexJson(args, index, errorChannel))
|
||||||
if PageLength != 0 {
|
if PageLength != 0 {
|
||||||
registerHandler(mux, Prefix+"/index/json/:page", serveIndexJson(args, index, errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/index/json/:page", serveIndexJson(args, index, errorChannel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerHandler(mux, Prefix+"/extensions/available", serveAvailableExtensions(errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/extensions/available", serveAvailableExtensions(errorChannel))
|
||||||
registerHandler(mux, Prefix+"/extensions/enabled", serveEnabledExtensions(formats, errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/extensions/enabled", serveEnabledExtensions(formats, errorChannel))
|
||||||
registerHandler(mux, Prefix+"/types/available", serveAvailableMediaTypes(errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/types/available", serveAvailableMediaTypes(errorChannel))
|
||||||
registerHandler(mux, Prefix+"/types/enabled", serveEnabledMediaTypes(formats, errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/types/enabled", serveEnabledMediaTypes(formats, errorChannel))
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ func registerProfileHandler(mux *httprouter.Router, verb, path string, handler h
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerProfileHandlers(mux *httprouter.Router) {
|
func registerProfileHandlers(mux *httprouter.Router) {
|
||||||
registerProfileHandler(mux, "GET", Prefix+"/debug/pprof/", pprof.Index)
|
registerProfileHandler(mux, "GET", Prefix+AdminPrefix+"/debug/pprof/", pprof.Index)
|
||||||
registerProfileHandler(mux, "GET", Prefix+"/debug/pprof/cmdline", pprof.Cmdline)
|
registerProfileHandler(mux, "GET", Prefix+AdminPrefix+"/debug/pprof/cmdline", pprof.Cmdline)
|
||||||
registerProfileHandler(mux, "GET", Prefix+"/debug/pprof/profile", pprof.Profile)
|
registerProfileHandler(mux, "GET", Prefix+AdminPrefix+"/debug/pprof/profile", pprof.Profile)
|
||||||
registerProfileHandler(mux, "GET", Prefix+"/debug/pprof/symbol", pprof.Symbol)
|
registerProfileHandler(mux, "GET", Prefix+AdminPrefix+"/debug/pprof/symbol", pprof.Symbol)
|
||||||
registerProfileHandler(mux, "GET", Prefix+"/debug/pprof/trace", pprof.Trace)
|
registerProfileHandler(mux, "GET", Prefix+AdminPrefix+"/debug/pprof/trace", pprof.Trace)
|
||||||
}
|
}
|
||||||
|
|
13
cmd/root.go
13
cmd/root.go
|
@ -7,21 +7,24 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ReleaseVersion string = "3.3.2"
|
ReleaseVersion string = "3.4.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
AdminPrefix string
|
||||||
All bool
|
All bool
|
||||||
Audio bool
|
Audio bool
|
||||||
Bind string
|
Bind string
|
||||||
CaseSensitive bool
|
CaseSensitive bool
|
||||||
Code bool
|
Code bool
|
||||||
CodeTheme string
|
CodeTheme string
|
||||||
|
Concurrency int
|
||||||
DisableButtons bool
|
DisableButtons bool
|
||||||
ExitOnError bool
|
ExitOnError bool
|
||||||
Fallback bool
|
Fallback bool
|
||||||
|
@ -61,6 +64,12 @@ var (
|
||||||
return ErrInvalidFileCountRange
|
return ErrInvalidFileCountRange
|
||||||
case Port < 1 || Port > 65535:
|
case Port < 1 || Port > 65535:
|
||||||
return ErrInvalidPort
|
return ErrInvalidPort
|
||||||
|
case Concurrency < 1 || Concurrency > 8192:
|
||||||
|
return ErrInvalidConcurrency
|
||||||
|
case strings.Contains(AdminPrefix, "/"):
|
||||||
|
return ErrInvalidAdminPrefix
|
||||||
|
case AdminPrefix != "":
|
||||||
|
AdminPrefix = "/" + AdminPrefix
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -84,12 +93,14 @@ func Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
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().BoolVarP(&All, "all", "a", false, "enable all supported file types")
|
||||||
rootCmd.Flags().BoolVar(&Audio, "audio", false, "enable support for audio files")
|
rootCmd.Flags().BoolVar(&Audio, "audio", false, "enable support for audio files")
|
||||||
rootCmd.Flags().StringVarP(&Bind, "bind", "b", "0.0.0.0", "address to bind to")
|
rootCmd.Flags().StringVarP(&Bind, "bind", "b", "0.0.0.0", "address to bind to")
|
||||||
rootCmd.Flags().BoolVar(&CaseSensitive, "case-sensitive", false, "use case-sensitive matching for filters")
|
rootCmd.Flags().BoolVar(&CaseSensitive, "case-sensitive", false, "use case-sensitive matching for filters")
|
||||||
rootCmd.Flags().BoolVar(&Code, "code", false, "enable support for source code files")
|
rootCmd.Flags().BoolVar(&Code, "code", false, "enable support for source code files")
|
||||||
rootCmd.Flags().StringVar(&CodeTheme, "code-theme", "solarized-dark256", "theme for source code syntax highlighting")
|
rootCmd.Flags().StringVar(&CodeTheme, "code-theme", "solarized-dark256", "theme for source code syntax highlighting")
|
||||||
|
rootCmd.Flags().IntVar(&Concurrency, "concurrency", 1024, "maximum concurrency for scan threads")
|
||||||
rootCmd.Flags().BoolVar(&DisableButtons, "disable-buttons", false, "disable first/prev/next/last buttons")
|
rootCmd.Flags().BoolVar(&DisableButtons, "disable-buttons", false, "disable first/prev/next/last buttons")
|
||||||
rootCmd.Flags().BoolVar(&ExitOnError, "exit-on-error", false, "shut down webserver on error, instead of just printing the error")
|
rootCmd.Flags().BoolVar(&ExitOnError, "exit-on-error", false, "shut down webserver on error, instead of just printing the error")
|
||||||
rootCmd.Flags().BoolVar(&Fallback, "fallback", false, "serve files as application/octet-stream if no matching format is registered")
|
rootCmd.Flags().BoolVar(&Fallback, "fallback", false, "serve files as application/octet-stream if no matching format is registered")
|
||||||
|
|
|
@ -544,7 +544,7 @@ func ServePage(args []string) error {
|
||||||
registerHandler(mux, Prefix+"/version", serveVersion())
|
registerHandler(mux, Prefix+"/version", serveVersion())
|
||||||
|
|
||||||
if Index {
|
if Index {
|
||||||
registerHandler(mux, Prefix+"/index/rebuild", serveIndexRebuild(args, index, formats, errorChannel))
|
registerHandler(mux, Prefix+AdminPrefix+"/index/rebuild", serveIndexRebuild(args, index, formats, errorChannel))
|
||||||
|
|
||||||
err = importIndex(paths, index, formats)
|
err = importIndex(paths, index, formats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue