mirror of
https://github.com/rjNemo/payit
synced 2026-06-06 02:16:40 +00:00
feat(web): add logging middleware and refactor handlers
Introduced LoggerMiddleware for HTTP request logging. Refactored handler methods to return http.HandlerFunc for improved composability. Updated route registration and tests to use new handler signatures.
This commit is contained in:
parent
d112a4f6e8
commit
bf721dc130
6 changed files with 77 additions and 47 deletions
|
|
@ -9,7 +9,8 @@ import (
|
|||
"github.com/rjNemo/payit/internal/payments"
|
||||
)
|
||||
|
||||
func (h *Handler) createCheckoutSession(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Handler) createCheckoutSession() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req payments.CheckoutSessionRequest
|
||||
|
||||
if r.Body != nil {
|
||||
|
|
@ -44,3 +45,4 @@ func (h *Handler) createCheckoutSession(w http.ResponseWriter, r *http.Request)
|
|||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func TestCreateCheckoutSessionSuccess(t *testing.T) {
|
|||
req := httptest.NewRequest(http.MethodPost, "/api/checkout", bytes.NewReader(body))
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.createCheckoutSession(rec, req)
|
||||
handler.createCheckoutSession()(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected status 200, got %d", rec.Code)
|
||||
|
|
@ -70,7 +70,7 @@ func TestCreateCheckoutSessionDefaultsQuantity(t *testing.T) {
|
|||
req := httptest.NewRequest(http.MethodPost, "/api/checkout", http.NoBody)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.createCheckoutSession(rec, req)
|
||||
handler.createCheckoutSession()(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected status 200, got %d", rec.Code)
|
||||
|
|
@ -86,7 +86,7 @@ func TestCreateCheckoutSessionRejectsInvalidJSON(t *testing.T) {
|
|||
req := httptest.NewRequest(http.MethodPost, "/api/checkout", bytes.NewBufferString("{"))
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.createCheckoutSession(rec, req)
|
||||
handler.createCheckoutSession()(rec, req)
|
||||
|
||||
if rec.Code != http.StatusBadRequest {
|
||||
t.Fatalf("expected status 400, got %d", rec.Code)
|
||||
|
|
@ -101,7 +101,7 @@ func TestCreateCheckoutSessionStripeFailure(t *testing.T) {
|
|||
req := httptest.NewRequest(http.MethodPost, "/api/checkout", http.NoBody)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.createCheckoutSession(rec, req)
|
||||
handler.createCheckoutSession()(rec, req)
|
||||
|
||||
if rec.Code != http.StatusInternalServerError {
|
||||
t.Fatalf("expected status 500, got %d", rec.Code)
|
||||
|
|
@ -111,7 +111,7 @@ func TestCreateCheckoutSessionStripeFailure(t *testing.T) {
|
|||
func TestCreateCheckoutSessionMethodNotAllowed(t *testing.T) {
|
||||
handler := &Handler{checkout: &fakeCheckoutService{}}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("POST /api/checkout", handler.createCheckoutSession)
|
||||
mux.HandleFunc("POST /api/checkout", handler.createCheckoutSession())
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/checkout", http.NoBody)
|
||||
rec := httptest.NewRecorder()
|
||||
|
|
|
|||
26
internal/web/middleware.go
Normal file
26
internal/web/middleware.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WrappedWriter struct {
|
||||
http.ResponseWriter
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
func (w *WrappedWriter) WriteHeader(statusCode int) {
|
||||
w.StatusCode = statusCode
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func LoggerMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
wrapped := &WrappedWriter{ResponseWriter: w, StatusCode: http.StatusOK}
|
||||
next.ServeHTTP(wrapped, r)
|
||||
log.Printf("%s %s %d %v", r.Method, r.URL.Path, wrapped.StatusCode, time.Since(start))
|
||||
})
|
||||
}
|
||||
|
|
@ -13,7 +13,8 @@ type checkoutPageData struct {
|
|||
Currency string
|
||||
}
|
||||
|
||||
func (h *Handler) renderCheckoutPage(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Handler) renderCheckoutPage() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
price := float64(h.cfg.Product.PriceCents) / 100
|
||||
data := checkoutPageData{
|
||||
ProductName: h.cfg.Product.Name,
|
||||
|
|
@ -28,3 +29,4 @@ func (h *Handler) renderCheckoutPage(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func (h *Handler) registerRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /api/checkout", h.createCheckoutSession)
|
||||
mux.Handle("GET /", http.HandlerFunc(h.renderCheckoutPage))
|
||||
mux.Handle("POST /api/checkout", h.createCheckoutSession())
|
||||
mux.Handle("GET /", h.renderCheckoutPage())
|
||||
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(h.fs))))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,5 +41,5 @@ func NewServer(cfg config.Config) http.Handler {
|
|||
mux := http.NewServeMux()
|
||||
h.registerRoutes(mux)
|
||||
|
||||
return mux
|
||||
return LoggerMiddleware(mux)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue