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

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

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

问题

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

  1. func (a *authController) Logout(ctx *gin.Context) {
  2. refreshToken, err := ctx.Cookie("refresh_token")
  3. ...
  4. ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
  5. ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
  6. ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
  7. ctx.JSON(http.StatusOK, gin.H{"status": "success"})
  8. }

测试函数中的代码:

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

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

  1. cookies := recorder.Result().Cookies()
  2. for _, c := range cookies {
  3. if c.Name == "access_token" {
  4. assert.Equal(t, "", c.Value)
  5. }
  6. ...
  7. }

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

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

英文:

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

  1. func (a *authController) Logout(ctx *gin.Context) {
  2. refreshToken, err := ctx.Cookie("refresh_token")
  3. ...
  4. ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
  5. ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
  6. ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
  7. ctx.JSON(http.StatusOK, gin.H{"status": "success"})
  8. }

code inside the test function:

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

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

  1. coockies := recorder.Result().Cookies()
  2. for _, c := range coockies {
  3. if c.Name == "access_token" {
  4. assert.Equal(t, "", c.Value)
  5. }
  6. ...
  7. }

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处理程序:

  1. package ${your_package}
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/http/httptest"
  6. "testing"
  7. "github.com/gin-gonic/gin"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func Logout(ctx *gin.Context) {
  11. // refreshToken, err := ctx.Cookie("refresh_token")
  12. ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
  13. ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
  14. ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
  15. ctx.JSON(http.StatusOK, gin.H{"status": "success"})
  16. }
  17. func setupRouter() *gin.Engine {
  18. r := gin.Default()
  19. r.GET("/logout", Logout)
  20. return r
  21. }
  22. func TestLogout(t *testing.T) {
  23. w := httptest.NewRecorder()
  24. r := setupRouter()
  25. req, err := http.NewRequest("GET", "/logout", nil)
  26. assert.Nil(t, err)
  27. req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
  28. req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
  29. r.ServeHTTP(w, req)
  30. for _, v := range w.Result().Cookies() {
  31. if v.Name == "access_token" {
  32. assert.Equal(t, "", v.Value)
  33. }
  34. }
  35. assert.Equal(t, http.StatusOK, w.Code)
  36. respBody := &gin.H{}
  37. err = json.Unmarshal(w.Body.Bytes(), respBody)
  38. assert.Nil(t, err)
  39. assert.Equal(t, gin.H{"status": "success"}, *respBody)
  40. }
  1. === RUN TestLogout
  2. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
  3. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
  4. - using env: export GIN_MODE=release
  5. - using code: gin.SetMode(gin.ReleaseMode)
  6. [GIN-debug] GET /logout --> app.Logout (3 handlers)
  7. [GIN] 2022/09/19 - 10:46:00 | 200 | 81μs | | GET "/logout"
  8. --- PASS: TestLogout (0.00s)
  9. 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:

  1. package ${your_package}
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "net/http/httptest"
  6. "testing"
  7. "github.com/gin-gonic/gin"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func Logout(ctx *gin.Context) {
  11. // refreshToken, err := ctx.Cookie("refresh_token")
  12. ctx.SetCookie("access_token", "", -1, "/", "localhost", false, true)
  13. ctx.SetCookie("refresh_token", "", -1, "/", "localhost", false, true)
  14. ctx.SetCookie("logged_in", "", -1, "/", "localhost", false, true)
  15. ctx.JSON(http.StatusOK, gin.H{"status": "success"})
  16. }
  17. func setupRouter() *gin.Engine {
  18. r := gin.Default()
  19. r.GET("/logout", Logout)
  20. return r
  21. }
  22. func TestLogout(t *testing.T) {
  23. w := httptest.NewRecorder()
  24. r := setupRouter()
  25. req, err := http.NewRequest("GET", "/logout", nil)
  26. assert.Nil(t, err)
  27. req.AddCookie(&http.Cookie{Name: "refresh_token", Value: "encodedRefreshToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
  28. req.AddCookie(&http.Cookie{Name: "access_token", Value: "encodedAccessToken", MaxAge: 60 * 60, Path: "/", Domain: "localhost", Secure: false, HttpOnly: true})
  29. r.ServeHTTP(w, req)
  30. for _, v := range w.Result().Cookies() {
  31. if v.Name == "access_token" {
  32. assert.Equal(t, "", v.Value)
  33. }
  34. }
  35. assert.Equal(t, http.StatusOK, w.Code)
  36. respBody := &gin.H{}
  37. err = json.Unmarshal(w.Body.Bytes(), respBody)
  38. assert.Nil(t, err)
  39. assert.Equal(t, gin.H{"status": "success"}, *respBody)
  40. }
  1. === RUN TestLogout
  2. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
  3. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
  4. - using env: export GIN_MODE=release
  5. - using code: gin.SetMode(gin.ReleaseMode)
  6. [GIN-debug] GET /logout --> app.Logout (3 handlers)
  7. [GIN] 2022/09/19 - 10:46:00 | 200 | 81µs | | GET "/logout"
  8. --- PASS: TestLogout (0.00s)
  9. 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:

确定