diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/main.go b/cmd/file-server/main.go similarity index 64% rename from main.go rename to cmd/file-server/main.go index 4f5a584..0bffb30 100644 --- a/main.go +++ b/cmd/file-server/main.go @@ -5,6 +5,8 @@ import ( "fmt" "net/http" "os" + + "file-server/internal/handler" ) var port uint @@ -17,18 +19,20 @@ func init() { } func main() { - if folderPath == "" { fmt.Fprintf(os.Stderr, "Error: parametr 'path' is required") os.Exit(1) } server := &http.Server{ - Addr: fmt.Sprintf(":%d", port), - Handler: &fileHandler{ - root: folderPath, - }, + Addr: fmt.Sprintf(":%d", port), + Handler: handler.NewHandler(folderPath), } - server.ListenAndServe() + err := server.ListenAndServe() + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v", err) + + os.Exit(1) + } } diff --git a/ev.json b/ev.json deleted file mode 100644 index 1166e2c..0000000 --- a/ev.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build": [ - ["make"] - ], - "services": [ - { - "name": "files-server", - "restart_after_update": true, - "cmd": ["./files-server", "-p", "/var/files/", "-l", "8745"] - } - ] -} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d91b5a5 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module file-server + +go 1.20 diff --git a/handler.go b/internal/handler/handler.go similarity index 76% rename from handler.go rename to internal/handler/handler.go index 93782a2..99c354b 100644 --- a/handler.go +++ b/internal/handler/handler.go @@ -1,4 +1,4 @@ -package main +package handler import ( "fmt" @@ -8,7 +8,6 @@ import ( "net/url" "os" "path" - "path/filepath" "sort" "strings" ) @@ -49,18 +48,18 @@ func localRedirect(w http.ResponseWriter, r *http.Request, newPath string) { } func toHTTPError(err error) (msg string, httpStatus int) { - if os.IsNotExist(err) { + switch { + case os.IsNotExist(err): return "404 page not found", http.StatusNotFound - } - if os.IsPermission(err) { + case os.IsPermission(err): return "403 Forbidden", http.StatusForbidden + default: + return "500 Internal Server Error", http.StatusInternalServerError } - // Default: - return "500 Internal Server Error", http.StatusInternalServerError } -func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name string) { - f, err := fs.Open(name) +func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, filePath string) { + f, err := fs.Open(filePath) if err != nil { msg, code := toHTTPError(err) renderError(w, msg, code) @@ -86,7 +85,7 @@ func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name // Still a directory? (we didn't find an index.html file) if d.IsDir() { - dirList(w, r, f, name, fs) + dirList(w, r, f, fs, filePath) return } @@ -95,7 +94,7 @@ func serveFile(w http.ResponseWriter, r *http.Request, fs http.FileSystem, name http.ServeContent(w, r, d.Name(), d.ModTime(), f) } -func dirList(w http.ResponseWriter, r *http.Request, f http.File, name string, fs http.FileSystem) { +func dirList(w http.ResponseWriter, r *http.Request, f http.File, fs http.FileSystem, filePath string) { dirs, err := f.Readdir(-1) if err != nil { renderError(w, "Error reading directory", http.StatusInternalServerError) @@ -110,35 +109,39 @@ func dirList(w http.ResponseWriter, r *http.Request, f http.File, name string, f w.Header().Set("Content-Type", "text/html; charset=utf-8") - t, err := template.New("main.html").ParseFiles("main.html") + t, err := template.New("main.html").ParseFiles("static/main.html") if err != nil { fmt.Printf(err.Error()) return } data := &Data{ - Title: name, - IsRoot: name == "/", + Title: filePath, + IsRoot: filePath == "/", Files: make([]*File, 0, len(dirs)), - Readme: loadReadmeFile(name, fs), } for _, d := range dirs { - name := d.Name() + fileName := d.Name() icon := "file" size := byteCountBinary(d.Size()) + if d.IsDir() { - name += "/" + fileName += "/" icon = "folder" size = "-" } - url := url.URL{Path: name} + if !d.IsDir() && strings.HasPrefix(strings.ToLower(fileName), "readme.") { + data.Readme = loadReadmeFile(fs, filePath+"/"+fileName) + } + + url := url.URL{Path: fileName} data.Files = append(data.Files, &File{ Icon: icon, URL: url.String(), - Name: htmlReplacer.Replace(name), + Name: htmlReplacer.Replace(fileName), Size: size, Date: d.ModTime().Format("02.01.2006 15:04:05"), }) @@ -152,8 +155,8 @@ func dirList(w http.ResponseWriter, r *http.Request, f http.File, name string, f } -func loadReadmeFile(path string, fs http.FileSystem) string { - f, err := fs.Open(filepath.Join(path, "readme.txt")) +func loadReadmeFile(fs http.FileSystem, fileName string) string { + f, err := fs.Open(fileName) if err != nil { return "" } @@ -166,14 +169,22 @@ func loadReadmeFile(path string, fs http.FileSystem) string { } type fileHandler struct { - root string + rootPath string +} + +func NewHandler(rootPath string) http.Handler { + return &fileHandler{ + rootPath: rootPath, + } } func (fh *fileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { upath := r.URL.Path + if !strings.HasPrefix(upath, "/") { upath = "/" + upath r.URL.Path = upath } - serveFile(w, r, http.Dir(fh.root), path.Clean(upath)) + + serveFile(w, r, http.Dir(fh.rootPath), path.Clean(upath)) } diff --git a/struct.go b/internal/handler/struct.go similarity index 92% rename from struct.go rename to internal/handler/struct.go index ced44af..79deb2c 100644 --- a/struct.go +++ b/internal/handler/struct.go @@ -1,4 +1,4 @@ -package main +package handler // File - type File struct { diff --git a/makefile b/makefile index 64eb922..7869313 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,8 @@ +.PHONY: build + all: build -build: - go build -o files-server \ No newline at end of file +build: build/files-server + +build/files-server: cmd/file-server/main.go internal/handler/*.go + go build -o build/files-server cmd/file-server/main.go diff --git a/main.html b/static/main.html similarity index 100% rename from main.html rename to static/main.html