pomerium/internal/tripper/chain.go
Bobby DeSimone ba14ea246d
*: remove import path comments (#545)
- import path comments are obsoleted by the go.mod file's module statement

Signed-off-by: Bobby DeSimone <bobbydesimone@gmail.com>
2020-03-16 10:13:47 -07:00

69 lines
2.3 KiB
Go

package tripper
import "net/http"
// Constructor is a type alias for func(http.RoundTripper) http.RoundTripper
type Constructor func(http.RoundTripper) http.RoundTripper
// Chain acts as a list of http.RoundTripper constructors.
// Chain is effectively immutable:
// once created, it will always hold
// the same set of constructors in the same order.
type Chain struct {
constructors []Constructor
}
// NewChain creates a new chain,
// memorizing the given list of tripper constructors.
// New serves no other function,
// constructors are only called upon a call to Then().
func NewChain(constructors ...Constructor) Chain {
return Chain{append([]Constructor(nil), constructors...)}
}
// Then chains the trippers and returns the final http.RoundTripper.
// NewChain(m1, m2, m3).Then(h)
// is equivalent to:
// m1(m2(m3(h)))
// When the request comes in, it will be passed to m1, then m2, then m3
// and finally, the given roundtripper
// (assuming every tripper calls the following one).
//
// A chain can be safely reused by calling Then() several times.
// stdStack := tripper.NewChain(ratelimitTripper, csrfTripper)
// tracePipe = stdStack.Then(traceTripper)
// authPipe = stdStack.Then(authTripper)
// Note that constructors are called on every call to Then()
// and thus several instances of the same tripper will be created
// when a chain is reused in this way.
// For proper tripper implementations, this should cause no problems.
//
// Then() treats nil as http.DefaultTransport.
func (c Chain) Then(h http.RoundTripper) http.RoundTripper {
if h == nil {
h = http.DefaultTransport
}
for i := range c.constructors {
h = c.constructors[len(c.constructors)-1-i](h)
}
return h
}
// 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 := middleware.NewChain(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, 0, len(c.constructors)+len(constructors))
newCons = append(newCons, c.constructors...)
newCons = append(newCons, constructors...)
return Chain{newCons}
}