Commit 158970ea authored by Christian Himpel's avatar Christian Himpel Committed by Brad Fitzpatrick

http: write cookies according to RFC 6265

RFC 6265 requires that user agents MUST NOT send more than
one Cookie header in a request.

Note, this change also fixes an issue when sending requests
with more than one cookie header line to a php script served
by an apache web server.  Apache concatenates the cookies
with ", ", but php tries to split them only at ";".  E.g.
two cookies: "a=b, c=d" are seen by php as one cookie "a"
with the value "b, c=d".

Fixes #1801

R=bradfitz
CC=golang-dev
https://golang.org/cl/4535048
parent ca83cd2c
......@@ -218,22 +218,26 @@ func readCookies(h Header) []*Cookie {
return cookies
}
// writeCookies writes the wire representation of the cookies
// to w. Each cookie is written on a separate "Cookie: " line.
// This choice is made because HTTP parsers tend to have a limit on
// line-length, so it seems safer to place cookies on separate lines.
// writeCookies writes the wire representation of the cookies to
// w. According to RFC 6265 section 5.4, writeCookies does not
// attach more than one Cookie header field. That means all
// cookies, if any, are written into the same line, separated by
// semicolon.
func writeCookies(w io.Writer, kk []*Cookie) os.Error {
lines := make([]string, 0, len(kk))
for _, c := range kk {
lines = append(lines, fmt.Sprintf("Cookie: %s=%s\r\n", sanitizeName(c.Name), sanitizeValue(c.Value)))
if len(kk) == 0 {
return nil
}
sort.SortStrings(lines)
for _, l := range lines {
if _, err := io.WriteString(w, l); err != nil {
return err
var buf bytes.Buffer
fmt.Fprintf(&buf, "Cookie: ")
for i, c := range kk {
if i > 0 {
fmt.Fprintf(&buf, "; ")
}
fmt.Fprintf(&buf, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
}
return nil
fmt.Fprintf(&buf, "\r\n")
_, err := w.Write(buf.Bytes())
return err
}
func sanitizeName(n string) string {
......
......@@ -47,10 +47,22 @@ var writeCookiesTests = []struct {
Cookies []*Cookie
Raw string
}{
{
[]*Cookie{},
"",
},
{
[]*Cookie{&Cookie{Name: "cookie-1", Value: "v$1"}},
"Cookie: cookie-1=v$1\r\n",
},
{
[]*Cookie{
&Cookie{Name: "cookie-1", Value: "v$1"},
&Cookie{Name: "cookie-2", Value: "v$2"},
&Cookie{Name: "cookie-3", Value: "v$3"},
},
"Cookie: cookie-1=v$1; cookie-2=v$2; cookie-3=v$3\r\n",
},
}
func TestWriteCookies(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment