过滤embed.FS导致HTTP服务器出现ERR_TOO_MANY_REDIRECTS错误如何解决
问题原因
核心冲突是http.FileServer的默认重定向逻辑和你自定义fs.FS实现的返回结果不匹配:
http.FileServer处理请求时,会先将URL路径转为文件系统的查询名称,再调用Open方法获取文件,随后通过Stat()方法判断返回的是目录还是文件。- 你实现的
primaryFiles仅处理name="."的查询,当访问/index.html时,对应查询名称是index.html,你的实现直接返回fs.ErrNotExist,会触发FileServer的路径校正重定向逻辑。 - 当访问
/时,你返回的是index.html的文件句柄,其Stat()结果是文件而非目录,和/路径默认对应的目录属性冲突,导致FileServer计算重定向路径时逻辑异常,生成了..//这种错误的目标地址,最终引发循环重定向。
修复方案
这里提供两种实现简单的修复方式,按需选择即可:
方案1:单独处理根路径请求(更推荐,逻辑清晰无歧义)
不需要自定义fs.FS,直接为根路径编写单独的处理逻辑,仅在请求路径为/时返回index.html,其他根路径下的请求直接返回404:
package main import ( "net/http" "embed" "log" ) //go:embed index.html var files embed.FS func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // 仅匹配根路径,避免匹配所有子路径 if r.URL.Path != "/" { http.NotFound(w, r) return } // 直接读取embed的index.html返回 content, err := files.ReadFile("index.html") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Write(content) }) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(files)))) log.Fatal(http.ListenAndServe(":8080", nil)) }
方案2:修正自定义fs的实现
如果你希望继续使用http.FileServer处理根路径,只需要扩展primaryFiles的Open逻辑,同时处理"."和"index.html"两个查询名称即可:
type primaryFiles struct {} func (pf *primaryFiles) Open(name string) (fs.File, error) { switch name { case ".", "index.html": return files.Open("index.html") default: return nil, fs.ErrNotExist } }
修改后/和/index.html都能正确返回内容,不会触发异常重定向。
内容的提问来源于stack exchange,提问作者flyx
相关产品推荐
相关产品推荐

