func SetCookie(w ResponseWriter, cookie *Cookie) {
if v := cookie.String(); v != "" {
w.Header().Add("Set-Cookie", v)
}
}
If you want to set the header "Set-Cookie" to the empty string instead of not sending the header, you can just call w.Header().Add("set-cookie", "") yourself, I guess.
Whoever wrote that part of the net/http package probably wanted `Cookie` to fulfill the `Stringer` interface, so the compromise was to use an empty string.
Mildly reminiscent of x/crypto/acme/autocert only having supported TLS-SNI because it made for more elegant code and the other methods didn't, but that's probably too cynical an interpretation.
I would start arguing about the semantics of "causing an error" here, but I don't think it would as productive as reducing it down to this question.
If I as a client of this library call "SetCookie", and after the call, a cookie has not been set (and I was not notified), I would call that an error (or fault, or whatever), independent of implementation.
Setting a cookie translates to writing a header down the socket but it isn't written when SetCookie is called. It is written when you use the ResponseWriter as a parameter for a writer method (io.WriteString, for instance).
As SetCookie just adds a new header to an aliased map (Headers) and setting to a map shouldn't fail (how it could?), it makes sense to report any error when the HTTP response is written serialized to the socket, not before. At least, for me, as you can manipulate the response as you wish and you only need to worry about errors on write.
How far do you take this, though? If you call 'w.Header().Add("Set-Cooike", "my=cookie")' you're not going to get your cookie either. Header.Add could check the key and say "hey, that's not in the HTTP standard, did you mean Set-Cookie?" but that would be annoying when you want to extend the standard. But OK, you can only extend the standard by prefixing the header with X-, so allow that. But what if you want to set X-Frame-Options and misspell it as "X-Farme-Options"? That one is kind of standard, though, so I guess that could be checked. But what if you want to set options on a Farme?
The point is, there is only so much validation of free-form text you can do. Ultimately your tests need to ensure that the headers you set do the right thing. And in the case of cookies, you are adding no appreciable overhead to automated tests by using httptest.Server and an actual client that understands cookies, so you'll find the bug pretty easily.
I agree that it would be nice to validate the cookie object and get some error message instead of an empty string. But it's not an error that you are ever going to take action on at runtime. Nobody writes:
cookie := GenerateInvalidCookie()
if _, err := cookie.Serialize(); err != nil {
log.Printf("ok, I guess we'll use a valid cookie")
cookie = GenerateValidCookie()
if _, err = cookie.Serialize(); err != nil {
log.Fatalf("you can't say I didn't try")
}
}
w.SetCookie(cookie)
So at some point, you have to ask what you're going to do about it. In the end, whether or not a cookie is valid depends on the user agent that is receiving the cookie. Test it against that.
https://golang.org/src/net/http/cookie.go?s=3875:3923#L147
If you want to set the header "Set-Cookie" to the empty string instead of not sending the header, you can just call w.Header().Add("set-cookie", "") yourself, I guess.