mirror of
https://github.com/golang/go
synced 2024-11-19 15:05:00 -07:00
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
This commit is contained in:
parent
ca83cd2c2f
commit
158970ea66
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user