Gin API key authentication middleware

Go
package main

import (
	"crypto/subtle"
	"log"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
)

// APIKeyAuth rejects requests without a valid X-API-Key header. The expected
// key is read from the APP_API_KEY environment variable at startup.
func APIKeyAuth() gin.HandlerFunc {
	expected := os.Getenv("APP_API_KEY")
	return func(c *gin.Context) {
		provided := c.GetHeader("X-API-Key")
		if expected == "" || subtle.ConstantTimeCompare([]byte(provided), []byte(expected)) != 1 {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid api key"})
			return
		}
		c.Next()
	}
}

func main() {
	router := gin.New()
	router.Use(gin.Recovery(), APIKeyAuth())
	router.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "pong"})
	})
	log.Fatal(router.Run(":8080"))
}