Require trailing slash when specifying directory path

This commit is contained in:
Trevor Slocum 2020-12-05 22:49:53 -08:00
parent 3a46bd1de8
commit a96e2123fb
3 changed files with 23 additions and 14 deletions

View file

@ -29,9 +29,12 @@ Hosts are defined by their hostname followed by one or more paths to serve.
Paths may be defined as fixed strings or regular expressions (starting with `^`). Paths may be defined as fixed strings or regular expressions (starting with `^`).
Paths are matched in the order they are defined. Any path not matching a specific page, file name or file extension should end
in a trailing slash, signifying that it is a directory. Visitors are
automatically redirected when accessing a directory path without including a
trailing slash.
Fixed string paths will match with and without a trailing slash. Paths are matched in the order they are defined.
When accessing a directory the file `index.gemini` or `index.gmi` is served. When accessing a directory the file `index.gemini` or `index.gmi` is served.
@ -223,18 +226,18 @@ hosts:
root: /home/geminirocks/public_html root: /home/geminirocks/public_html
fastcgi: unix:///var/run/php.sock fastcgi: unix:///var/run/php.sock
- -
path: /files path: /files/
root: /home/geminirocks/files root: /home/geminirocks/files
cache: 604800 # Cache for 1 week cache: 604800 # Cache for 1 week
list: true # Enable directory listing list: true # Enable directory listing
- -
path: ^/(help|info)$ path: ^/(help|info)/$
root: /home/geminirocks/docs/help root: /home/geminirocks/docs/help
- -
path: ^/proxy-example$ path: /proxy-example/
proxy: gemini://localhost:1966 proxy: gemini://localhost:1966
- -
path: ^/cmd-example$ path: /cmd-example
command: uname -a command: uname -a
cache: 0 # Do not cache cache: 0 # Do not cache
- -

View file

@ -214,9 +214,6 @@ func readconfig(configPath string) error {
if serve.Path == "" { if serve.Path == "" {
log.Fatal("a path must be specified in each serve entry") log.Fatal("a path must be specified in each serve entry")
} }
if len(serve.Path) > 1 && serve.Path[len(serve.Path)-1] == '/' {
serve.Path = serve.Path[:len(serve.Path)-1]
}
if serve.Path[0] == '^' { if serve.Path[0] == '^' {
serve.r = regexp.MustCompile(serve.Path) serve.r = regexp.MustCompile(serve.Path)
} }

View file

@ -133,9 +133,6 @@ func servePath(c *tls.Conn, request *url.URL, serve *pathConfig) (int, int64) {
if serve.Path[0] == '/' { if serve.Path[0] == '/' {
pathSlashes++ // Regexp does not match starting slash pathSlashes++ // Regexp does not match starting slash
} }
if serve.Path[0] != '^' && serve.Path[len(serve.Path)-1] != '/' {
pathSlashes++
}
} }
if len(requestSplit) >= pathSlashes { if len(requestSplit) >= pathSlashes {
resolvedPath = strings.Join(requestSplit[pathSlashes:], "/") resolvedPath = strings.Join(requestSplit[pathSlashes:], "/")
@ -262,15 +259,27 @@ func handleRequest(c *tls.Conn, request *url.URL, requestData string) (int, int6
matchedRegexp := serve.r != nil && serve.r.Match(pathBytes) matchedRegexp := serve.r != nil && serve.r.Match(pathBytes)
matchedPrefix := serve.r == nil && strings.HasPrefix(request.Path, serve.Path) matchedPrefix := serve.r == nil && strings.HasPrefix(request.Path, serve.Path)
if !matchedRegexp && !matchedPrefix { if !matchedRegexp && !matchedPrefix {
matchedRegexp = serve.r != nil && serve.r.Match(append(pathBytes[:], byte('/')))
matchedPrefix = serve.r == nil && strings.HasPrefix(request.Path+"/", serve.Path)
if matchedRegexp || matchedPrefix {
newRequest, err := url.Parse(request.String())
if err != nil {
return writeStatus(c, statusBadRequest), -1, ""
}
newRequest.Path += "/"
return writeHeader(c, statusRedirectTemporary, newRequest.String()), -1, serve.Log
}
continue continue
} }
requireInput := serve.Input != "" || serve.SensitiveInput != "" requireInput := serve.Input != "" || serve.SensitiveInput != ""
if request.RawQuery == "" && requireInput { if request.RawQuery == "" && requireInput {
if serve.SensitiveInput != "" { if serve.SensitiveInput != "" {
return writeHeader(c, statusSensitiveInput, serve.SensitiveInput), -1, "" return writeHeader(c, statusSensitiveInput, serve.SensitiveInput), -1, serve.Log
} }
return writeHeader(c, statusInput, serve.Input), -1, "" return writeHeader(c, statusInput, serve.Input), -1, serve.Log
} }
if matchedRegexp || matchedPrefix { if matchedRegexp || matchedPrefix {