Last active
August 9, 2024 06:31
-
-
Save lummie/91cd1c18b2e32fa9f316862221a6fd5c to your computer and use it in GitHub Desktop.
A wrapper for GOs http.FileServer that allows a custom 404 handler to be assigned
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package middleware | |
import ( | |
"net/http" | |
"os" | |
"path" | |
"strings" | |
) | |
// FSHandler404 provides the function signature for passing to the FileServerWith404 | |
type FSHandler404 = func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) | |
/* | |
FileServerWith404 wraps the http.FileServer checking to see if the url path exists first. | |
If the file fails to exist it calls the supplied FSHandle404 function | |
The implementation can choose to either modify the request, e.g. change the URL path and return true to have the | |
default FileServer handling to still take place, or return false to stop further processing, for example if you wanted | |
to write a custom response | |
e.g. redirects to root and continues the file serving handler chain | |
func fileSystem404(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) { | |
//if not found redirect to / | |
r.URL.Path = "/" | |
return true | |
} | |
Use the same as you would with a http.FileServer e.g. | |
r.Handle("/", http.StripPrefix("/", mw.FileServerWith404(http.Dir("./staticDir"), fileSystem404))) | |
*/ | |
func FileServerWith404(root http.FileSystem, handler404 FSHandler404) http.Handler { | |
fs := http.FileServer(root) | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
//make sure the url path starts with / | |
upath := r.URL.Path | |
if !strings.HasPrefix(upath, "/") { | |
upath = "/" + upath | |
r.URL.Path = upath | |
} | |
upath = path.Clean(upath) | |
// attempt to open the file via the http.FileSystem | |
f, err := root.Open(upath) | |
if err != nil { | |
if os.IsNotExist(err) { | |
// call handler | |
if handler404 != nil { | |
doDefault := handler404(w, r) | |
if !doDefault { | |
return | |
} | |
} | |
} | |
} | |
// close if successfully opened | |
if err == nil { | |
f.Close() | |
} | |
// default serve | |
fs.ServeHTTP(w, r) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment