github.com/xmidt-org/webpa-common@v1.11.9/xhttp/gate/constructor.go (about) 1 package gate 2 3 import ( 4 "net/http" 5 ) 6 7 // constructor is a configurable Alice-style decorator for HTTP handlers that controls 8 // traffic based on the current state of a gate. 9 type constructor struct { 10 g Interface 11 closed http.Handler 12 } 13 14 func (c *constructor) decorate(next http.Handler) http.Handler { 15 return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) { 16 if c.g.Open() { 17 next.ServeHTTP(response, request) 18 } else { 19 c.closed.ServeHTTP(response, request) 20 } 21 }) 22 } 23 24 func defaultClosedHandler(response http.ResponseWriter, _ *http.Request) { 25 response.WriteHeader(http.StatusServiceUnavailable) 26 } 27 28 // ConstructorOption configures a gate decorator 29 type ConstructorOption func(*constructor) 30 31 // WithClosedHandler configures an arbitrary http.Handler that will serve requests when a gate is closed. 32 // If the handler is nil, the internal default is used instead. 33 func WithClosedHandler(closed http.Handler) ConstructorOption { 34 return func(c *constructor) { 35 if closed != nil { 36 c.closed = closed 37 } else { 38 c.closed = http.HandlerFunc(defaultClosedHandler) 39 } 40 } 41 } 42 43 // NewConstructor returns an Alice-style constructor which decorates HTTP handlers with gating logic. If supplied, the closed 44 // handler is invoked instead of the decorated handler whenever the gate is closed. The closed handler may be nil, in which 45 // case a default is used that returns http.StatusServiceUnavailable. 46 // 47 // If g is nil, this function panics. 48 func NewConstructor(g Interface, options ...ConstructorOption) func(http.Handler) http.Handler { 49 if g == nil { 50 panic("A gate is required") 51 } 52 53 c := &constructor{ 54 g: g, 55 closed: http.HandlerFunc(defaultClosedHandler), 56 } 57 58 for _, o := range options { 59 o(c) 60 } 61 62 return c.decorate 63 }