Gorilla Mux路由器在处理程序内部只能工作一次,然后显示404页面未找到。

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

Gorilla Mux router from inside handler only works once then gives 404 page not found

问题

我正在使用Gorilla mux作为我的路由器,但是我遇到了一个非常奇怪的问题。在第一次请求服务器时,我得到了一个有效的响应。但是在后续的请求中,我收到了一个404页面未找到的错误。控制台中没有错误信息。

我的代码非常简单(可以直接复制粘贴进行测试):

package main

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

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/", RootHandler).Name("root")
	http.Handle("/", router)

	log.Println("Listening on port 1337...")
	if err := http.ListenAndServe(":1337", nil); err != nil {
		log.Fatal("http.ListenAndServe: ", err)
	}
}

func RootHandler(w http.ResponseWriter, r *http.Request) {
	content := "Welcome to "
	rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()
	if err != nil {
		log.Printf("mux.CurrentRoute(r).Subrouter().Get(\"root\").URL(): ", err)
	}
	response := content + rootUrl.String()
	fmt.Fprintf(w, response)
}

经过一些代码注释和测试,似乎以下这行代码有问题:

rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()

在处理程序中使用当前请求获取路由器的方法来自于另一个StackOverflow帖子:https://stackoverflow.com/questions/23553061/how-to-call-a-route-by-its-name-from-inside-a-handler

但是由于某种奇怪的原因,它只能工作一次:

shell-1$ go run servertest.go
2014/10/30 13:31:34 Listening on port 1337...

shell-2$ curl http://127.0.0.1:1337
Welcome to /
shell-2$ curl http://127.0.0.1:1337
404 page not found

如你所见,控制台中没有错误信息。

有人知道为什么它只能工作一次吗?

英文:

I'm using Gorilla mux as my router and I'm having a very strange behaviour. On the first request to the server, I get a valid response. But on subsequent requests, I receive a 404 page not found. There are no errors in the console.

My code is pretty straightforward (it can be copy-pasted to test it right out):

package main

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

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/", RootHandler).Name("root")
	http.Handle("/", router)

	log.Println("Listening on port 1337...")
	if err := http.ListenAndServe(":1337", nil); err != nil {
		log.Fatal("http.ListenAndServe: ", err)
	}
}

func RootHandler(w http.ResponseWriter, r *http.Request) {
	content := "Welcome to "
	rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()
	if err != nil {
		log.Printf("mux.CurrentRoute(r).Subrouter().Get(\"root\").URL(): ", err)
	}
	response := content + rootUrl.String()
	fmt.Fprintf(w, response)
}

After some code commenting and tests, it seems the following line is the culprit:

rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()

This method of getting the router inside the handler using the current request comes from another StackOverflow post: https://stackoverflow.com/questions/23553061/how-to-call-a-route-by-its-name-from-inside-a-handler

But for a strange reason, it only works once:

shell-1$ go run servertest.go
2014/10/30 13:31:34 Listening on port 1337...

shell-2$ curl http://127.0.0.1:1337
Welcome to /
shell-2$ curl http://127.0.0.1:1337
404 page not found

As you can see, there are no errors in the console.

Does someone have an idea of why it only works once ?

答案1

得分: 2

问题是Subrouter()不是用来返回路由器的,而是用来创建一个路由器,因此它会改变调用它的路由器的匹配器,导致你丢失处理程序。

你可以尝试使用闭包将路由器传递给处理程序。

func RootHandler(router *mux.Router) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        ...
    }
}
英文:

The problem is Subrouter() isn't made to return the router, but to create one, thus it changes the matcher of the router it is called on, making you lose the handler.

You could try passing the router to the handler using closures instead.

func RootHandler(router *mux.Router) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		...
	}
}

答案2

得分: 0

我遇到了这个问题,并通过重新初始化方法来解决它:

// 单独创建一个子路由器
subRoute := mux.CurrentRoute(req).Subrouter()

// 调用你想要的路由,并存储URL
url, err := subRoute.Get("check_authorization").URL("id", key, "password", token)

// 重新初始化方法为GET或者之前使用的任何方法
subRoute.Methods(http.MethodGet)

希望对你有帮助!

英文:

i run to this problem and fixe it by re initiating the methods

//create a subrouter separately \
subRoute := mux.CurrentRoute(req).Subrouter() \
//Call the Route u want and store the URL 
url, err := subRoute.Get("check_authorization").URL("id", key, "password", token) 
// re-initiate the method to GET or whatever u had before 
subRoute.Methods(http.MethodGet) 

huangapple
  • 本文由 发表于 2014年10月30日 20:34:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/26653152.html
匿名

发表评论

匿名网友

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

确定