Golang Gorilla mux 与 http.FileServer 返回 404

Posted

技术标签:

【中文标题】Golang Gorilla mux 与 http.FileServer 返回 404【英文标题】:Golang Gorilla mux with http.FileServer returning 404 【发布时间】:2014-02-09 15:51:07 【问题描述】:

我看到的问题是我正在尝试将 http.FileServer 与 Gorilla mux Router.Handle 函数一起使用。

这不起作用(图像返回 404)..

myRouter := mux.NewRouter()
myRouter.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

这行得通(图像显示正常)..

http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

下面是简单的go web server程序,显示问题...

package main

import (
    "fmt"
    "net/http"
    "io"
    "log"
    "github.com/gorilla/mux"
)

const (
    HomeFolder = "/root/test/"
)

func HomeHandler(w http.ResponseWriter, req *http.Request) 
    io.WriteString(w, htmlContents)


func main() 

    myRouter := mux.NewRouter()
    myRouter.HandleFunc("/", HomeHandler)
    //
    // The next line, the image route handler results in 
    // the test.png image returning a 404.
    // myRouter.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
    //
    myRouter.Host("mydomain.com")
    http.Handle("/", myRouter)

    // This method of setting the image route handler works fine.
    // test.png is shown ok.
    http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

    // HTTP - port 80
    err := http.ListenAndServe(":80", nil)

    if err != nil 
        log.Fatal("ListenAndServe: ", err)
        fmt.Printf("ListenAndServe:%s\n", err.Error())
    


const htmlContents = `<!DOCTYPE HTML>
<html lang="en">
  <head>
    <title>Test page</title>
    <meta charset = "UTF-8" />
  </head>
  <body>
    <p align="center">
        <img src="/images/test.png"  >
    </p>
  </body>
</html>
`

【问题讨论】:

【参考方案1】:

我在 golang-nuts 讨论组上发布了这个并得到了this solution from Toni Cárdenas ...

标准的 net/http ServeMux(这是您在使用 http.Handle 时使用的标准处理程序)和 mux 路由器具有不同的地址匹配方式。

查看http://golang.org/pkg/net/http/#ServeMux 和http://godoc.org/github.com/gorilla/mux 之间的区别。

所以基本上,http.Handle('/images/', ...) 匹配'/images/whatever',而myRouter.Handle('/images/', ...) 匹配'/images/',如果你想处理'/images/whatever',你必须...

选项 1 - 在路由器中使用正则表达式匹配

myRouter.Handle("/images/rest",
     http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

选项 2 - 在路由器上使用 PathPrefix 方法:

myRouter.PathPrefix("/images/").Handler(http.StripPrefix("/images/", 
     http.FileServer(http.Dir(HomeFolder + "images/"))))

【讨论】:

+1 #2 在我当前的项目中已经成功(在我偶然发现这个答案之前。只是向读者保证 #2 是我正在使用和工作的)。跨度> 只是补充说明,请记住,如果你是像我这样的 golang 新手,golang 不喜欢 #2 中格式化的语句。我需要在 golang 停止抱怨期待逗号之前将所有三行合并为一行(语法没有变化,只有空格的变化)。 #2 是正确的答案,它只是以这样的方式形成,会给像我这样的新手和新手带来问题。 你说得对,我不得不把 make 语句放在一行。 非常感谢您让我摆脱了数小时的痛苦,PathPrefix 和 StripPrefix 对我有用,我从 r.Handle("/", fs) 转到 r.PathPrefix("/").Handler(http.StripPrefix("/", fs)) @SamGamgee - 你可以更进一步,删除http.StripPrefix(),这样你最终会得到r.PathPrefix("/").Handler(fs)【参考方案2】:

截至 2015 年 5 月,gorilla/mux 软件包仍然没有版本发布。但现在问题不同了。并不是myRouter.Handle 不匹配 url 并且需要正则表达式,它确实如此!但是http.FileServer 需要从 url 中删除前缀。下面的示例运行良好。

ui := http.FileServer(http.Dir("ui"))
myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))

注意,上面的示例中没有 /ui/rest。您也可以将 http.FileServer 包装到 logger gorilla/handler 中,然后查看请求进入 FileServer 和响应 404 出去。

ui := handlers.CombinedLoggingHandler(os.Stderr,http.FileServer(http.Dir("ui"))
myRouter.Handle("/ui/", ui) // getting 404
// works with strip: myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))

【讨论】:

router 的默认Handle 方法仍然像以前一样创建route。我尝试了你上面所说的方法,"/ui/" 不会匹配所有带有"/ui/" 前缀的路径。 @dodgy_coder 的解决方案是正确的。使用默认的Handler 方法包含正则表达式或使用PathPrefix

以上是关于Golang Gorilla mux 与 http.FileServer 返回 404的主要内容,如果未能解决你的问题,请参考以下文章

gorilla/mux 的学习

GoLang/Mux 语法问题:if ID, Ok = mux.Vars(r)["ID"]; !行

golang http 恐慌的全局恢复处理程序

GolangWeb 入门 08 集成 Gorilla Mux

GolangWeb 入门 08 集成 Gorilla Mux

go 常见外部包解析