From 9f7463cd289e292a92d22b0cf9d63f500240d747 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Sun, 22 Nov 2015 13:29:21 +0200 Subject: [PATCH] Access Cookie members via accessors --- cookie.go | 166 +++++++++++++++++++++++++++++++++++-------------- cookie_test.go | 10 +-- header.go | 4 +- header_test.go | 72 ++++++++++----------- 4 files changed, 164 insertions(+), 88 deletions(-) diff --git a/cookie.go b/cookie.go index a2b9631..63bc588 100644 --- a/cookie.go +++ b/cookie.go @@ -7,71 +7,147 @@ import ( "time" ) -// CookieExpireDelete may be set on Cookie.Expire for expiring the given cookie. -var CookieExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) +var zeroTime time.Time + +var ( + // CookieExpireDelete may be set on Cookie.Expire for expiring the given cookie. + CookieExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + + // CookieExpireUnlimited indicates that the cookie doesn't expire. + CookieExpireUnlimited = zeroTime +) // Cookie represents HTTP response cookie. type Cookie struct { - // Key is cookie name. - Key []byte - - // Value is cookie value. - Value []byte - - // Expiration time for the cookie. - // - // Set expiration time to CookieExpireDelete for expiring (deleting) - // the cookie on the client. - // - // By default cookie lifetime is limited by browser session. - Expire time.Time - - // Domain for the cookie. - // - // By default cookie is set to the current domain. - Domain []byte - - // Path for the cookie. - // - // By default cookie is set to the current page only. - Path []byte + key []byte + value []byte + expire time.Time + domain []byte + path []byte bufKV argsKV buf []byte } -var zeroTime time.Time +// Path returns cookie path. +func (c *Cookie) Path() []byte { + return c.path +} + +// SetPath sets cookie path. +func (c *Cookie) SetPath(path string) { + c.buf = AppendBytesStr(c.buf[:0], path) + c.path = normalizePath(c.path, c.buf) +} + +// SetPathBytes sets cookie path. +func (c *Cookie) SetPathBytes(path []byte) { + c.buf = append(c.buf[:0], path...) + c.path = normalizePath(c.path, c.buf) +} + +// Domain returns cookie domain. +// +// The returned domain is valid until the next Cookie modification method call. +func (c *Cookie) Domain() []byte { + return c.domain +} + +// SetDomain sets cookie domain. +func (c *Cookie) SetDomain(domain string) { + c.domain = AppendBytesStr(c.domain[:0], domain) +} + +// SetDomain +func (c *Cookie) SetDomainBytes(domain []byte) { + c.domain = append(c.domain[:0], domain...) +} + +// Expire returns cookie expiration time. +// +// CookieExpireUnlimited is returned if cookie doesn't expire +func (c *Cookie) Expire() time.Time { + expire := c.expire + if expire.IsZero() { + expire = CookieExpireUnlimited + } + return expire +} + +// SetExpire sets cookie expiration time. +// +// Set expiration time to CookieExpireDelete for expiring (deleting) +// the cookie on the client. +// +// By default cookie lifetime is limited by browser session. +func (c *Cookie) SetExpire(expire time.Time) { + c.expire = expire +} + +// Value returns cookie value. +// +// The returned value is valid until the next Cookie modification method call. +func (c *Cookie) Value() []byte { + return c.value +} + +// SetValue sets cookie value. +func (c *Cookie) SetValue(value string) { + c.value = AppendBytesStr(c.value[:0], value) +} + +// SetValueBytes sets cookie value. +func (c *Cookie) SetValueBytes(value []byte) { + c.value = append(c.value[:0], value...) +} + +// Key returns cookie name. +// +// The returned value is valid until the next Cookie modification method call. +func (c *Cookie) Key() []byte { + return c.key +} + +// SetKey sets cookie name. +func (c *Cookie) SetKey(key string) { + c.key = AppendBytesStr(c.key[:0], key) +} + +// SetKeyBytes sets cookie name. +func (c *Cookie) SetKeyBytes(key []byte) { + c.key = append(c.key[:0], key...) +} // Reset clears the cookie. func (c *Cookie) Reset() { - c.Key = c.Key[:0] - c.Value = c.Value[:0] - c.Expire = zeroTime - c.Domain = c.Domain[:0] - c.Path = c.Path[:0] + c.key = c.key[:0] + c.value = c.value[:0] + c.expire = zeroTime + c.domain = c.domain[:0] + c.path = c.path[:0] } // AppendBytes appends cookie representation to dst and returns dst // (maybe newly allocated). func (c *Cookie) AppendBytes(dst []byte) []byte { - if len(c.Key) > 0 { - dst = appendQuotedArg(dst, c.Key) + if len(c.key) > 0 { + dst = appendQuotedArg(dst, c.key) dst = append(dst, '=') } - dst = appendQuotedArg(dst, c.Value) + dst = appendQuotedArg(dst, c.value) - if !c.Expire.IsZero() { - c.bufKV.value = AppendHTTPDate(c.bufKV.value[:0], c.Expire) + if !c.expire.IsZero() { + c.bufKV.value = AppendHTTPDate(c.bufKV.value[:0], c.expire) dst = append(dst, ';', ' ') dst = append(dst, strCookieExpires...) dst = append(dst, '=') dst = append(dst, c.bufKV.value...) } - if len(c.Domain) > 0 { - dst = appendCookiePart(dst, strCookieDomain, c.Domain) + if len(c.domain) > 0 { + dst = appendCookiePart(dst, strCookieDomain, c.domain) } - if len(c.Path) > 0 { - dst = appendCookiePart(dst, strCookiePath, c.Path) + if len(c.path) > 0 { + dst = appendCookiePart(dst, strCookiePath, c.path) } return dst } @@ -117,8 +193,8 @@ func (c *Cookie) ParseBytes(src []byte) error { return errNoCookies } - c.Key = append(c.Key[:0], kv.key...) - c.Value = append(c.Value[:0], kv.value...) + c.key = append(c.key[:0], kv.key...) + c.value = append(c.value[:0], kv.value...) for s.next(kv, false) { if len(kv.key) == 0 && len(kv.value) == 0 { @@ -131,11 +207,11 @@ func (c *Cookie) ParseBytes(src []byte) error { if err != nil { return err } - c.Expire = exptime + c.expire = exptime case bytes.Equal(strCookieDomain, kv.key): - c.Domain = append(c.Domain[:0], kv.value...) + c.domain = append(c.domain[:0], kv.value...) case bytes.Equal(strCookiePath, kv.key): - c.Path = append(c.Path[:0], kv.value...) + c.path = append(c.path[:0], kv.value...) } } return nil diff --git a/cookie_test.go b/cookie_test.go index 478f91c..f1565e6 100644 --- a/cookie_test.go +++ b/cookie_test.go @@ -32,19 +32,19 @@ func TestCookieAppendBytes(t *testing.T) { testCookieAppendBytes(t, c, "foo", "", "foo=") testCookieAppendBytes(t, c, "ффф", "12 лодлы", "%D1%84%D1%84%D1%84=12%20%D0%BB%D0%BE%D0%B4%D0%BB%D1%8B") - c.Domain = []byte("foobar.com") + c.SetDomain("foobar.com") testCookieAppendBytes(t, c, "a", "b", "a=b; domain=foobar.com") - c.Path = []byte("/a/b") + c.SetPath("/a/b") testCookieAppendBytes(t, c, "aa", "bb", "aa=bb; domain=foobar.com; path=/a/b") - c.Expire = CookieExpireDelete + c.SetExpire(CookieExpireDelete) testCookieAppendBytes(t, c, "xxx", "yyy", "xxx=yyy; expires=Tue, 10 Nov 2009 23:00:00 GMT; domain=foobar.com; path=/a/b") } func testCookieAppendBytes(t *testing.T, c *Cookie, key, value, expectedS string) { - c.Key = []byte(key) - c.Value = []byte(value) + c.SetKey(key) + c.SetValue(value) result := string(c.AppendBytes(nil)) if result != expectedS { t.Fatalf("Unexpected cookie %q. Expected %q", result, expectedS) diff --git a/header.go b/header.go index 7006c62..b945685 100644 --- a/header.go +++ b/header.go @@ -579,7 +579,7 @@ func (h *ResponseHeader) SetCanonical(key, value []byte) { // SetCookie sets the given response cookie. func (h *ResponseHeader) SetCookie(cookie *Cookie) { - h.cookies = setArg(h.cookies, cookie.Key, cookie.Cookie()) + h.cookies = setArg(h.cookies, cookie.Key(), cookie.Cookie()) } // SetCookie sets 'key: value' cookies. @@ -754,7 +754,7 @@ func (h *RequestHeader) CookieBytes(key []byte) []byte { // // Returns false if cookie with the given cookie.Key is missing. func (h *ResponseHeader) Cookie(cookie *Cookie) bool { - v := peekArgBytes(h.cookies, cookie.Key) + v := peekArgBytes(h.cookies, cookie.Key()) if v == nil { return false } diff --git a/header_test.go b/header_test.go index 917ef7c..9f6e4ec 100644 --- a/header_test.go +++ b/header_test.go @@ -282,26 +282,26 @@ func TestResponseHeaderSetCookie(t *testing.T) { h.Set("Set-Cookie", "aaaaa=bxx") var c Cookie - c.Key = []byte("foo") + c.SetKey("foo") if !h.Cookie(&c) { - t.Fatalf("cannot obtain %q cookie", c.Key) + t.Fatalf("cannot obtain %q cookie", c.Key()) } - if string(c.Value) != "bar" { - t.Fatalf("unexpected cookie value %q. Expected %q", c.Value, "bar") + if string(c.Value()) != "bar" { + t.Fatalf("unexpected cookie value %q. Expected %q", c.Value(), "bar") } - if string(c.Path) != "/aa/bb" { - t.Fatalf("unexpected cookie path %q. Expected %q", c.Path, "/aa/bb") + if string(c.Path()) != "/aa/bb" { + t.Fatalf("unexpected cookie path %q. Expected %q", c.Path(), "/aa/bb") } - if string(c.Domain) != "aaa.com" { - t.Fatalf("unexpected cookie domain %q. Expected %q", c.Domain, "aaa.com") + if string(c.Domain()) != "aaa.com" { + t.Fatalf("unexpected cookie domain %q. Expected %q", c.Domain(), "aaa.com") } - c.Key = []byte("aaaaa") + c.SetKey("aaaaa") if !h.Cookie(&c) { - t.Fatalf("cannot obtain %q cookie", c.Key) + t.Fatalf("cannot obtain %q cookie", c.Key()) } - if string(c.Value) != "bxx" { - t.Fatalf("unexpected cookie value %q. Expecting %q", c.Value, "bxx") + if string(c.Value()) != "bxx" { + t.Fatalf("unexpected cookie value %q. Expecting %q", c.Value(), "bxx") } } @@ -413,36 +413,36 @@ func TestResponseHeaderCookie(t *testing.T) { var h ResponseHeader var c Cookie - c.Key = []byte("foobar") - c.Value = []byte("aaa") + c.SetKey("foobar") + c.SetValue("aaa") h.SetCookie(&c) - c.Key = []byte("йцук") - c.Domain = []byte("foobar.com") + c.SetKey("йцук") + c.SetDomain("foobar.com") h.SetCookie(&c) c.Reset() - c.Key = []byte("foobar") + c.SetKey("foobar") if !h.Cookie(&c) { - t.Fatalf("Cannot find cookie %q", c.Key) + t.Fatalf("Cannot find cookie %q", c.Key()) } var expectedC1 Cookie - expectedC1.Key = []byte("foobar") - expectedC1.Value = []byte("aaa") + expectedC1.SetKey("foobar") + expectedC1.SetValue("aaa") if !equalCookie(&expectedC1, &c) { t.Fatalf("unexpected cookie\n%#v\nExpected\n%#v\n", c, expectedC1) } - c.Key = []byte("йцук") + c.SetKey("йцук") if !h.Cookie(&c) { - t.Fatalf("cannot find cookie %q", c.Key) + t.Fatalf("cannot find cookie %q", c.Key()) } var expectedC2 Cookie - expectedC2.Key = []byte("йцук") - expectedC2.Value = []byte("aaa") - expectedC2.Domain = []byte("foobar.com") + expectedC2.SetKey("йцук") + expectedC2.SetValue("aaa") + expectedC2.SetDomain("foobar.com") if !equalCookie(&expectedC2, &c) { t.Fatalf("unexpected cookie\n%v\nExpected\n%v\n", c, expectedC2) } @@ -450,8 +450,8 @@ func TestResponseHeaderCookie(t *testing.T) { h.VisitAllCookie(func(key, value []byte) { var cc Cookie cc.ParseBytes(value) - if !bytes.Equal(key, cc.Key) { - t.Fatalf("Unexpected cookie key %q. Expected %q", key, cc.Key) + if !bytes.Equal(key, cc.Key()) { + t.Fatalf("Unexpected cookie key %q. Expected %q", key, cc.Key()) } switch { case bytes.Equal(key, []byte("foobar")): @@ -482,17 +482,17 @@ func TestResponseHeaderCookie(t *testing.T) { t.Fatalf("unexpected error: %s", err) } - c.Key = []byte("foobar") + c.SetKey("foobar") if !h1.Cookie(&c) { - t.Fatalf("Cannot find cookie %q", c.Key) + t.Fatalf("Cannot find cookie %q", c.Key()) } if !equalCookie(&expectedC1, &c) { t.Fatalf("unexpected cookie\n%v\nExpected\n%v\n", c, expectedC1) } - c.Key = []byte("йцук") + c.SetKey("йцук") if !h1.Cookie(&c) { - t.Fatalf("cannot find cookie %q", c.Key) + t.Fatalf("cannot find cookie %q", c.Key()) } if !equalCookie(&expectedC2, &c) { t.Fatalf("unexpected cookie\n%v\nExpected\n%v\n", c, expectedC2) @@ -500,19 +500,19 @@ func TestResponseHeaderCookie(t *testing.T) { } func equalCookie(c1, c2 *Cookie) bool { - if !bytes.Equal(c1.Key, c2.Key) { + if !bytes.Equal(c1.Key(), c2.Key()) { return false } - if !bytes.Equal(c1.Value, c2.Value) { + if !bytes.Equal(c1.Value(), c2.Value()) { return false } - if !c1.Expire.Equal(c2.Expire) { + if !c1.Expire().Equal(c2.Expire()) { return false } - if !bytes.Equal(c1.Domain, c2.Domain) { + if !bytes.Equal(c1.Domain(), c2.Domain()) { return false } - if !bytes.Equal(c1.Path, c2.Path) { + if !bytes.Equal(c1.Path(), c2.Path()) { return false } return true