A Minimal Working Go CORS Implementation
There seems to be a few approachs to getting CORS working cleanly on Go with Gin but none of them seemed to quite work for me with a React front-end. So after much frustration messing about with this, I figured I’d write a quick article even just for personal reference the next time I forget how to do this.
Step 1: Create a Middleware
This is for me the neatest way to add header values across a wide range of routes. Since this is minimal, it is not necessarily the most secure way to do this. But it should be pretty obvious how to modify this to add in a correct production configuration.
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "access-control-allow-origin, access-control-allow-headers")
c.Next()
}
}
Step 2: Create your Preflight Response
The preflight request is what usually catches me out. You may be able to avoid preflights if you use very simple requests but for the most part you are better off being prepared for preflights. For a minimal implementation, the preflight response should be able to use the same middleware.
func Preflight(c *gin.Context) {
c.JSON(http.StatusNoContent, gin.H{})
}
Step 3: Set up your Routes
Next you need to add in whatever routes you want to add CORS headers. Don’t forget to add in your OPTIONS methods that will be used for your preflight requests.
func main() {
r := gin.Default()
public := r.Group("/api")
public.Use(middlewares.CORSMiddleware())
public.POST("/register", controllers.Register)
public.POST("/login", controllers.Login)
public.OPTIONS("/login", controllers.Preflight)
public.OPTIONS("/register", controllers.Preflight)
protected := r.Group("/api/admin")
protected.Use(middlewares.JwtAuthMiddleware())
protected.Use(middlewares.CORSMiddleware())
protected.GET("/user", controllers.CurrentUser)
err := r.Run(":8080")
if err != nil {
return
}
}