I'm trying to make an SPA web app and took this sample from the gorilla mux package https://github.com/gorilla/mux#serving-single-page-applications But it didn't work before I made some changes in path like it described there https://github.com/gorilla/mux/issues/588
When I open in browser some path http://localhost:8080/somepage it serves the index.html and related files(css and js). But if I enter path with another slash e.g http://localhost:8080/somepage/smt it also serves index.html but js and css don't work, and theirs code is changed to the code which is in index.html. So I have my js or css file with exact same code as in index.html. I have no idea why it is and how the sample of the package works.
Here is my code
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path, err := filepath.Abs(r.URL.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
path = filepath.Join(h.staticPath, r.URL.Path)
_, err = os.Stat(path)
if os.IsNotExist(err) {
//this called if the path is like that http://localhost:8080/any or ...any/somesubpage
http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
return
} else if err != nil {
fmt.Println("500")
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
//this called if the path is just http://localhost:8080
http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
}
func main() {
router := mux.NewRouter()
//api handlers
spa := spaHandler{staticPath: "./", indexPath: "index.html"}
router.PathPrefix("/").Handler(spa)
srv := &http.Server{
Handler: router,
Addr: "127.0.0.1:8080",
}
log.Fatal(srv.ListenAndServe())
}
staticPath is ./ because if my index.html is in some folder this absolutely won't work.
I used this sample in Ubuntu without changes and it worked well. Maybe because of differences in working of filepath. But I need it on Windows.
Or maybe there are other ways of making spa in go?
Your code will return index.html
if the requested file does not exist; for example if the request is for http://address.com/foo/bar/xxx.html
(and there is no xxx.html
in that path) then the index.html
file will be returned. The issue is that if index.html
includes <script src="test.js"></script>
(or src=./test.js
) then the script tag will result in the browser requesting http://address.com/foo/bar/test.js
(because the path is relative and the path of the original request was /foo/bar/
) and this will not return the expected file (index.html
will be returned because the requested file does not exist!).
Changing your html to an use absolute path (e.g. <script src="/test.js"></script>
) means the correct javascript (or other file type) will be requested regardless of the original request path.