package captcha import ( "net/http" "text/template" "github.com/yusing/go-proxy/internal/auth" "github.com/yusing/go-proxy/internal/logging" "github.com/yusing/go-proxy/internal/net/gphttp" _ "embed" ) const cookieName = "godoxy_captcha_session" //go:embed captcha.html var captchaPageHTML string var captchaPage = template.Must(template.New("captcha").Parse(captchaPageHTML)) func PreRequest(p Provider, w http.ResponseWriter, r *http.Request) (proceed bool) { // check session sessionID, err := r.Cookie(cookieName) if err == nil { session, ok := CaptchaSessions.Load(sessionID.Value) if ok { if session.expired() { CaptchaSessions.Delete(sessionID.Value) } else { return true } } } if !gphttp.GetAccept(r.Header).AcceptHTML() { gphttp.Forbidden(w, "Captcha is required") return false } if r.Method == http.MethodPost { err := p.Verify(r) if err == nil { session := newCaptchaSession(p) CaptchaSessions.Store(session.ID, session) auth.SetTokenCookie(w, r, cookieName, session.ID, p.SessionExpiry()) http.Redirect(w, r, r.URL.Path, http.StatusFound) return false } gphttp.Unauthorized(w, err.Error()) return false } // captcha challenge err = captchaPage.Execute(w, map[string]any{ "ScriptHTML": p.ScriptHTML(), "FormHTML": p.FormHTML(), }) if err != nil { logging.Error().Err(err).Msg("failed to execute captcha page") } return false }