package main import ( dwhttp "dwelling-files/internal/http" "dwelling-files/pkg/files" "dwelling-files/web" "dwelling-files/web/locales" "flag" "fmt" "log" "net/http" "os" "os/signal" "syscall" "git.arav.su/Arav/httpr" "github.com/invopop/ctxi18n" ) var version string var listenAddress *string = flag.String("listen", "/var/run/dwelling-files/sock", "listen address (ip:port|unix_path)") var directoryPath *string = flag.String("path", "/srv/ftp", "path to file share") var enableFileHandler *bool = flag.Bool("file-handling", false, "enable file handling if it is handled by something else (e.g. NGiNX)") var showVersion *bool = flag.Bool("v", false, "show version") func main() { flag.Parse() log.SetFlags(0) if *showVersion { fmt.Println("dwelling-files ver.", version, "\nCopyright (c) 2023,2024 Alexander \"Arav\" Andreev ") return } if err := ctxi18n.LoadWithDefault(locales.Content, "en"); err != nil { log.Fatalln(err) } r := httpr.New() r.Handler(http.MethodGet, "/", Index) r.Handler(http.MethodGet, "/*filepath", Index) r.ServeStatic("/assets/*filepath", web.Assets()) var fileServer http.Handler if *enableFileHandler { fileServer = http.FileServer(http.Dir(*directoryPath)) } r.Handler(http.MethodGet, "/file/*filepath", func(w http.ResponseWriter, r *http.Request) { if !*enableFileHandler { http.Error(w, "File handling is turned off.", http.StatusServiceUnavailable) return } r.URL.Path = httpr.Param(r, "filepath") fileServer.ServeHTTP(w, r) }) srv := dwhttp.NewHttpServer(I18nMiddleware(r)) if err := srv.Start(*listenAddress); err != nil { log.Fatalln(err) } doneSignal := make(chan os.Signal, 1) signal.Notify(doneSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) <-doneSignal if err := srv.Stop(); err != nil { log.Fatalln(err) } } func I18nMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { lang := "en" if lq := r.URL.Query().Get("lang"); lq != "" { lc := http.Cookie{Name: "lang", Value: lq, HttpOnly: false, MaxAge: 0} http.SetCookie(w, &lc) lang = lq } else if l, err := r.Cookie("lang"); err == nil { lang = l.Value } else if al := r.Header.Get("Accept-Language"); al != "" { lang = r.Header.Get("Accept-Language") } ctx, err := ctxi18n.WithLocale(r.Context(), lang) if err != nil { log.Println("i18nmw:", err) } next.ServeHTTP(w, r.WithContext(ctx)) }) } func Index(w http.ResponseWriter, r *http.Request) { path := "/" + httpr.Param(r, "filepath") if path[len(path)-1] != '/' { path += "/" } entries, stats, err := files.ScanDirectory(*directoryPath+path, path) if err != nil { log.Println("Error directory scan:", err) http.Error(w, "Not found", http.StatusNotFound) return } web.Index(files.CurrentPath(path), version, &stats, &entries, r).Render(r.Context(), w) }