Cookie已设置但未检测到。

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

Cookie set and not detected

问题

我正在构建一个网站,将使用许多路由,因此我不想使用单独的处理程序。我的解决方案是迭代一个端点列表。

当我这样做时,会设置一个cookie,但无法检测到。下面的代码可以复制并粘贴,只需注释/取消注释两个路由系统。

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}}

有什么解决方法吗?

英文:

I am building a website that will use many routes and because of this I don't want individual handlers. My solution is to iterate over a list of endpoints.
When I do this a cookie is set but not detected. The code below can be copy and pasted, just comments/uncomment the two route systems.

package main
import (
&quot;fmt&quot;
&quot;html/template&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;github.com/gorilla/handlers&quot;
&quot;github.com/gorilla/mux&quot;
)
var tmpl *template.Template
const testCookieName = &quot;testCookieName&quot;
const testCookievalue = &quot;testCookievalue&quot;
func main(){
port :=&quot;:8088&quot;
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(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, &quot;index&quot;, &quot;&quot;)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
router.HandleFunc(&quot;/cookie&quot;, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, &quot;cookie&quot;, &quot;&quot;)
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[&quot;/&quot;] = &quot;index&quot;
pages[&quot;/cookie&quot;] = &quot;cookie&quot;
for k, v :=range pages{
router.HandleFunc(k, func(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, v, &quot;&quot;)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
})
}
var err error
tmpl, err = template.ParseGlob(&quot;views/*&quot;)
if err != nil {
panic(err.Error())
}
router.PathPrefix(&quot;/&quot;).HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
http.FileServer(http.Dir(&quot;./static/&quot;)).ServeHTTP(res, req)
})
fmt.Println(&quot;Server running on localhost&quot; + port)
err = http.ListenAndServe(port, handlers.CompressHandler(router))
if err != nil {
log.Fatal(err)
}
}
func middlewareNoWWW(next http.Handler) http.Handler {
fmt.Println(&quot;middlewareNoWWW&quot;)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Host[0:4] == &quot;www.&quot; {
target := &quot;http://&quot; + r.Host[4:]
http.Redirect(w, r, target, 301)
}
next.ServeHTTP(w, r)
})
}
func middlewareHeaders(next http.Handler) http.Handler {
fmt.Println(&quot;middlewareHeaders&quot;)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(&quot;Cache-Control&quot;, &quot;max-age=2592000&quot;) // 30 days
w.Header().Set(&quot;Content-Encoding&quot;, &quot;gzip&quot;)
w.Header().Set(&quot;Strict-Transport-Security&quot;, &quot;max-age=63072000; includeSubDomains; preload&quot;)
next.ServeHTTP(w, r)
})
}
func middlewareSetCookie(next http.Handler) http.Handler {
fmt.Println(&quot;middlewareSetCookie&quot;)
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:     &quot;/&quot;,
HttpOnly: true,
MaxAge:   0,
Domain:   &quot;localhost&quot;}
http.SetCookie(w, &amp;cookie)
}
next.ServeHTTP(w, r)
})
}
func middlewareCheckCookies(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println(&quot;middlewareCheckCookies&quot;)
fmt.Println(r.URL.String())
c, err := r.Cookie(testCookieName)
if err != nil || c.Value != testCookievalue {
redirectURL := &quot;/cookie&quot;
if r.URL.String() != redirectURL {
http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
return
}
}
next.ServeHTTP(w, r)
})
}

./views/cookie.html

{{define &quot;cookie&quot;}}no cookie set&lt;a href=&quot;/&quot;&gt;index&lt;/a&gt;{{end}}

./views/index.html

{{define &quot;index&quot;}}&lt;a href=&quot;/&quot;&gt;index&lt;/a&gt;{{end}}

Any clue to solving this?

答案1

得分: 2

你的代码问题在于它为处理程序函数构建了糟糕的闭包。如果你不使用不受控制地变化的变量(在这种情况下是由循环引起的)来构建闭包,将会有所帮助。你可以添加以下代码来解决这个问题:

	for k, v := range pages {
		k, v := k, v // <-- 这一行

通过这样做,每个处理程序函数将拥有自己的一组外部变量。

老实说,我真的不太理解你最初的问题是什么。"cookie未被检测到"是什么意思?

英文:

The problem with your code is that it builds lousy closures for handler functions. It would help if you did not use uncontrollably changing (in this case by the loop) variables to build a closure. You can add the following line of code to fix the problem:

	for k, v := range pages {
		k, v := k, v // &lt;-- this line

With that, each handler function will have its own set of external variables.

To be honest, I don't really understand what your initial problem is. What does it mean -- "a cookie is ... not detected"?

huangapple
  • 本文由 发表于 2021年11月13日 05:33:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/69949298.html
匿名

发表评论

匿名网友

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

确定