You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反向代理时脚本相对路径解析异常问题排查与修复

浏览器解析相对路径异常:./script.js 被解析为 /script.js 的问题与修复

问题场景

我用Go搭建了反向代理,从/hello路径代理后端Go服务器;后端服务器从根路径/提供HTML页面,页面中script标签使用相对路径./script.js。但访问http://127.0.0.1:4321/hello时,浏览器将./script.js解析为/script.js,导致请求走根路径而非代理的/hello路径,无法正确获取资源。

疑问:按道理,浏览器在/hello路径下,./script.js应该解析成/hello/script.js才对?

问题根源

浏览器解析相对路径的规则是基于当前页面URL的路径层级判定:

  • 如果URL路径末尾带斜杠(比如/hello/),浏览器会认为这是一个目录,相对路径./script.js会解析为/hello/script.js
  • 如果URL路径末尾不带斜杠(比如/hello),浏览器会把hello当作一个文件,相对路径./script.js会解析为和该文件同级的路径,也就是/script.js

你的场景中,访问的是无末尾斜杠的/hello,浏览器将hello视为文件,因此相对路径直接指向根目录下的script.js。

修复方案

方案1:代理自动重定向到带末尾斜杠的路径

在反向代理的/hello处理函数中,检查请求路径是否带末尾斜杠,无斜杠则重定向到/hello/,同时调整路径替换逻辑兼容新路径:

http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
    // 无末尾斜杠时重定向
    if r.URL.Path == "/hello" {
        http.Redirect(w, r, "/hello/", http.StatusPermanentRedirect)
        return
    }
    log.Printf("hello request URL: %s\n", r.URL)
    proxy.ServeHTTP(w, r)
    log.Printf("hello response: %+v\n", w)
})

// 调整Director中的路径替换逻辑
proxy.Director = func(req *http.Request) {
    req.URL.Scheme = targetURL.Scheme
    req.URL.Host = targetURL.Host
    req.Host = req.URL.Host

    req.Header.Del("If-None-Match")
    req.Header.Del("If-Modified-Since")
    req.Header.Set("Accept-Encoding", "")

    // 兼容/hello和/hello/两种路径
    if strings.HasPrefix(req.URL.Path, "/hello/") {
        req.URL.Path = strings.Replace(req.URL.Path, "/hello/", "/", 1)
    } else if req.URL.Path == "/hello" {
        req.URL.Path = "/"
    }
    fmt.Printf("replaced: %s\n", req.URL.Path)
}

用户访问/hello时会自动跳转到/hello/,浏览器会正确解析相对路径。

方案2:在HTML中添加<base>标签

在页面<head>中添加<base>标签,指定所有相对路径的基准URL:

<head>
    <meta charset="UTF-8">
    <title>Swagger UI</title>
    <base href="/hello/">
</head>

无论页面URL是否带末尾斜杠,浏览器都会基于/hello/解析所有相对路径,./script.js会直接解析为/hello/script.js。

方案3:修改script路径为绝对路径

直接将script的src改为代理路径下的绝对路径:

<script src="/hello/script.js" charset="UTF-8"> </script>

这种方法简单直接,但如果代理路径(如/hello)后续需要修改,需同步调整HTML路径,灵活性较差。

方案4:代理拦截根路径静态资源请求

如果不想修改前端和访问路径,可在代理中拦截根路径的静态资源请求,转发到后端服务器:

// 单独处理script.js请求
http.HandleFunc("/script.js", func(w http.ResponseWriter, r *http.Request) {
    r.URL.Path = "/script.js"
    proxy.ServeHTTP(w, r)
})

此方法需为每个静态资源单独配置,适合资源数量少的场景。

内容的提问来源于stack exchange,提问作者oyevtushe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 17:40:18