Description

I could set a dot-prefix domain at cookie. For example ".a.b.com". It will return "a.b.com". I don't know why dot will be lost.

How to reproduce

package main

import (
    "time"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.SetCookie("NAME","VALUE",23*60,"/",".a.b.com",true,true)
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run(":8089") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
    time.Sleep(60*60)
}

Expectations

❯ curl -v GET 'http://0.0.0.0:8089/ping'

* Could not resolve host: GET
* Closing connection 0
curl: (6) Could not resolve host: GET
*   Trying 0.0.0.0:8089...
* Connected to 0.0.0.0 (127.0.0.1) port 8089 (#1)
> GET /ping HTTP/1.1
> Host: 0.0.0.0:8089
> User-Agent: curl/7.77.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Set-Cookie: NAME=VALUE; Path=/; Domain=.a.b.com; Max-Age=1380; HttpOnly; Secure
< Date: Fri, 13 May 2022 05:22:41 GMT
< Content-Length: 18
< 
* Connection #1 to host 0.0.0.0 left intact
{"message":"pong"}%         

I want Domain=.a.b.com

Actual result

❯ curl -v GET 'http://0.0.0.0:8089/ping'

* Could not resolve host: GET
* Closing connection 0
curl: (6) Could not resolve host: GET
*   Trying 0.0.0.0:8089...
* Connected to 0.0.0.0 (127.0.0.1) port 8089 (#1)
> GET /ping HTTP/1.1
> Host: 0.0.0.0:8089
> User-Agent: curl/7.77.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Set-Cookie: NAME=VALUE; Path=/; Domain=a.b.com; Max-Age=1380; HttpOnly; Secure
< Date: Fri, 13 May 2022 05:22:41 GMT
< Content-Length: 18
< 
* Connection #1 to host 0.0.0.0 left intact
{"message":"pong"}%         

this line < Set-Cookie: NAME=VALUE; Path=/; Domain=a.b.com; Max-Age=1380; HttpOnly; Secure domain without dot prefix

Environment

  • go version: go 1.14
  • gin version (or commit ref): v1.7.7
  • operating system: macOS and linux

Comment From: cevin

ctx.SetCookie directly uses GoLang's built-in net/http.SetCookie(writer, *cookie)

This is how the Domain is handled (note the comments section):

if len(c.Domain) > 0 {
  if validCookieDomain(c.Domain) {
      // A c.Domain containing illegal characters is not
      // sanitized but simply dropped which turns the cookie
      // into a host-only cookie. A leading dot is okay
      // but won't be sent.
      d := c.Domain
      if d[0] == '.' {
          d = d[1:]
      }
      b.WriteString("; Domain=")
      b.WriteString(d)
  } else {
      log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute", c.Domain)
  }
}

I think you can just write the Header for Set-Cookie, like ctx.Header('Set-Cookie', 'name="value"; domain=.a.b.com; HttpOnly')

Comment From: hiveer

I have a similar case: https://stackoverflow.com/questions/79194445/go-gin-ctx-setcookie-cant-clear-cookie-for-a-specific-domain