wrip
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
module git.max-richter.dev/max/marka/server-new
|
||||
|
||||
go 1.25.1
|
@@ -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
|
||||
|
@@ -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"
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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"))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user