package director import ( "context" "net/http" "net/url" "forge.cadoles.com/Cadoles/go-proxy" "forge.cadoles.com/Cadoles/go-proxy/wildcard" "forge.cadoles.com/cadoles/bouncer/internal/store" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) type Director struct { repo store.ProxyRepository } func (d *Director) rewriteRequest(r *http.Request) error { ctx := r.Context() proxies, err := d.getProxies(ctx) if err != nil { return errors.WithStack(err) } var match *url.URL MAIN: for _, p := range proxies { for _, from := range p.From { if matches := wildcard.Match(r.Host, from); !matches { continue } match = p.To break MAIN } } if match == nil { return nil } r.URL.Host = match.Host r.URL.Scheme = match.Scheme return nil } func (d *Director) getProxies(ctx context.Context) ([]*store.Proxy, error) { headers, err := d.repo.QueryProxy(ctx) if err != nil { return nil, errors.WithStack(err) } proxies := make([]*store.Proxy, len(headers)) for i, h := range headers { proxy, err := d.repo.GetProxy(ctx, h.ID) if err != nil { return nil, errors.WithStack(err) } proxies[i] = proxy } return proxies, nil } func (d *Director) Middleware() proxy.Middleware { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { if err := d.rewriteRequest(r); err != nil { logger.Error(r.Context(), "could not rewrite request", logger.E(errors.WithStack(err))) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } next.ServeHTTP(w, r) } return http.HandlerFunc(fn) } } func New(repo store.ProxyRepository) *Director { return &Director{repo} }