49 lines
1.0 KiB
Go
49 lines
1.0 KiB
Go
package httpx
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"os"
|
||
|
|
"path"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
const basename = "/"
|
||
|
|
|
||
|
|
type NotFoundHandler struct {
|
||
|
|
fs http.FileSystem
|
||
|
|
fileServer http.Handler
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewNotFoundHandler 静态资源服务:命中即返回文件,否则回退到 index.html(前端 SPA 路由)
|
||
|
|
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 = "/" // vue app 虚拟路由统一回 index.html
|
||
|
|
n.fileServer.ServeHTTP(w, r)
|
||
|
|
return
|
||
|
|
default:
|
||
|
|
http.Error(w, "not found", http.StatusNotFound)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|