49 lines
957 B
Go
49 lines
957 B
Go
package xhttp
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
const basename = "/"
|
|
|
|
type NotFoundHandler struct {
|
|
fs http.FileSystem
|
|
fileServer http.Handler
|
|
}
|
|
|
|
func NewNotFoundHandler(fs http.FileSystem) NotFoundHandler {
|
|
return NotFoundHandler{
|
|
fs: fs,
|
|
fileServer: http.FileServer(fs),
|
|
}
|
|
}
|
|
|
|
func (n NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if strings.HasPrefix(r.URL.Path, "/api/") {
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
filePath := strings.TrimPrefix(path.Clean(r.URL.Path), basename)
|
|
if len(filePath) == 0 {
|
|
filePath = basename
|
|
}
|
|
|
|
file, err := n.fs.Open(filePath)
|
|
switch {
|
|
case err == nil:
|
|
n.fileServer.ServeHTTP(w, r)
|
|
_ = file.Close()
|
|
return
|
|
case os.IsNotExist(err):
|
|
r.URL.Path = "/" // all virtual routes in react app means visit index.html
|
|
n.fileServer.ServeHTTP(w, r)
|
|
return
|
|
default:
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
}
|