Files
2026-08-15 07:13:00 +00:00

37 lines
1.2 KiB
Go

package site
import "strings"
// splitTilde splits a site URL path into its project and the rest.
//
// "/~proj" -> ("proj", "", true)
// "/~proj/" -> ("proj", "/", true)
// "/~proj/a/b" -> ("proj", "/a/b", true)
// "/", "/x", "/~" -> ("", "", false)
//
// The remainder keeps its leading slash, because its absence is what
// distinguishes "/~proj" — which has to be redirected before relative links
// inside the page can resolve — from "/~proj/".
//
// This is hand-parsed rather than expressed as a ServeMux pattern because
// net/http rejects "/~{project}/{path...}": its wildcards must start a path
// segment. Registering "/" instead also keeps the mux's built-in ".." and "//"
// redirects, though those are a convenience and not a defence — a
// percent-encoded traversal arrives here already decoded and unredirected, so
// Resolve does its own normalisation.
func splitTilde(urlPath string) (project, rest string, ok bool) {
if !strings.HasPrefix(urlPath, "/~") {
return "", "", false
}
rest = urlPath[len("/~"):]
if i := strings.IndexByte(rest, '/'); i >= 0 {
project, rest = rest[:i], rest[i:]
} else {
project, rest = rest, ""
}
if project == "" {
return "", "", false
}
return project, rest, true
}