【发布时间】:2021-12-25 04:17:08
【问题描述】:
我正在构建一个将使用许多路由的网站,因此我不想要单独的处理程序。我的解决方案是遍历端点列表。 当我这样做时,设置了一个 cookie 但未检测到。下面的代码可以复制粘贴,只需cmets/uncomment两个路由系统即可。
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
)
var tmpl *template.Template
const testCookieName = "testCookieName"
const testCookievalue = "testCookievalue"
func main(){
port :=":8088"
router := mux.NewRouter()
router.Use(middlewareSetCookie)
router.Use(middlewareCheckCookies)//no cookie sends page to /cookie for an error msg
router.Use(middlewareNoWWW)
router.Use(middlewareHeaders)
//Using individual routes works as expected and a cookie is set and detected.
/*
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, "index", "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
router.HandleFunc("/cookie", func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, "cookie", "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
*/
//Given the number of routes I need I have to use a loop to iterate over all to keep the code base maintanable
//The cookie is set but not detected in the code below
/**/
pages := make(map[string]string)
pages["/"] = "index"
pages["/cookie"] = "cookie"
for k, v :=range pages{
router.HandleFunc(k, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, v, "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}
var err error
tmpl, err = template.ParseGlob("views/*")
if err != nil {
panic(err.Error())
}
router.PathPrefix("/").HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
http.FileServer(http.Dir("./static/")).ServeHTTP(res, req)
})
fmt.Println("Server running on localhost" + port)
err = http.ListenAndServe(port, handlers.CompressHandler(router))
if err != nil {
log.Fatal(err)
}
}
func middlewareNoWWW(next http.Handler) http.Handler {
fmt.Println("middlewareNoWWW")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Host[0:4] == "www." {
target := "http://" + r.Host[4:]
http.Redirect(w, r, target, 301)
}
next.ServeHTTP(w, r)
})
}
func middlewareHeaders(next http.Handler) http.Handler {
fmt.Println("middlewareHeaders")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains; preload")
next.ServeHTTP(w, r)
})
}
func middlewareSetCookie(next http.Handler) http.Handler {
fmt.Println("middlewareSetCookie")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie(testCookieName)
if err != nil || c.Value != testCookievalue {
cookie := http.Cookie{
Name: testCookieName,
Value: testCookievalue,
Path: "/",
HttpOnly: true,
MaxAge: 0,
Domain: "localhost"}
http.SetCookie(w, &cookie)
}
next.ServeHTTP(w, r)
})
}
func middlewareCheckCookies(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("middlewareCheckCookies")
fmt.Println(r.URL.String())
c, err := r.Cookie(testCookieName)
if err != nil || c.Value != testCookievalue {
redirectURL := "/cookie"
if r.URL.String() != redirectURL {
http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
return
}
}
next.ServeHTTP(w, r)
})
}
./views/cookie.html
{{define "cookie"}}no cookie set<a href="/">index</a>{{end}}
./views/index.html
{{define "index"}}<a href="/">index</a>{{end}}
有解决这个问题的线索吗?
【问题讨论】:
-
在调用 http.Redirect 后,有几个地方函数会继续正常流程。写入重定向标头后从函数返回。
-
添加了退货但问题仍然存在。
-
修复所有对 http.Redirect 的调用的问题。尝试从 cookie 中删除域。另请注意,SetCookie 设置响应标头,Request.Cookie 获取请求标头。在以后的请求之前,您不能期望看到 SetCookie 的结果。
-
我刚刚测试,我可以看到 cookie 值,我错过了什么吗? ibb.co/BsLmjF2
-
您在任何时候是否有不同的(例如,不是临时的)重定向代码?对我来说,这听起来很像您在某个时候进行了永久重定向,现在您的浏览器已经缓存了该响应。