-
Notifications
You must be signed in to change notification settings - Fork 98
/
hcaptcha.go
78 lines (66 loc) 路 2.01 KB
/
hcaptcha.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Package hcaptcha is a simple middleware that checks for an HCaptcha UUID
// and then validates it. It returns an error if the UUID is not valid (the request may have been sent by a robot).
package hcaptcha
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/gofiber/fiber/v3"
"github.com/valyala/fasthttp"
"net/url"
)
// HCaptcha is a middleware handler that checks for an HCaptcha UUID and then validates it.
type HCaptcha struct {
Config
}
// New creates a new HCaptcha middleware handler.
func New(config Config) fiber.Handler {
if config.SiteVerifyURL == "" {
config.SiteVerifyURL = DefaultSiteVerifyURL
}
if config.ResponseKeyFunc == nil {
config.ResponseKeyFunc = DefaultResponseKeyFunc
}
h := &HCaptcha{
config,
}
return h.Validate
}
// Validate checks for an HCaptcha UUID and then validates it.
func (h *HCaptcha) Validate(c fiber.Ctx) error {
token, err := h.ResponseKeyFunc(c)
if err != nil {
c.Status(fiber.StatusBadRequest)
return fmt.Errorf("error retrieving HCaptcha token: %w", err)
}
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.SetBody([]byte(url.Values{
"secret": {h.SecretKey},
"response": {token},
}.Encode()))
req.Header.SetMethod("POST")
req.Header.SetContentType("application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("Accept", "application/json")
req.SetRequestURI(h.SiteVerifyURL)
res := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(res)
// Send the request to the HCaptcha API
if err = fasthttp.Do(req, res); err != nil {
c.Status(fiber.StatusBadRequest)
return fmt.Errorf("error sending request to HCaptcha API: %w", err)
}
o := struct {
Success bool `json:"success"`
}{}
if err = json.NewDecoder(bytes.NewReader(res.Body())).Decode(&o); err != nil {
c.Status(fiber.StatusInternalServerError)
return fmt.Errorf("error decoding HCaptcha API response: %w", err)
}
if !o.Success {
c.Status(fiber.StatusForbidden)
return errors.New("unable to check that you are not a robot")
}
return c.Next()
}