handlers.*LemonsqueezyHandler.handleRequest   C
last analyzed

Complexity

Conditions 10

Size

Total Lines 33
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 29
dl 0
loc 33
rs 5.9999
c 0
b 0
f 0
nop 2

How to fix   Complexity   

Complexity

Complex classes like handlers.*LemonsqueezyHandler.handleRequest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package handlers
2
3
import (
4
	"context"
5
	"encoding/json"
6
	"fmt"
7
8
	"github.com/NdoleStudio/httpsms/pkg/services"
9
	"github.com/NdoleStudio/httpsms/pkg/telemetry"
10
	"github.com/NdoleStudio/httpsms/pkg/validators"
11
	lemonsqueezy "github.com/NdoleStudio/lemonsqueezy-go"
12
	"github.com/davecgh/go-spew/spew"
13
	"github.com/gofiber/fiber/v2"
14
	"github.com/palantir/stacktrace"
15
)
16
17
// LemonsqueezyHandler handles lemonsqueezy events
18
type LemonsqueezyHandler struct {
19
	handler
20
	logger    telemetry.Logger
21
	tracer    telemetry.Tracer
22
	service   *services.LemonsqueezyService
23
	validator *validators.LemonsqueezyHandlerValidator
24
}
25
26
// NewLemonsqueezyHandler creates a new LemonsqueezyHandler
27
func NewLemonsqueezyHandler(
28
	logger telemetry.Logger,
29
	tracer telemetry.Tracer,
30
	service *services.LemonsqueezyService,
31
	validator *validators.LemonsqueezyHandlerValidator,
32
) (h *LemonsqueezyHandler) {
33
	return &LemonsqueezyHandler{
34
		logger:    logger.WithService(fmt.Sprintf("%T", h)),
35
		tracer:    tracer,
36
		service:   service,
37
		validator: validator,
38
	}
39
}
40
41
// RegisterRoutes registers the routes for the MessageHandler
42
func (h *LemonsqueezyHandler) RegisterRoutes(app *fiber.App, middlewares ...fiber.Handler) {
43
	router := app.Group("lemonsqueezy")
44
	router.Post("/event", h.computeRoute(middlewares, h.Event)...)
45
}
46
47
// Event handles lemonsqueezy events
48
func (h *LemonsqueezyHandler) Event(c *fiber.Ctx) error {
49
	ctx, span, ctxLogger := h.tracer.StartFromFiberCtxWithLogger(c, h.logger)
50
	defer span.End()
51
52
	signature := c.Get("X-Signature")
53
	if errors := h.validator.ValidateEvent(ctx, signature, c.Body()); len(errors) != 0 {
54
		msg := fmt.Sprintf("validation errors [%s], while storing request [%s] and signature [%s]", spew.Sdump(errors), c.Body(), signature)
55
		ctxLogger.Warn(stacktrace.NewError(msg))
56
		return h.responseUnprocessableEntity(c, errors, "validation errors while storing lemonsqueezy event")
57
	}
58
59
	if err := h.handleRequest(ctx, c); err != nil {
60
		msg := fmt.Sprintf("cannot handle lemonsqueezy event [%s]", c.Body())
61
		ctxLogger.Error(stacktrace.Propagate(err, msg))
62
		return h.responseInternalServerError(c)
63
	}
64
65
	return h.responseNoContent(c, "event consumed successfully")
66
}
67
68
func (h *LemonsqueezyHandler) handleRequest(ctx context.Context, c *fiber.Ctx) error {
69
	eventName := c.Get("X-Event-Name")
70
	switch eventName {
71
	case "subscription_created":
72
		var request lemonsqueezy.WebhookRequestSubscription
73
		err := json.Unmarshal(c.Body(), &request)
74
		if err != nil {
75
			return stacktrace.Propagate(err, fmt.Sprintf("cannot marshall [%s] to [%T]", c.Body(), request))
76
		}
77
		return h.service.HandleSubscriptionCreatedEvent(ctx, c.OriginalURL(), &request)
78
	case "subscription_cancelled":
79
		var request lemonsqueezy.WebhookRequestSubscription
80
		err := json.Unmarshal(c.Body(), &request)
81
		if err != nil {
82
			return stacktrace.Propagate(err, fmt.Sprintf("cannot marshall [%s] to [%T]", c.Body(), request))
83
		}
84
		return h.service.HandleSubscriptionCanceledEvent(ctx, c.OriginalURL(), &request)
85
	case "subscription_expired":
86
		var request lemonsqueezy.WebhookRequestSubscription
87
		err := json.Unmarshal(c.Body(), &request)
88
		if err != nil {
89
			return stacktrace.Propagate(err, fmt.Sprintf("cannot marshall [%s] to [%T]", c.Body(), request))
90
		}
91
		return h.service.HandleSubscriptionExpiredEvent(ctx, c.OriginalURL(), &request)
92
	case "subscription_updated":
93
		var request lemonsqueezy.WebhookRequestSubscription
94
		err := json.Unmarshal(c.Body(), &request)
95
		if err != nil {
96
			return stacktrace.Propagate(err, fmt.Sprintf("cannot marshall [%s] to [%T]", c.Body(), request))
97
		}
98
		return h.service.HandleSubscriptionUpdatedEvent(ctx, c.OriginalURL(), &request)
99
	default:
100
		return stacktrace.NewError(fmt.Sprintf("invalid event [%s] received with request [%s]", eventName, c.Body()))
101
	}
102
}
103