From 4f3bfe1a159726627e07267a5744cba121f2e8f8 Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Fri, 15 Feb 2019 10:04:51 +0100 Subject: [PATCH 1/2] fix context Err() issue add unit text fix documentation --- server.go | 13 ++++++++----- server_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/server.go b/server.go index ee0926ddb1..80973735a5 100644 --- a/server.go +++ b/server.go @@ -2,6 +2,7 @@ package fasthttp import ( "bufio" + "context" "crypto/tls" "errors" "fmt" @@ -2322,13 +2323,15 @@ func (ctx *RequestCtx) Done() <-chan struct{} { // successive calls to Err return the same error. // If Done is not yet closed, Err returns nil. // If Done is closed, Err returns a non-nil error explaining why: -// Canceled if the context was canceled +// Canceled if the context was canceled ( via server Shutdown ) // or DeadlineExceeded if the context's deadline passed. -// -// This method always returns nil and is only present to make -// RequestCtx implement the context interface. func (ctx *RequestCtx) Err() error { - return nil + select { + case <-ctx.s.done: + return context.Canceled + default: + return nil + } } // Value returns the value associated with this context for key, or nil diff --git a/server_test.go b/server_test.go index 372ef401ec..5c87926830 100644 --- a/server_test.go +++ b/server_test.go @@ -2857,6 +2857,43 @@ func TestShutdownDone(t *testing.T) { verifyResponse(t, br, StatusOK, "aaa/bbb", "real response") } +func TestShutdownErr(t *testing.T) { + ln := fasthttputil.NewInmemoryListener() + s := &Server{ + Handler: func(ctx *RequestCtx) { + // This will panic, but I was not able to intercept with recover() + c, cancel := context.WithCancel(ctx) + defer cancel() + <-c.Done() + ctx.Success("aaa/bbb", []byte("real response")) + }, + } + + go func() { + if err := s.Serve(ln); err != nil { + t.Fatalf("unexepcted error: %s", err) + } + }() + conn, err := ln.Dial() + if err != nil { + t.Fatalf("unexepcted error: %s", err) + } + if _, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")); err != nil { + t.Fatalf("unexpected error: %s", err) + } + go func() { + // Shutdown won't return if the connection doesn't close, + // which doesn't happen until we read the response. + if err := s.Shutdown(); err != nil { + t.Fatalf("unexepcted error: %s", err) + } + }() + // We can only reach this point and get a valid response + // if reading from ctx.Done() returned. + br := bufio.NewReader(conn) + verifyResponse(t, br, StatusOK, "aaa/bbb", "real response") +} + func verifyResponse(t *testing.T, r *bufio.Reader, expectedStatusCode int, expectedContentType, expectedBody string) { var resp Response if err := resp.Read(r); err != nil { From b8807c9d7c5f3f8dc3c5e833116b167f7adc379f Mon Sep 17 00:00:00 2001 From: Tiago Peczenyj Date: Tue, 28 May 2019 18:15:18 +0200 Subject: [PATCH 2/2] add support to SameSite=None --- cookie.go | 11 +++++++++++ cookie_test.go | 11 +++++++++++ strings.go | 1 + 3 files changed, 23 insertions(+) diff --git a/cookie.go b/cookie.go index 8137643c24..6faa8c0360 100644 --- a/cookie.go +++ b/cookie.go @@ -31,6 +31,8 @@ const ( CookieSameSiteLaxMode // CookieSameSiteStrictMode sets the SameSite flag with the "Strict" parameter CookieSameSiteStrictMode + // CookieSameSiteStrictMode sets the SameSite flag with the "None" parameter + CookieSameSiteNoneMode ) // AcquireCookie returns an empty Cookie object from the pool. @@ -288,6 +290,11 @@ func (c *Cookie) AppendBytes(dst []byte) []byte { dst = append(dst, strCookieSameSite...) dst = append(dst, '=') dst = append(dst, strCookieSameSiteStrict...) + case CookieSameSiteNoneMode: + dst = append(dst, ';', ' ') + dst = append(dst, strCookieSameSite...) + dst = append(dst, '=') + dst = append(dst, strCookieSameSiteNone...) } return dst } @@ -386,6 +393,10 @@ func (c *Cookie) ParseBytes(src []byte) error { if caseInsensitiveCompare(strCookieSameSiteStrict, kv.value) { c.sameSite = CookieSameSiteStrictMode } + case 'n': // "none" + if caseInsensitiveCompare(strCookieSameSiteNone, kv.value) { + c.sameSite = CookieSameSiteNoneMode + } } } } diff --git a/cookie_test.go b/cookie_test.go index 50c2ad3463..ae8b4fd750 100644 --- a/cookie_test.go +++ b/cookie_test.go @@ -121,6 +121,17 @@ func TestCookieSameSite(t *testing.T) { t.Fatalf("missing SameSite flag in cookie %q", s) } + if err := c.Parse("foo=bar; samesite=none"); err != nil { + t.Fatalf("unexpected error: %s", err) + } + if c.SameSite() != CookieSameSiteNoneMode { + t.Fatalf("SameSite None Mode must be set") + } + s = c.String() + if !strings.Contains(s, "; SameSite=None") { + t.Fatalf("missing SameSite flag in cookie %q", s) + } + if err := c.Parse("foo=bar"); err != nil { t.Fatalf("unexpected error: %s", err) } diff --git a/strings.go b/strings.go index 6fef4ead73..f654f958a0 100644 --- a/strings.go +++ b/strings.go @@ -62,6 +62,7 @@ var ( strCookieSameSite = []byte("SameSite") strCookieSameSiteLax = []byte("Lax") strCookieSameSiteStrict = []byte("Strict") + strCookieSameSiteNone = []byte("None") strClose = []byte("close") strGzip = []byte("gzip")