【问题标题】:Cookie set and not detectedCookie 已设置但未检测到
【发布时间】: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
  • 您在任何时候是否有不同的(例如,不是临时的)重定向代码?对我来说,这听起来很像您在某个时候进行了永久重定向,现在您的浏览器已经缓存了该响应。

标签: http go cookies


【解决方案1】:

您的代码的问题在于它为处理函数构建了糟糕的闭包。如果您不使用无法控制的变化(在这种情况下通过循环)变量来构建闭包,这将有所帮助。您可以添加以下代码行来解决问题:

    for k, v := range pages {
        k, v := k, v // <-- this line

这样,每个处理函数都会有自己的一组外部变量。

说实话,我真的不明白你最初的问题是什么。这是什么意思——“一个 cookie 是……未检测到”?

【讨论】:

    猜你喜欢
    • 2015-07-04
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    相关资源
    最近更新 更多