43 lines
1.3 KiB
Go
43 lines
1.3 KiB
Go
package reloader
|
|
|
|
import (
|
|
"net/http"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// AtomicHandler provides an atomic http.Handler implementation, allowing safe
|
|
// handler replacement at runtime. AtomicHandler must be initialized with a call
|
|
// to NewAtomicHandler. It will never panic and is safe for concurrent use.
|
|
type AtomicHandler struct {
|
|
val atomic.Value
|
|
}
|
|
|
|
// atomicHandlerValue is the value stored within an atomicHandler.
|
|
type atomicHandlerValue struct{ http.Handler }
|
|
|
|
// NewAtomicHandler creates a new AtomicHandler ready for use.
|
|
func NewAtomicHandler(h http.Handler) *AtomicHandler {
|
|
ah := new(AtomicHandler)
|
|
ah.Store(h)
|
|
return ah
|
|
}
|
|
|
|
// String implements fmt.Stringer by returning a string literal.
|
|
func (ah *AtomicHandler) String() string { return "reloader.AtomicHandler" }
|
|
|
|
// Store will update this http.Handler to serve future requests using h.
|
|
func (ah *AtomicHandler) Store(h http.Handler) {
|
|
ah.val.Store(&atomicHandlerValue{h})
|
|
}
|
|
|
|
// load will return the underlying http.Handler used to serve requests.
|
|
func (ah *AtomicHandler) load() http.Handler {
|
|
return ah.val.Load().(*atomicHandlerValue).Handler
|
|
}
|
|
|
|
// ServeHTTP implements the standard libraries http.Handler interface by
|
|
// atomically passing the request along to the most recently stored handler.
|
|
func (ah *AtomicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
ah.load().ServeHTTP(w, r)
|
|
}
|