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  }