package captiveportal import ( "net/http" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) func (s *Service) Middleware() func(next http.Handler) http.Handler { registry := s.registry matcher := s.options.Matcher liar := s.options.Liar return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() matches, os, err := matcher.Match(r) if err != nil { panic(errors.WithStack(err)) } logger.Debug( ctx, "applied captive portal matching", logger.F("os", os), logger.F("url", r.URL.String()), logger.F("host", r.Host), logger.F("matches", matches), ) if !matches { next.ServeHTTP(w, r) return } id, err := s.identifier.Identify(r) if err != nil { panic(errors.Wrap(err, ErrClientIdentificationFailed.Error())) } logger.Debug( ctx, "identified captive portal client", logger.F("remoteAddr", r.RemoteAddr), logger.F("id", id), ) registry.Touch(id, os) if registry.IsLying(id) { logger.Debug( ctx, "lying to captive portal client", logger.F("remoteAddr", r.RemoteAddr), logger.F("id", id), ) liar.Handle(os, w, r) return } if registry.IsCaptive(id) { logger.Debug( ctx, "capture captive portal client", logger.F("remoteAddr", r.RemoteAddr), logger.F("id", id), ) // Redirect to configured URL http.Redirect(w, r, s.redirectURL, http.StatusTemporaryRedirect) return } next.ServeHTTP(w, r) } return http.HandlerFunc(fn) } }