Golang Gorilla mux与http.FileServer返回404错误。

huangapple go评论90阅读模式
英文:

Golang Gorilla mux with http.FileServer returning 404

问题

我看到的问题是,我正在尝试使用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服务器程序,展示了这个问题:

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)
	//
	// 下一行,图像路由处理程序导致test.png图像返回404。
	// myRouter.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))
	//
	myRouter.Host("mydomain.com")
	http.Handle("/", myRouter)

	// 这种设置图像路由处理程序的方法可以正常工作。
	// test.png图像显示正常。
	http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(HomeFolder + "images/"))))

	// HTTP - 端口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" height="640" width="480">
	</p>
  </body>
</html>
`
英文:

The problem I'm seeing is that I'm trying to use the http.FileServer with the Gorilla mux Router.Handle function.

This doesn't work (the image returns a 404)..

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

this works (the image is shown ok)..

http.Handle(&quot;/images/&quot;, http.StripPrefix(&quot;/images/&quot;, http.FileServer(http.Dir(HomeFolder + &quot;images/&quot;))))

Simple go web server program below, showing the problem...

package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;io&quot;
	&quot;log&quot;
	&quot;github.com/gorilla/mux&quot;
)

const (
	HomeFolder = &quot;/root/test/&quot;
)

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

func main() {

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

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

	// HTTP - port 80
	err := http.ListenAndServe(&quot;:80&quot;, nil)
	
	if err != nil {
		log.Fatal(&quot;ListenAndServe: &quot;, err)
		fmt.Printf(&quot;ListenAndServe:%s\n&quot;, err.Error())
	}
}

const htmlContents = `&lt;!DOCTYPE HTML&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
	&lt;title&gt;Test page&lt;/title&gt;
	&lt;meta charset = &quot;UTF-8&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
	&lt;p align=&quot;center&quot;&gt;
		&lt;img src=&quot;/images/test.png&quot; height=&quot;640&quot; width=&quot;480&quot;&gt;
	&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;
`

答案1

得分: 68

我在golang-nuts讨论组上发布了这个问题,并从Toni Cárdenas那里得到了这个解决方案...

标准的net/http ServeMux(在使用http.Handle时使用的标准处理程序)和mux Router在匹配地址时有不同的方式。

请参阅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/"))))
英文:

I posted this on golang-nuts discussion group and got this solution from Toni Cárdenas ...

The standard net/http ServeMux (which is the standard handler you are using when you use http.Handle) and the mux Router have different ways of matching an address.

See the differences between http://golang.org/pkg/net/http/#ServeMux and http://godoc.org/github.com/gorilla/mux.

So basically, <code>http.Handle('/images/', ...)</code> matches '/images/whatever', while <code>myRouter.Handle('/images/', ...)</code> only matches '/images/', and if you want to handle '/images/whatever', you have to ...

Option 1 - Use a regular expression match in your router

myRouter.Handle(&quot;/images/{rest}&quot;,
     http.StripPrefix(&quot;/images/&quot;, http.FileServer(http.Dir(HomeFolder + &quot;images/&quot;))))

Option 2 - Use the PathPrefix method on your router:

myRouter.PathPrefix(&quot;/images/&quot;).Handler(http.StripPrefix(&quot;/images/&quot;, 
     http.FileServer(http.Dir(HomeFolder + &quot;images/&quot;))))

答案2

得分: 0

截至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包装到gorilla/handler的日志记录器中,查看请求进入FileServer和响应404离开的情况。

ui := handlers.CombinedLoggingHandler(os.Stderr, http.FileServer(http.Dir("ui")))
myRouter.Handle("/ui/", ui) // 得到404
// 使用strip可以正常工作:myRouter.Handle("/ui/", http.StripPrefix("/ui/", ui))
英文:

As of May 2015 gorilla/mux package still have no version releases. But problem is different now. It is not that myRouter.Handle does not match url and needs regexp, it does! But http.FileServer requires prefix to be removed from url. Below example works fine.

ui := http.FileServer(http.Dir(&quot;ui&quot;))
myRouter.Handle(&quot;/ui/&quot;, http.StripPrefix(&quot;/ui/&quot;, ui))

Note, there is no /ui/{rest} in abowe example. You may also wrap http.FileServer into logger gorilla/handler and see request to coming to FileServer and response 404 going out.

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

huangapple
  • 本文由 发表于 2014年1月20日 20:50:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/21234639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定