0
votes

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?

1
Please show how index.html is referencing the js/css files. I'd guess you are using relative paths (if so adding a / at the front should fix your issue).Brits
@Brits I removed the dot from the beginning of link and it worked. Thank you. <link rel="stylesheet" href="./client/style.css" type="text/css"/> to <link rel="stylesheet" href="/client/style.css" type="text/css"/>. Can you please explain why it works so?IDarar

1 Answers

0
votes

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.