This commit is contained in:
Max Richter
2025-09-24 22:39:14 +02:00
parent 733ae876b9
commit 3f0d25f935
18 changed files with 2 additions and 145 deletions

View File

@@ -1,3 +0,0 @@
module git.max-richter.dev/max/marka/server-new
go 1.25.1

View File

@@ -1,16 +1,3 @@
module git.max-richter.dev/max/marka/server
module git.max-richter.dev/max/marka/server-new
go 1.24.5
require git.max-richter.dev/max/marka/parser v0.0.0-20250819170608-69c2550f448e
require (
git.max-richter.dev/max/marka/registry v0.0.0-20250817132016-6db87db32567 // indirect
git.max-richter.dev/max/marka/renderer v0.0.0-20250819170608-69c2550f448e // indirect
git.max-richter.dev/max/marka/template v0.0.0-20250817132016-6db87db32567 // indirect
git.max-richter.dev/max/marka/testdata v0.0.0-20250819195334-b3c01bb43d9a // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.1 // indirect
golang.org/x/text v0.14.0 // indirect
)
go 1.25.1

View File

@@ -1,33 +0,0 @@
package fsx
import (
"mime"
"path/filepath"
"strings"
)
var textPlainExtensions = map[string]bool{
".txt": true,
".log": true,
".json": true,
".yaml": true,
".yml": true,
".toml": true,
".xml": true,
".csv": true,
}
func ContentTypeFor(name string) string {
ext := strings.ToLower(filepath.Ext(name))
switch ext {
case ".md", ".markdown", ".mdown":
return "application/markdown"
}
if ct := mime.TypeByExtension(ext); ct != "" {
return ct
}
if textPlainExtensions[ext] {
return "text/plain; charset=utf-8"
}
return "application/octet-stream"
}

View File

@@ -1,56 +0,0 @@
package fsx
import (
"errors"
"path/filepath"
"strings"
)
func CleanURLLike(p string) string {
p = strings.TrimSpace(p)
if p == "" || p == "/" {
return "/"
}
parts := []string{}
for seg := range strings.SplitSeq(strings.ReplaceAll(p, "/", "/"), "/") {
switch seg {
case "", ".":
continue
case "..":
if len(parts) > 0 {
parts = parts[:len(parts)-1]
}
default:
parts = append(parts, seg)
}
}
return "/" + strings.Join(parts, "/")
}
func SafeRel(root, requested string) (string, error) {
s := CleanURLLike(requested)
if after, ok := strings.CutPrefix(s, "/"); ok {
s = after
}
full := filepath.Join(root, filepath.FromSlash(s))
rel, err := filepath.Rel(root, full)
if err != nil {
return "", err
}
if rel == "." {
return "/", nil
}
sep := string(filepath.Separator)
if strings.HasPrefix(rel, "..") || strings.Contains(rel, ".."+sep) {
return "", errors.New("path escapes root")
}
return "/" + filepath.ToSlash(rel), nil
}
func ResponsePath(root, full string) string {
rel, err := filepath.Rel(root, full)
if err != nil || rel == "." {
return "/"
}
return "/" + filepath.ToSlash(rel)
}

View File

@@ -1,38 +0,0 @@
// Package handlers provides HTTP handlers for the file system.
package handlers
import (
"errors"
"net/http"
"path/filepath"
"git.max-richter.dev/max/marka/server/internal/fsx"
"git.max-richter.dev/max/marka/server/internal/httpx"
)
type File struct{ root string }
func NewFile(root string) http.Handler { return &File{root: root} }
func (h *File) ServeHTTP(w http.ResponseWriter, r *http.Request) {
reqPath := r.URL.Path
if reqPath == "" {
reqPath = "/"
}
cleanRel, err := fsx.SafeRel(h.root, reqPath)
if err != nil {
httpx.WriteError(w, http.StatusBadRequest, err)
return
}
target := filepath.Join(h.root, filepath.FromSlash(cleanRel))
switch r.Method {
case http.MethodGet:
h.get(w, r, target)
case http.MethodPost:
h.post(w, r, target)
default:
httpx.WriteError(w, http.StatusMethodNotAllowed, errors.New("method not allowed"))
}
}