Repository: gin-gonic/gin
Pull request #1615 (2018-10-29 09:04:05)

Added support for SameSite cookie flag
Read more at:
https://golang.org/pkg/net/http/#Cookie

codecov[bot]: # [Codecov](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=h1) Report
> Merging [#1615](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=desc) into [master](https://codecov.io/gh/gin-gonic/gin/commit/c65e5efc9a0ae6666819cda8e9a86db4d3d19833?src=pr&el=desc) will **increase** coverage by `0.24%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/gin-gonic/gin/pull/1615/graphs/tree.svg?width=650&token=Qpqxhwery8&height=150&src=pr)](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1615      +/-   ##
==========================================
+ Coverage   99.27%   99.52%   +0.24%     
==========================================
  Files          39       21      -18     
  Lines        1931      418    -1513     
==========================================
- Hits         1917      416    -1501     
+ Misses         10        1       -9     
+ Partials        4        1       -3
```


| [Impacted Files](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [logger.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-bG9nZ2VyLmdv) | | |
| [debug.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-ZGVidWcuZ28=) | | |
| [tree.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-dHJlZS5nbw==) | | |
| [utils.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-dXRpbHMuZ28=) | | |
| [response\_writer.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-cmVzcG9uc2Vfd3JpdGVyLmdv) | | |
| [fs.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-ZnMuZ28=) | | |
| [response\_writer\_1.8.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-cmVzcG9uc2Vfd3JpdGVyXzEuOC5nbw==) | | |
| [path.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-cGF0aC5nbw==) | | |
| [context\_17.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-Y29udGV4dF8xNy5nbw==) | | |
| [auth.go](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree#diff-YXV0aC5nbw==) | | |
| ... and [7 more](https://codecov.io/gh/gin-gonic/gin/pull/1615/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=footer). Last update [c65e5ef...211510c](https://codecov.io/gh/gin-gonic/gin/pull/1615?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

JFKingsley: Is there any chance that we could see this merged? There's several instances in codebases that I maintain where the ability to use this now that Go 1.11 is out would be massively useful.
appleboy: @anio sameSite mode only support on go 1.11 version.

https://golang.org/pkg/net/http/#Cookie

```go
type Cookie struct {
    Name  string
    Value string

    Path       string    // optional
    Domain     string    // optional
    Expires    time.Time // optional
    RawExpires string    // for reading cookies only

    // MaxAge=0 means no 'Max-Age' attribute specified.
    // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
    // MaxAge>0 means Max-Age attribute present and given in seconds
    MaxAge   int
    Secure   bool
    HttpOnly bool
    SameSite SameSite // Go 1.11
    Raw      string
    Unparsed []string // Raw text of unparsed attribute-value pairs
}
```
haywirez: Could this issue get some more attention? Chrome 80 with [same-site cookies by default](https://chromestatus.com/feature/5633521622188032) is shipping in **less than a month**: https://chromiumdash.appspot.com/schedule
haywirez: An earlier comment in this thread:

> Samesite flag only support on Golang v1.11

The [README](https://github.com/gin-gonic/gin#testing) already states that this project requires Go 1.11+. So I don't really see why this shouldn't be merged 🤔 ?

> To install Gin package, you need to install Go and set your Go workspace first.
> 
> 1. The first need Go installed (**version 1.11+ is required**), then you can use the below Go command to install Gin.




thinkerou: @appleboy I have fixed, please review, thanks!

Patch:
diff --git a/context.go b/context.go
index e979d28..ee202d1 100644
--- a/context.go
+++ b/context.go
@@ -775,7 +775,7 @@ func (c *Context) GetRawData() ([]byte, error) {
 // SetCookie adds a Set-Cookie header to the ResponseWriter's headers.
 // The provided cookie must have a valid Name. Invalid cookies may be
 // silently dropped.
-func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {
+func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, sameSite http.SameSite, secure, httpOnly bool) {
 	if path == "" {
 		path = "/"
 	}
@@ -785,6 +785,7 @@ func (c *Context) SetCookie(name, value string, maxAge int, path, domain string,
 		MaxAge:   maxAge,
 		Path:     path,
 		Domain:   domain,
+		SameSite: sameSite,
 		Secure:   secure,
 		HttpOnly: httpOnly,
 	})


Test patch:
diff --git a/context_test.go b/context_test.go
index 18709d3..df2d954 100644
--- a/context_test.go
+++ b/context_test.go
@@ -602,14 +602,14 @@ func TestContextPostFormMultipart(t *testing.T) {
 
 func TestContextSetCookie(t *testing.T) {
 	c, _ := CreateTestContext(httptest.NewRecorder())
-	c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
-	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
+	c.SetCookie("user", "gin", 1, "/", "localhost", http.SameSiteLaxMode, true, true)
+	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
 }
 
 func TestContextSetCookiePathEmpty(t *testing.T) {
 	c, _ := CreateTestContext(httptest.NewRecorder())
-	c.SetCookie("user", "gin", 1, "", "localhost", true, true)
-	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
+	c.SetCookie("user", "gin", 1, "", "localhost", http.SameSiteLaxMode, true, true)
+	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
 }
 
 func TestContextGetCookie(t *testing.T) {