diff --git a/backend/main.go b/backend/main.go index ea5b665..ccef420 100644 --- a/backend/main.go +++ b/backend/main.go @@ -1,9 +1,9 @@ package main import ( + "fmt" "net/http" "os" - "fmt" "github.com/go-chi/chi/v5" ) @@ -11,15 +11,16 @@ import ( func main() { connectDB() - r := chi.NewRouter() + router := chi.NewRouter() - r.Use(authMiddleware) + router.Use(logMiddleware) + router.Use(authMiddleware) // routes - r.Get("/quotes", getQuotes) - r.Post("/quotes", createQuote) - r.Put("/quotes/{id}", updateQuote) - r.Delete("/quotes/{id}", deleteQuote) + router.Get("/quotes", getQuotes) + router.Post("/quotes", createQuote) + router.Put("/quotes/{id}", updateQuote) + router.Delete("/quotes/{id}", deleteQuote) port := os.Getenv("PORT") if port == "" { @@ -27,5 +28,5 @@ func main() { } fmt.Println("started and listening on localhost:" + port) - http.ListenAndServe(":"+port, r) -} \ No newline at end of file + http.ListenAndServe(":"+port, router) +} diff --git a/backend/middleware.go b/backend/middleware.go index fbf2d45..83ac4a3 100644 --- a/backend/middleware.go +++ b/backend/middleware.go @@ -1,8 +1,14 @@ package main import ( + "bytes" + "fmt" + "io" "net/http" "os" + "time" + + "crypto/subtle" ) func authMiddleware(next http.Handler) http.Handler { @@ -18,7 +24,7 @@ func authMiddleware(next http.Handler) http.Handler { expectedHeader := "Bearer " + expectedKey - if authHeader != expectedHeader { + if subtle.ConstantTimeCompare([]byte(authHeader), []byte(expectedHeader)) != 1 { http.Error(w, "unauthorized", http.StatusUnauthorized) return } @@ -26,3 +32,32 @@ func authMiddleware(next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } + +func logMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + reqMethod := r.Method + reqUrl := r.URL.String() + reqIp := r.RemoteAddr + reqHeaderContentType := r.Header.Get("Content-Type") + defer r.Body.Close() + bodyBytes, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "[log] Failed to read body", http.StatusBadRequest) + return + } + + fmt.Printf("\n[%s] %s request on %s\n", reqIp, reqMethod, reqUrl) + fmt.Println("Timestamp (UTC): " + time.Now().UTC().String()) + fmt.Println("Header Content-Type: " + reqHeaderContentType) + if len(bodyBytes) == 0 { + fmt.Println("Body: ") + } else { + fmt.Println("Body: " + string(bodyBytes)) + } + + // restore the request body for later + r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + + next.ServeHTTP(w, r) + }) +}