Golang中URL尾部斜杠导致CSS/JS无法加载的问题

Golang中URL尾部斜杠导致CSS/JS无法加载的问题 我遇到了一个问题:当URL路径末尾添加斜杠时,静态资源无法加载。

https://static.go4webdev.org/why (工作正常) SVG文件的路径将是 /icn/meatballs.svg

https://static.go4webdev.org/why/ (无法加载CSS/JS等) SVG文件的路径将是 why/icn/meatballs.svg

这在一定程度上破坏了指向公共文件夹中某些资源的路径。

func init() {
	tpl = template.Must(template.ParseGlob("public/tmpl/*.html"))
	http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("./public/img"))))
	http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./public/css"))))
	http.Handle("/icn/", http.StripPrefix("/icn/", http.FileServer(http.Dir("./public/icn"))))
	http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./public/js"))))
	http.Handle("/mov/", http.StripPrefix("/mov/", http.FileServer(http.Dir("./public/mov"))))
	http.Handle("/misc/", http.StripPrefix("/misc/", http.FileServer(http.Dir("./public/misc"))))
}

有什么办法可以正确加载页面吗?


更多关于Golang中URL尾部斜杠导致CSS/JS无法加载的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

HTML中相对路径的工作原理是这样的(这是浏览器的问题,不是Go语言的问题)。存在以下几种可能的解决方案(顺序是随机的,只是我想到的顺序,不代表任何偏好):

  1. 对资源使用绝对路径而非相对路径
  2. 始终将带尾部斜杠的路径重定向到不带尾部斜杠的路径,并相应地编写资源引用
  3. 始终将不带尾部斜杠的路径重定向到带尾部斜杠的路径,并相应地编写资源引用
  4. 设置一个 <base> 标签,并相应地编写资源引用

更多关于Golang中URL尾部斜杠导致CSS/JS无法加载的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这个问题是由于相对路径解析导致的。当URL以斜杠结尾时,浏览器会将相对路径解析为相对于当前目录,而不是相对于根目录。

解决方案是使用绝对路径或添加<base>标签。以下是两种实现方式:

方案一:在HTML模板中使用绝对路径

// 在模板中使用绝对路径
<link rel="stylesheet" href="/css/style.css">
<script src="/js/app.js"></script>
<img src="/img/logo.png">

方案二:在模板中添加base标签

// 在HTML模板的<head>中添加
<base href="/">

// 或者在Go代码中动态设置
func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
    // 设置base URL
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    
    // 解析并执行模板
    err := tpl.ExecuteTemplate(w, tmpl+".html", data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

方案三:使用URL重写(更彻底的解决方案)

func init() {
    // 静态文件服务配置保持不变
    http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("./public/img"))))
    http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./public/css"))))
    http.Handle("/icn/", http.StripPrefix("/icn/", http.FileServer(http.Dir("./public/icn"))))
    http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./public/js"))))
    
    // 主处理器,移除尾部斜杠
    http.HandleFunc("/why", func(w http.ResponseWriter, r *http.Request) {
        // 如果请求以斜杠结尾,重定向到没有斜杠的版本
        if r.URL.Path == "/why/" {
            http.Redirect(w, r, "/why", http.StatusMovedPermanently)
            return
        }
        
        // 正常处理请求
        err := tpl.ExecuteTemplate(w, "why.html", nil)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    })
}

方案四:使用中间件统一处理尾部斜杠

func RemoveTrailingSlash(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 保留根路径的斜杠,移除其他路径的尾部斜杠
        if r.URL.Path != "/" && strings.HasSuffix(r.URL.Path, "/") {
            http.Redirect(w, r, strings.TrimSuffix(r.URL.Path, "/"), http.StatusMovedPermanently)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 使用中间件
func main() {
    // 配置静态文件服务...
    
    // 包装处理器
    handler := RemoveTrailingSlash(http.DefaultServeMux)
    
    http.ListenAndServe(":8080", handler)
}

推荐使用方案一或方案三。方案一最简单直接,方案三可以统一URL格式,避免重复内容问题。

回到顶部