-3

I am attempting to set a Cookie and sometimes it works and other times it does not. There is no obvious pattern.

func quoteGetHandler(w http.ResponseWriter, req *http.Request) {
    parts := strings.Split(req.URL.Path, "/")
    csrfToken := uniuri.NewLen(32)
    exp, err := strconv.Atoi(os.Getenv("COOKIE_EXPIRE"))  //5
    if err != nil {
        http.Error(w, whereami.WhereAmI()+err.Error(), http.StatusInternalServerError)
    }
    expire := time.Now().Add(time.Duration(exp) * time.Minute)
    cookie := http.Cookie{
        Name:     os.Getenv("COOKIE_NAME"), //csrf_token
        Value:    csrfToken, //string
        Path:     "/",
        Expires:  expire,
        HttpOnly: true,
        Secure:   true,
        MaxAge:   0,
        Domain:   os.Getenv("DOMAIN")} //<--example.com
    http.SetCookie(w, &cookie)
    tmp := htmlTags["quote"]
    tmp.CsrfToken = csrfToken
    if 2 < len(parts) && parts[2] != "" {
        tmp.Param = parts[2]
    }
    htmlTags["quote"] = tmp
    err = tmpl.ExecuteTemplate(w, siteType+"quote", htmlTags["quote"])
    if err != nil {
        http.Error(w, whereami.WhereAmI()+err.Error(), http.StatusInternalServerError)
    }
}

This happens on Chrome ,FF, Bravo, Safari.

The protocol is https.

pigfox
  • 1,301
  • 3
  • 28
  • 52
  • 1
    Not related to your question, but why are you re-parsing your env variables for every request, rather than just once? – Jonathan Hall Jun 08 '21 at 19:30
  • 1
    *"sometimes it works and other times it does not"* - what exactly means "it works" and what exactly means "it does not". What do you even observe - HTTP response, application behavior .... ? And it this erratic behavior with the environment variables being the same? – Steffen Ullrich Jun 08 '21 at 19:53
  • At times it does set a cookie as expected. Then it does not set a cookie. This behavior is very random. – pigfox Jun 08 '21 at 20:54

1 Answers1

2

"Random" behavior is hard to debug and reason about without a reproducible example.

Some errors and notes regarding your handler.

  1. If the COOKIE_EXPIRE env var is not an integer, your handler sends back an error response and does not return. Note that you can't set other headers (including cookies) after you write anything to the response (http.Error() does write to the response).

  2. If the COOKIE_EXPIRE is an integer but is negative or 0, the cookie expiration (expire variable) will point to the past and will result in the cookie being deleted in the browser.

  3. If cookie name is invalid (COOKIE_NAME env var), the cookie may be silently discarded (as per the doc of http.SetCookie()).

  4. Since you set Secure to true, note that the cookie may be set in the browser, but it will not be included (sent) when insecure (HTTP) requests are made to your server.

  5. If executing the template fails (tmpl.ExecuteTemplate()), some of the response may already be committed, so you can't send another response (not even http.Error()). You either have to execute the template directed into a buffer, and if it succeeds, then send it; or send it directly to the response, but if it fails, you can't make corrections afterwards (best you can do is log the error for later inspection).

icza
  • 389,944
  • 63
  • 907
  • 827