Append() method
diff --git a/chain.go b/chain.go index 04a17f7..d675546 100644 --- a/chain.go +++ b/chain.go
@@ -59,3 +59,21 @@ return final } + +// Append extends a chain, adding the specified constructors +// as the last ones in the request flow. +// +// Append returns a new chain, leaving the original one untouched. +// +// stdChain := alice.New(m1, m2) +// extChain := stdChain.Append(m3, m4) +// // requests in stdChain go m1 -> m2 +// // requests in extChain go m1 -> m2 -> m3 -> m4 +func (c Chain) Append(constructors ...Constructor) Chain { + newCons := make([]Constructor, len(c.constructors)) + copy(newCons, c.constructors) + newCons = append(newCons, constructors...) + + newChain := New(newCons...) + return newChain +}
diff --git a/chain_test.go b/chain_test.go index 8c57896..d78b1d9 100644 --- a/chain_test.go +++ b/chain_test.go
@@ -21,6 +21,10 @@ } } +var testApp = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("app\n")) +}) + // Tests creating a new chain func TestNew(t *testing.T) { c1 := func(h http.Handler) http.Handler { @@ -40,10 +44,9 @@ func TestThenWorksWithNoMiddleware(t *testing.T) { assert.NotPanics(t, func() { chain := New() - app := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) - final := chain.Then(app) + final := chain.Then(testApp) - assert.Equal(t, final, app) + assert.Equal(t, final, testApp) }) } @@ -56,11 +59,8 @@ t1 := tagMiddleware("t1\n") t2 := tagMiddleware("t2\n") t3 := tagMiddleware("t3\n") - app := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("app\n")) - }) - chained := New(t1, t2, t3).Then(app) + chained := New(t1, t2, t3).Then(testApp) w := httptest.NewRecorder() r, err := http.NewRequest("GET", "/", nil) @@ -72,3 +72,30 @@ assert.Equal(t, w.Body.String(), "t1\nt2\nt3\napp\n") } + +func TestAppendAddsHandlersCorrectly(t *testing.T) { + chain := New(tagMiddleware("t1\n"), tagMiddleware("t2\n")) + newChain := chain.Append(tagMiddleware("t3\n"), tagMiddleware("t4\n")) + + assert.Equal(t, len(chain.constructors), 2) + assert.Equal(t, len(newChain.constructors), 4) + + chained := newChain.Then(testApp) + + w := httptest.NewRecorder() + r, err := http.NewRequest("GET", "/", nil) + if err != nil { + t.Fatal(err) + } + + chained.ServeHTTP(w, r) + + assert.Equal(t, w.Body.String(), "t1\nt2\nt3\nt4\napp\n") +} + +func TestAppendRespectsImmutability(t *testing.T) { + chain := New(tagMiddleware("")) + newChain := chain.Append(tagMiddleware("")) + + assert.NotEqual(t, &chain.constructors[0], &newChain.constructors[0]) +}