为什么 gin 的 SetCookie 方法会添加新的 cookie,而不是更改旧的 cookie?

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

Why does gin SetCookie add new cookies but not change the old ones?

问题

我正在尝试测试 Logout 处理程序,其中有一个 ctx.SetCookie 方法:

func (a *authController) Logout(ctx *gin.Context) {
	refreshToken, err := ctx.Cookie("refresh_token")
	...
	ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)

	ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}

测试函数中的代码:

recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.SetCookie("logged_in", "truee", 60*60, "/", "localhost", false, false)
req, _ := http.NewRequest("GET", "/logout", nil)
http.SetCookie(recorder, &http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true}})
http.SetCookie(recorder, &http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.Header = http.Header{"Cookie": recorder.Result().Header["Set-Cookie"]}
ctx.Request = req
test.mock()
authController.Logout(ctx)

调用后,我尝试检查 cookie 是否已被删除:

cookies := recorder.Result().Cookies()
for _, c := range cookies {
	if c.Name == "access_token" {
	    assert.Equal(t, "", c.Value)
    }
    ...
}

我遇到的问题是 SetCookie 方法不会更改 cookie,而是添加新的 cookie。也就是说,在调用该方法后,我有两对带有 access Token 的 cookie。

结果导致测试未通过。我不明白我做错了什么,是否可以解决?或者这是正常的行为?

英文:

I'm trying to test the Logout handler where there is a ctx.SetCookie method:

func (a *authController) Logout(ctx *gin.Context) {
	refreshToken, err := ctx.Cookie("refresh_token")
	...
	ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)

	ctx.JSON(http.StatusOK, gin.H{"status": "success"})

}

code inside the test function:

recorder := httptest.NewRecorder()
ctx, _ := gin.CreateTestContext(recorder)
ctx.SetCookie("logged_in", "truee", 60*60, "/", "localhost", false, false)
req, _ := http.NewRequest("GET", "/logout", nil)
http.SetCookie(recorder, &http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true}})
http.SetCookie(recorder, &http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
req.Header = http.Header{"Cookie": recorder.Result().Header["Set-Cookie"]}
ctx.Request = req
test.mock()
authController.Logout(ctx)

After the call, I'm trying to check if the cookies have been deleted:


coockies := recorder.Result().Cookies()
for _, c := range coockies {
	if c.Name == "access_token" {
	    assert.Equal(t, "", c.Value)
    }
    ...
}

And I face such a problem that setCookie does not change cookies , but adds new ones . That is, after calling this method, I have two pairs of cookies with access Token, etc.

And as a result, the tests do not pass. I don't understand I'm doing something wrong and can it be solved somehow? or is that how it should be ?

答案1

得分: 1

使用AddCookierecorder设置cookie。

我认为你应该像这样测试Logout处理程序:

package ${your_package}

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
)

func Logout(ctx *gin.Context) {
	// refreshToken, err := ctx.Cookie("refresh_token")
	ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)

	ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}

func setupRouter() *gin.Engine {
	r := gin.Default()
	r.GET("/logout", Logout)
	return r
}

func TestLogout(t *testing.T) {
	w := httptest.NewRecorder()
	r := setupRouter()
	req, err := http.NewRequest("GET", "/logout", nil)
	assert.Nil(t, err)
	req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
	req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
	r.ServeHTTP(w, req)

	for _, v := range w.Result().Cookies() {
		if v.Name == "access_token" {
			assert.Equal(t, "", v.Value)
		}
	}
	assert.Equal(t, http.StatusOK, w.Code)
	respBody := &gin.H{}
	err = json.Unmarshal(w.Body.Bytes(), respBody)
	assert.Nil(t, err)
	assert.Equal(t, gin.H{"status": "success"}, *respBody)
}
=== RUN   TestLogout
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /logout                   --> app.Logout (3 handlers)
[GIN] 2022/09/19 - 10:46:00 | 200 |          81μs |                 | GET      "/logout"
--- PASS: TestLogout (0.00s)
PASS

参考:https://gin-gonic.com/docs/testing/

英文:

Use AddCookie to set cookie for the recorder.

I think you should test the Logout handler like this:

package ${your_package}

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
)

func Logout(ctx *gin.Context) {
	// refreshToken, err := ctx.Cookie("refresh_token")
	ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
	ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)

	ctx.JSON(http.StatusOK, gin.H{"status": "success"})
}

func setupRouter() *gin.Engine {
	r := gin.Default()
	r.GET("/logout", Logout)
	return r
}

func TestLogout(t *testing.T) {
	w := httptest.NewRecorder()
	r := setupRouter()
	req, err := http.NewRequest("GET", "/logout", nil)
	assert.Nil(t, err)
	req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
	req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
	r.ServeHTTP(w, req)

	for _, v := range w.Result().Cookies() {
		if v.Name == "access_token" {
			assert.Equal(t, "", v.Value)
		}
	}
	assert.Equal(t, http.StatusOK, w.Code)
	respBody := &gin.H{}
	err = json.Unmarshal(w.Body.Bytes(), respBody)
	assert.Nil(t, err)
	assert.Equal(t, gin.H{"status": "success"}, *respBody)
}
=== RUN   TestLogout
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env:	export GIN_MODE=release
- using code:	gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET    /logout                   --> app.Logout (3 handlers)
[GIN] 2022/09/19 - 10:46:00 | 200 |          81µs |                 | GET      "/logout"
--- PASS: TestLogout (0.00s)
PASS

Reference: https://gin-gonic.com/docs/testing/

huangapple
  • 本文由 发表于 2022年9月18日 22:08:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/73763428.html
匿名

发表评论

匿名网友

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

确定