Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions internal/webserver/Webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ import (
"github.com/forceu/gokapi/internal/webserver/ssl"
)

// TODO add 404 handler

// staticFolderEmbedded is the embedded version of the "static" folder
// This contains JS files, CSS, images etc
//
Expand Down Expand Up @@ -175,8 +173,39 @@ func filesystemHandler(webserverDir fs.FS) http.HandlerFunc {
return
}
addCacheHeader(w)
http.FileServer(http.FS(webserverDir)).ServeHTTP(w, r)
nfw := &notFoundInterceptor{ResponseWriter: w}
http.FileServer(http.FS(webserverDir)).ServeHTTP(nfw, r)
if nfw.intercepted {
// The response was cached as servable content above; a 404 means that
// assumption was wrong, so undo it before showing the error page.
w.Header().Del("cdn-cache-control")
w.Header().Del("Cloudflare-CDN-Cache-Control")
w.Header().Del("cache-control")
errorHandling.RedirectGenericErrorPage(w, r, errorHandling.TypeFileNotFound)
}
}
}

// notFoundInterceptor suppresses http.FileServer's built-in 404 response, so that a
// styled Gokapi error page can be shown instead of the plain stdlib fallback page.
type notFoundInterceptor struct {
http.ResponseWriter
intercepted bool
}

func (nfw *notFoundInterceptor) WriteHeader(statusCode int) {
if statusCode == http.StatusNotFound {
nfw.intercepted = true
return
}
nfw.ResponseWriter.WriteHeader(statusCode)
}

func (nfw *notFoundInterceptor) Write(b []byte) (int, error) {
if nfw.intercepted {
return len(b), nil
}
return nfw.ResponseWriter.Write(b)
}

func handleFavicon(w http.ResponseWriter, r *http.Request) {
Expand Down
8 changes: 8 additions & 0 deletions internal/webserver/Webserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ func TestStaticDirs(t *testing.T) {
RequiredContent: []string{".btn-secondary:hover"},
})
}
func TestStaticFileNotFound(t *testing.T) {
t.Parallel()
test.HttpPageResult(t, test.HttpTestConfig{
Url: "http://localhost:53843/this/file/does/not/exist.xyz",
RedirectUrl: "error",
IgnoreRedirectParm: true,
})
}

func postValues(username, password, csrf string) []test.PostBody {
return []test.PostBody{
Expand Down
Loading