Merge pull request #19 from nigelsim/recursive-fallback

feat: recursive fallback resolution
This commit is contained in:
Pierre Zemb 2019-10-16 15:36:24 +02:00 committed by GitHub
commit 1699bc8106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 9 deletions

View file

@ -49,7 +49,7 @@ Usage of /goStatic:
-enable-basic-auth
Enable basic auth. By default, password are randomly generated. Use --set-basic-auth to set it.
-fallback string
Default relative to be used when no file requested found. E.g. /index.html
Default fallback file. Either absolute for a specific asset (/index.html), or relative to recursively resolve (index.html).
-password-length int
Size of the randomized password (default 16)
-path string
@ -58,4 +58,13 @@ Usage of /goStatic:
The listening port (default 8043)
-set-basic-auth string
Define the basic auth. Form must be user:password
```
```
#### Fallback
The fallback option is principally useful for single page applications (SPAs) where the browser may request a file, but where part of the path is in fact an internal route in the application, not a file on disk. goStatic supports two possible usages of this option:
1. Using an absolute path so that all not found requests resolve to the same file
2. Using a relative file, which searches up the tree for the specified file
The second case is useful if you have multiple SPAs within the one filesystem. e.g., */* and */admin*.

View file

@ -3,6 +3,7 @@ package main
import (
"net/http"
"os"
"path"
)
// fallback opens defaultPath when the underlying fs returns os.ErrNotExist
@ -11,10 +12,25 @@ type fallback struct {
fs http.FileSystem
}
func (fb fallback) Open(path string) (http.File, error) {
f, err := fb.fs.Open(path)
if os.IsNotExist(err) {
return fb.fs.Open(fb.defaultPath)
func OpenDefault(fb fallback, requestPath string) (http.File, error) {
requestPath = path.Dir(requestPath)
defaultFile := requestPath + "/" + fb.defaultPath;
f, err := fb.fs.Open(defaultFile)
if os.IsNotExist(err) && requestPath != "" {
parentPath, _ := path.Split(requestPath)
return OpenDefault(fb, parentPath)
}
return f, err
}
func (fb fallback) Open(requestPath string) (http.File, error) {
f, err := fb.fs.Open(requestPath)
if os.IsNotExist(err) {
if len(fb.defaultPath) == 0 || fb.defaultPath[0] == '/' {
return fb.fs.Open(fb.defaultPath)
}
return OpenDefault(fb, requestPath)
}
return f, err
}

View file

@ -15,8 +15,8 @@ var (
// Def of flags
portPtr = flag.Int("port", 8043, "The listening port")
context = flag.String("context", "", "The 'context' path on which files are served, e.g. 'doc' will serve the files at 'http://localhost:<port>/doc/'")
path = flag.String("path", "/srv/http", "The path for the static files")
fallbackPath = flag.String("fallback", "", "Default relative to be used when no file requested found. E.g. /index.html")
basePath = flag.String("path", "/srv/http", "The path for the static files")
fallbackPath = flag.String("fallback", "", "Default fallback file. Either absolute for a specific asset (/index.html), or relative to recursively resolve (index.html)")
headerFlag = flag.String("append-header", "", "HTTP response header, specified as `HeaderName:Value` that should be added to all responses.")
basicAuth = flag.Bool("enable-basic-auth", false, "Enable basic auth. By default, password are randomly generated. Use --set-basic-auth to set it.")
setBasicAuth = flag.String("set-basic-auth", "", "Define the basic auth. Form must be user:password")
@ -49,7 +49,7 @@ func main() {
port := ":" + strconv.FormatInt(int64(*portPtr), 10)
var fileSystem http.FileSystem = http.Dir(*path)
var fileSystem http.FileSystem = http.Dir(*basePath)
if *fallbackPath != "" {
fileSystem = fallback{