package handlers import ( "errors" "fmt" "net/http" "os" "path/filepath" "time" "git.max-richter.dev/max/marka/server/internal/fsx" "git.max-richter.dev/max/marka/server/internal/httpx" ) func (h *File) get(w http.ResponseWriter, r *http.Request, target string) { fi, err := os.Stat(target) if err != nil { if os.IsNotExist(err) { httpx.WriteError(w, http.StatusNotFound, errors.New("not found")) } else { httpx.WriteError(w, http.StatusInternalServerError, err) } return } if fi.IsDir() { h.handleDir(w, r, target) } else { h.handleFile(w, r, target, fi) } } func (h *File) handleDir(w http.ResponseWriter, r *http.Request, dirPath string) { entries, err := os.ReadDir(dirPath) if err != nil { httpx.WriteError(w, http.StatusInternalServerError, err) return } type item struct { Name string `json:"name"` Path string `json:"path"` Content any `json:"content,omitempty"` IsDir bool `json:"isDir"` Size int64 `json:"size"` ModTime time.Time `json:"modTime"` } out := make([]item, 0, len(entries)) for _, e := range entries { info, _ := e.Info() // As in original, ignore error to get partial info entryPath := filepath.Join(dirPath, e.Name()) var content any if !e.IsDir() && fsx.ContentTypeFor(e.Name()) == "application/markdown" { content, _ = parseMarkdownFile(entryPath) // As in original, ignore error } out = append(out, item{ Name: e.Name(), Path: fsx.ResponsePath(h.root, entryPath), IsDir: e.IsDir(), Content: content, Size: sizeOrZero(info), ModTime: modTimeOrZero(info), }) } httpx.WriteJSON(w, http.StatusOK, out) } func (h *File) handleFile(w http.ResponseWriter, r *http.Request, target string, fi os.FileInfo) { contentType := fsx.ContentTypeFor(target) if contentType == "application/markdown" { res, err := parseMarkdownFile(target) if err != nil { httpx.WriteError(w, http.StatusInternalServerError, fmt.Errorf("failed to parse markdown: %w", err)) return } httpx.WriteJSON(w, http.StatusOK, res) return } f, err := os.Open(target) if err != nil { httpx.WriteError(w, http.StatusInternalServerError, err) return } defer f.Close() w.Header().Set("Content-Type", contentType) http.ServeContent(w, r, filepath.Base(target), fi.ModTime(), f) }