Gorilla/mux SPA无法正确提供静态目录。

huangapple go评论108阅读模式
英文:

Gorilla/mux SPA does not serve static directory correctly

问题

我正在尝试制作一个单页应用的 Web 应用程序,并从 gorilla mux 包中使用了这个示例:https://github.com/gorilla/mux#serving-single-page-applications

但在我进行了一些更改之前,它并没有起作用,就像这里描述的那样:https://github.com/gorilla/mux/issues/588

当我在浏览器中打开某个路径,比如 http://localhost:8080/somepage,它会提供 index.html 和相关的文件(css 和 js)。但是,如果我输入带有另一个斜杠的路径,比如 http://localhost:8080/somepage/smt,它仍然提供 index.html,但是 js 和 css 不起作用,它们的代码被更改为 index.html 中的代码。所以,我的 js 或 css 文件的代码与 index.html 中的代码完全相同。我不知道为什么会这样,也不知道这个包的示例是如何工作的。

这是我的代码:

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) {
        // 如果路径是这样的 http://localhost:8080/any 或 ...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
    }

    // 如果路径只是 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 是 ./,因为如果我的 index.html 在某个文件夹中,这样绝对行不通。

我在 Ubuntu 上使用了这个示例而没有进行任何更改,它运行得很好。可能是因为 filepath 的工作方式不同。但我需要在 Windows 上使用它。

或者,也许还有其他制作单页应用的方法可以在 Go 中实现?

英文:

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

得分: 0

如果请求的文件不存在,你的代码将返回index.html;例如,如果请求的是http://address.com/foo/bar/xxx.html(并且该路径下没有xxx.html文件),那么将返回index.html文件。问题在于,如果index.html中包含<script src="test.js"></script>(或者src=./test.js),那么脚本标签将导致浏览器请求http://address.com/foo/bar/test.js(因为路径是相对路径,原始请求的路径是/foo/bar/),这将不会返回预期的文件(因为请求的文件不存在,将返回index.html)。

将你的HTML更改为使用绝对路径(例如<script src="/test.js"></script>)意味着无论原始请求路径如何,都将请求正确的JavaScript(或其他文件类型)。

英文:

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.

huangapple
  • 本文由 发表于 2021年3月7日 02:35:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/66509304.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定