From fba33432e6303c043c07e56d6bf327df2a516b49 Mon Sep 17 00:00:00 2001 From: Levatax Date: Wed, 23 Oct 2024 13:11:29 +0000 Subject: [PATCH] feat(hcaptcha): add custom error handling and fix documentation - Extend the Config structure to include a ValidateFunc field for custom error handling. - Update the Validate method to call the custom function if provided. - Fix documentation to clarify the correct order of middleware and handler in usage examples. This change allows users to define custom validation responses for HCaptcha, providing more flexibility in error handling. --- hcaptcha/README.md | 29 ++++++++++++++++++++++------- hcaptcha/config.go | 2 ++ hcaptcha/hcaptcha.go | 15 ++++++++++++--- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/hcaptcha/README.md b/hcaptcha/README.md index 952956e0..14542031 100644 --- a/hcaptcha/README.md +++ b/hcaptcha/README.md @@ -39,11 +39,12 @@ hcaptcha.New(config hcaptcha.Config) fiber.Handler ## Config -| Property | Type | Description | Default | -|:----------------|:----------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------| -| SecretKey | `string` | The secret key you obtained from the HCaptcha admin panel. This field must not be empty. | `""` | -| ResponseKeyFunc | `func(fiber.Ctx) (string, error)` | ResponseKeyFunc should return the token that captcha provides upon successful solving. By default, it gets the token from the body by parsing a JSON request and returns the `hcaptcha_token` field. | `hcaptcha.DefaultResponseKeyFunc` | -| SiteVerifyURL | `string` | This property specifies the API resource used for token authentication. | `https://api.hcaptcha.com/siteverify` | +| Property | Type | Description | Default | +|:-----------------|:----------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------| +| SecretKey | `string` | The secret key you obtained from the HCaptcha admin panel. This field must not be empty. | `""` | +| ResponseKeyFunc | `func(fiber.Ctx) (string, error)`| ResponseKeyFunc should return the token that captcha provides upon successful solving. By default, it gets the token from the body by parsing a JSON request and returns the `hcaptcha_token` field. | `hcaptcha.DefaultResponseKeyFunc` | +| SiteVerifyURL | `string` | This property specifies the API resource used for token authentication. | `https://api.hcaptcha.com/siteverify` | +| ValidateFunc | `func(bool, fiber.Ctx) error` | A custom validation function that allows you to define the behavior upon validation success or failure. If set, it will be called with the validation result and the context. | `nil` | ## Example @@ -51,6 +52,7 @@ hcaptcha.New(config hcaptcha.Config) fiber.Handler package main import ( + "errors" "github.com/gofiber/contrib/hcaptcha" "github.com/gofiber/fiber/v3" "log" @@ -63,9 +65,22 @@ const ( func main() { app := fiber.New() + + // Create HCaptcha middleware captcha := hcaptcha.New(hcaptcha.Config{ // Must set the secret key SecretKey: TestSecretKey, + // Custom validation function (optional) + ValidateFunc: func(success bool, c fiber.Ctx) error { + if !success { + c.Status(fiber.StatusForbidden).JSON(fiber.Map{ + "error": "Custom error: validation failed, please try again", + "details": "The HCaptcha validation was unsuccessful.", + }) + return errors.New("custom error: validation failed") + } + return nil + }, }) app.Get("/api/", func(c fiber.Ctx) error { @@ -74,9 +89,9 @@ func main() { }) }) - app.Post("/api/robots-excluded", func(c fiber.Ctx) error { + app.Post("/api/submit", captcha, func(c fiber.Ctx) error { return c.SendString("You are not a robot") - }, captcha) + }) log.Fatal(app.Listen(":3000")) } diff --git a/hcaptcha/config.go b/hcaptcha/config.go index 91bff4ed..3f5af07f 100644 --- a/hcaptcha/config.go +++ b/hcaptcha/config.go @@ -19,6 +19,8 @@ type Config struct { // SiteVerifyURL is the endpoint URL where the program should verify the given token // default value is: "https://api.hcaptcha.com/siteverify" SiteVerifyURL string + // ValidateFunc allows custom validation logic based on the HCaptcha validation result and the context + ValidateFunc func(success bool, c fiber.Ctx) error } // DefaultResponseKeyFunc is the default function to get the HCaptcha token from the request body diff --git a/hcaptcha/hcaptcha.go b/hcaptcha/hcaptcha.go index 2a1218ba..220fa3e2 100644 --- a/hcaptcha/hcaptcha.go +++ b/hcaptcha/hcaptcha.go @@ -69,9 +69,18 @@ func (h *HCaptcha) Validate(c fiber.Ctx) error { 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") + // Use custom ValidateFunc if defined, otherwise default behavior + if h.ValidateFunc != nil { + if err := h.ValidateFunc(o.Success, c); err != nil { + // If the custom ValidateFunc returns an error, set the response status code accordingly + c.Status(fiber.StatusForbidden) + return err + } + } else { + if !o.Success { + c.Status(fiber.StatusForbidden) + return errors.New("unable to check that you are not a robot") + } } return c.Next()