package http import ( "fmt" "image/jpeg" "justcaptcha/pkg/captcha" "justcaptcha/pkg/captcha/inmemdb" "justcaptcha/pkg/dwcaptcha" "net/http" "time" ) const errMsgWrongAnswer = "An answer provided was wrong" const errMsgImageNotFound = "cannot get an image for a non-existing CAPTCHA" type CaptchaHandlers struct { expiry time.Duration } func NewCaptchaHandlers(expiry time.Duration) *CaptchaHandlers { inmemdb.SetExpiry(expiry) return &CaptchaHandlers{expiry: expiry} } func (h *CaptchaHandlers) New(w http.ResponseWriter, r *http.Request) { dc := dwcaptcha.NewDwellingCaptcha(h.expiry) _, id := inmemdb.New(r.RemoteAddr, dc) w.WriteHeader(http.StatusCreated) fmt.Fprint(w, id) } func (h *CaptchaHandlers) Image(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(GetURLParam(r, "captcha")) captchaStyle := r.URL.Query().Get("style") captchaImage := inmemdb.Image(captchaID, captchaStyle) if captchaImage == nil { http.Error(w, errMsgImageNotFound, http.StatusNotFound) return } w.Header().Add("Content-Disposition", "inline; filename=\""+string(captchaID)+"\"") jpeg.Encode(w, *captchaImage, &jpeg.Options{Quality: 20}) } func (h *CaptchaHandlers) Solve(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(GetURLParam(r, "captcha")) r.ParseForm() answer := captcha.Answer(r.FormValue("answer")) if ok := inmemdb.Solve(captchaID, answer); !ok { http.Error(w, errMsgWrongAnswer, http.StatusForbidden) return } w.WriteHeader(http.StatusAccepted) } func (h *CaptchaHandlers) IsSolved(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(GetURLParam(r, "captcha")) isJustRemove := r.URL.Query().Has("remove") if isJustRemove { inmemdb.Remove(captchaID) w.WriteHeader(http.StatusNoContent) return } if solved := inmemdb.IsSolved(captchaID); !solved { http.Error(w, errMsgWrongAnswer, http.StatusForbidden) return } w.WriteHeader(http.StatusNoContent) }