I'm having issues with how browser resolves relative path to scripts. The setup is that I have simple go server that serves one html page from root "/" location, the html page contains script tag with relative path to script (the path = "./script.js"). Then, I have a reverse proxy that proxies that server but from location "/hello". The problem I'm facing is that browser resolves path "./script.js" in that html page as "/script.js", which then doesn't go through the proxy, since I proxy at "/hello" and not root.
The question is why ? If the path is relative, shouldn't that mean that if for browser we are at "/hello" then "./script.js" should become "/hello/script.js" ? How do I fix it ?
here's how reverse proxy is set up:
targetURL, _ := url.Parse("https://127.0.0.1:12345")
proxy := httputil.NewSingleHostReverseProxy(targetURL)
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
log.Printf("hello request URL: %s\n", r.URL)
proxy.ServeHTTP(w, r)
log.Printf("hello response: %+v\n", w)
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
log.Printf("root request URL: %s\n", r.URL)
log.Printf("root request: %+v\n", r)
})
proxy.Director = func(req *http.Request) {
req.URL.Scheme = targetURL.Scheme
req.URL.Host = targetURL.Host
req.Host = req.URL.Host // preserve the original Host
req.Header.Del("If-None-Match")
req.Header.Del("If-Modified-Since")
req.Header.Set("Accept-Encoding", "")
if strings.Contains(req.URL.Path, "/hello") {
req.URL.Path = strings.Replace(req.URL.Path, "/hello", "/", 1)
fmt.Printf("replaced: %s\n", req.URL.Path)
}
}
log.Fatal(http.ListenAndServe(":4321", nil))
Here I replace the "/hello" prefix before sending request to the target along with changing host. Also, I print if there are requests through the root, just to debug if any (and there are for idk the reason, script.js request goes through the root instead of /hello)
And here's the proxied server:
func HelloServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/html")
t := template.New("test")
t, _ = template.ParseFiles("page.html")
t.Execute(w, "")
}
func main() {
http.HandleFunc("/", HelloServer)
err := http.ListenAndServeTLS(":12345", "combined.pem", "kk.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
in which just one page.html is served from root.
The page.html that contains relative path to the script:
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./script.js" charset="UTF-8"> </script>
</body>
</html>
I've checked the proxied server on browser "http://127.0.0.1:4321/hello" (Google chrome/Safari), in dev tools I see that html page is loaded, but path to "./script.js" is "http://127.0.0.1:4321/script.js", without the prefix...