37 lines
1.2 KiB
Go
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
|
|
}
|