Thanks @kync for taking the time. There may in fact just be another way to solve the problem I’m trying to solve.
We are building a HTTP server for receiving requests from webhooks configured on various different vendor platforms. The goal is to have all the vendors specific handlers built to process and transform the requests to relay them to another service. We would like to be able to enable these on a per handler basis in a configuration file so that there are not endpoints registered that are not being used.
I’m thinking of way logstash inputs, filters and outputs are configured and enabled. In logstash you would have a configuration file that looks like
there is nothing wrong with your solution until you need to distinguish vendors via custom rules. How I would do it:
type StripeHandler struct {
Active bool
}
func (s StripeHandler) Matches(r *http.Request) bool {
// you can check a key in the query string, hostname whatever you need to identify
if r.URL.Path == "/stripe" {
return true
}
return false
}
func (s StripeHandler) IsActive() bool {
return s.Active
}
func (s StripeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println("stripe handled")
}
type PaypalHandler struct {
Active bool
}
func (p PaypalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println("paypal handled")
}
func (p PaypalHandler) IsActive() bool {
return p.Active
}
func (p PaypalHandler) Matches(r *http.Request) bool {
if r.URL.Path == "/paypal" {
return true
}
return false
}
type VendorHandler interface {
IsActive() bool
Matches(r *http.Request) bool
ServeHTTP(w http.ResponseWriter, r *http.Request)
}
type WebhookHandler struct {
handlers []VendorHandler
}
func (wh *WebhookHandler) Register(h VendorHandler) {
wh.handlers = append(wh.handlers, h)
}
func (wh *WebhookHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, handler := range wh.handlers {
if handler.IsActive() && handler.Matches(r) {
handler.ServeHTTP(w, r)
break
}
}
}
func main() {
configs := map[string]bool{"stripe": true, "paypal": false}
wh := WebhookHandler{}
for key, active := range configs {
if !active {
continue
}
switch key {
case "stripe":
{
wh.Register(StripeHandler{Active: true})
}
case "paypal":
{
wh.Register(PaypalHandler{Active: true})
}
}
}
uri, _ := url.Parse("https://play.golang.org/stripe")
wh.ServeHTTP(nil, &http.Request{URL: uri})
uri, _ = url.Parse("https://play.golang.org/paypal")
wh.ServeHTTP(nil, &http.Request{URL: uri})
fmt.Println()
}
I would go with above solution, not because it is better than yours, I like to avoid to configure services via a configuration file as much as possible.