Merge remote-tracking branch 'upstream/master'
diff --git a/chain.go b/chain.go
index 6ae8c26..f3afddf 100644
--- a/chain.go
+++ b/chain.go
@@ -92,3 +92,32 @@
 	newChain := New(newCons...)
 	return newChain
 }
+
+// AppendChain extends a chain, adding the specified chains
+// as the last ones in the request flow.
+//
+// AppendChain returns a new chain, leaving the original one untouched.
+//
+//     stdChain := alice.New(m1, m2)
+//     ext1Chain := alice.New(m3, m4)
+//     ext2Chain := stdChain.AppendChain(ext1Chain)
+//     // requests in stdChain go  m1 -> m2
+//     // requests in ext1Chain go m3 -> m4
+//     // requests in ext2Chain go m1 -> m2 -> m3 -> m4
+//
+// Another example:
+//  aHtmlAfterNosurf := alice.New(m2)
+// 	aHtml := alice.New(m1, func(h http.Handler) http.Handler {
+// 		csrf := nosurf.New(h)
+// 		csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail))
+// 		return csrf
+// 	}).AppendChain(aHtmlAfterNosurf)
+//		// requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler
+//		// requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail
+func (c Chain) AppendChain(chains ...Chain) Chain {
+	newChain := c
+	for _, ch := range chains {
+		newChain = newChain.Append(ch.constructors...)
+	}
+	return newChain
+}