GoDoxy/internal/net/gphttp/middleware/captcha/middleware.go
2025-05-04 17:21:12 +08:00

61 lines
1.4 KiB
Go

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
}