From 44b8157572fbc049b04e15dc5be1c0acb644f6f1 Mon Sep 17 00:00:00 2001 From: spacexnice Date: Tue, 23 Aug 2016 22:09:18 +0800 Subject: [PATCH 1/4] fix simpleAuthChallge concurrent problem Signed-off-by: spacexnice --- registry/client/auth/authchallenge.go | 22 ++++++--- registry/client/auth/authchallenge_test.go | 57 ++++++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/registry/client/auth/authchallenge.go b/registry/client/auth/authchallenge.go index c8cd83bb..4dbda9e0 100644 --- a/registry/client/auth/authchallenge.go +++ b/registry/client/auth/authchallenge.go @@ -5,6 +5,7 @@ import ( "net/http" "net/url" "strings" + "sync" ) // Challenge carries information from a WWW-Authenticate response header. @@ -43,19 +44,26 @@ type ChallengeManager interface { // perform requests on the endpoints or cache the responses // to a backend. func NewSimpleChallengeManager() ChallengeManager { - return simpleChallengeManager{} + return &simpleChallengeManager{ + Challanges: make(map[string][]Challenge), + } } -type simpleChallengeManager map[string][]Challenge +type simpleChallengeManager struct{ + sync.RWMutex + Challanges map[string][]Challenge +} -func (m simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { +func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { endpoint.Host = strings.ToLower(endpoint.Host) - challenges := m[endpoint.String()] + m.RLock() + defer m.RUnlock() + challenges := m.Challanges[endpoint.String()] return challenges, nil } -func (m simpleChallengeManager) AddResponse(resp *http.Response) error { +func (m *simpleChallengeManager) AddResponse(resp *http.Response) error { challenges := ResponseChallenges(resp) if resp.Request == nil { return fmt.Errorf("missing request reference") @@ -65,7 +73,9 @@ func (m simpleChallengeManager) AddResponse(resp *http.Response) error { Host: strings.ToLower(resp.Request.URL.Host), Scheme: resp.Request.URL.Scheme, } - m[urlCopy.String()] = challenges + m.Lock() + defer m.Unlock() + m.Challanges[urlCopy.String()] = challenges return nil } diff --git a/registry/client/auth/authchallenge_test.go b/registry/client/auth/authchallenge_test.go index 953ed5b4..e4f81d28 100644 --- a/registry/client/auth/authchallenge_test.go +++ b/registry/client/auth/authchallenge_test.go @@ -6,6 +6,7 @@ import ( "net/url" "strings" "testing" + "sync" ) func TestAuthChallengeParse(t *testing.T) { @@ -43,6 +44,7 @@ func TestAuthChallengeParse(t *testing.T) { func TestAuthChallengeNormalization(t *testing.T) { testAuthChallengeNormalization(t, "reg.EXAMPLE.com") testAuthChallengeNormalization(t, "bɿɒʜɔiɿ-ɿɘƚƨim-ƚol-ɒ-ƨʞnɒʜƚ.com") + testAuthChallengeConcurrent(t, "reg.EXAMPLE.com") } func testAuthChallengeNormalization(t *testing.T, host string) { @@ -79,3 +81,58 @@ func testAuthChallengeNormalization(t *testing.T, host string) { t.Fatal("Expected challenge for lower-cased-host URL") } } + + +func testAuthChallengeConcurrent(t *testing.T, host string) { + + scm := NewSimpleChallengeManager() + + url, err := url.Parse(fmt.Sprintf("http://%s/v2/", host)) + if err != nil { + t.Fatal(err) + } + + resp := &http.Response{ + Request: &http.Request{ + URL: url, + }, + Header: make(http.Header), + StatusCode: http.StatusUnauthorized, + } + resp.Header.Add("WWW-Authenticate", fmt.Sprintf("Bearer realm=\"https://%s/token\",service=\"registry.example.com\"", host)) + var s sync.WaitGroup + s.Add(2) + go func() { + i := 200 + for { + //time.Sleep(500 * time.Millisecond) + err = scm.AddResponse(resp) + if err != nil { + t.Fatal(err) + } + i = i -1 + if i < 0{ + break + } + } + s.Done() + }() + go func() { + lowered := *url + lowered.Host = strings.ToLower(lowered.Host) + k:= 200 + for { + _, err := scm.GetChallenges(lowered) + if err != nil { + t.Fatal(err) + } + k = k -1 + if k < 0{ + break + } + } + + s.Done() + }() + s.Wait() +} From ca2b78dc0acacce4c0e4e1013098855dbae42720 Mon Sep 17 00:00:00 2001 From: spacexnice Date: Wed, 24 Aug 2016 09:31:27 +0800 Subject: [PATCH 2/4] adjust for loop Signed-off-by: spacexnice --- registry/client/auth/authchallenge_test.go | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/registry/client/auth/authchallenge_test.go b/registry/client/auth/authchallenge_test.go index e4f81d28..f1b321a7 100644 --- a/registry/client/auth/authchallenge_test.go +++ b/registry/client/auth/authchallenge_test.go @@ -103,35 +103,24 @@ func testAuthChallengeConcurrent(t *testing.T, host string) { var s sync.WaitGroup s.Add(2) go func() { - i := 200 - for { - //time.Sleep(500 * time.Millisecond) + + for i:=0 ; i<200; i++ { err = scm.AddResponse(resp) if err != nil { t.Fatal(err) } - i = i -1 - if i < 0{ - break - } } s.Done() }() go func() { lowered := *url lowered.Host = strings.ToLower(lowered.Host) - k:= 200 - for { + for k := 0; k < 200 ; k++ { _, err := scm.GetChallenges(lowered) if err != nil { t.Fatal(err) } - k = k -1 - if k < 0{ - break - } } - s.Done() }() s.Wait() From 22cf89c02b2e4390cfe574960030a3705847410f Mon Sep 17 00:00:00 2001 From: spacexnice Date: Thu, 25 Aug 2016 07:34:36 +0800 Subject: [PATCH 3/4] gofmt -s do code format Signed-off-by: spacexnice --- registry/client/auth/authchallenge.go | 4 ++-- registry/client/auth/authchallenge_test.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/registry/client/auth/authchallenge.go b/registry/client/auth/authchallenge.go index 4dbda9e0..e8cdef7f 100644 --- a/registry/client/auth/authchallenge.go +++ b/registry/client/auth/authchallenge.go @@ -49,9 +49,9 @@ func NewSimpleChallengeManager() ChallengeManager { } } -type simpleChallengeManager struct{ +type simpleChallengeManager struct { sync.RWMutex - Challanges map[string][]Challenge + Challanges map[string][]Challenge } func (m *simpleChallengeManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { diff --git a/registry/client/auth/authchallenge_test.go b/registry/client/auth/authchallenge_test.go index f1b321a7..862b717b 100644 --- a/registry/client/auth/authchallenge_test.go +++ b/registry/client/auth/authchallenge_test.go @@ -5,8 +5,8 @@ import ( "net/http" "net/url" "strings" - "testing" "sync" + "testing" ) func TestAuthChallengeParse(t *testing.T) { @@ -82,7 +82,6 @@ func testAuthChallengeNormalization(t *testing.T, host string) { } } - func testAuthChallengeConcurrent(t *testing.T, host string) { scm := NewSimpleChallengeManager() @@ -104,7 +103,7 @@ func testAuthChallengeConcurrent(t *testing.T, host string) { s.Add(2) go func() { - for i:=0 ; i<200; i++ { + for i := 0; i < 200; i++ { err = scm.AddResponse(resp) if err != nil { t.Fatal(err) @@ -115,7 +114,7 @@ func testAuthChallengeConcurrent(t *testing.T, host string) { go func() { lowered := *url lowered.Host = strings.ToLower(lowered.Host) - for k := 0; k < 200 ; k++ { + for k := 0; k < 200; k++ { _, err := scm.GetChallenges(lowered) if err != nil { t.Fatal(err) From 68243306fb578a2e9d6ad3463a267eab02113fd8 Mon Sep 17 00:00:00 2001 From: spacexnice Date: Fri, 26 Aug 2016 09:41:54 +0800 Subject: [PATCH 4/4] correct onerror behavior Signed-off-by: spacexnice --- registry/client/auth/authchallenge_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/registry/client/auth/authchallenge_test.go b/registry/client/auth/authchallenge_test.go index 862b717b..e767ed74 100644 --- a/registry/client/auth/authchallenge_test.go +++ b/registry/client/auth/authchallenge_test.go @@ -102,25 +102,24 @@ func testAuthChallengeConcurrent(t *testing.T, host string) { var s sync.WaitGroup s.Add(2) go func() { - + defer s.Done() for i := 0; i < 200; i++ { err = scm.AddResponse(resp) if err != nil { - t.Fatal(err) + t.Error(err) } } - s.Done() }() go func() { + defer s.Done() lowered := *url lowered.Host = strings.ToLower(lowered.Host) for k := 0; k < 200; k++ { _, err := scm.GetChallenges(lowered) if err != nil { - t.Fatal(err) + t.Error(err) } } - s.Done() }() s.Wait() }