英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论