From d028df449dd7cb06bf9a0b8ee987ede8ece3081a Mon Sep 17 00:00:00 2001 From: Pierre Rousset Date: Mon, 16 Nov 2020 16:02:42 +0900 Subject: [PATCH] Add CORS AllowOriginFunc documentation and recipe --- cookbook/cors/origin-func/server.go | 43 +++++++++++++++++++++++ cookbook/cors/{ => origin-list}/server.go | 0 website/content/cookbook/cors.md | 11 ++++-- website/content/middleware/cors.md | 21 +++++++---- 4 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 cookbook/cors/origin-func/server.go rename cookbook/cors/{ => origin-list}/server.go (100%) diff --git a/cookbook/cors/origin-func/server.go b/cookbook/cors/origin-func/server.go new file mode 100644 index 00000000..7098ebb1 --- /dev/null +++ b/cookbook/cors/origin-func/server.go @@ -0,0 +1,43 @@ +package main + +import ( + "net/http" + "regexp" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +var ( + users = []string{"Joe", "Veer", "Zion"} +) + +func getUsers(c echo.Context) error { + return c.JSON(http.StatusOK, users) +} + +// allowOrigin takes the origin as an argument and returns true if the origin +// is allowed or false otherwise. +func allowOrigin(origin string) (bool, error) { + // In this example we use a regular expression but we can imagine various + // kind of custom logic. For example, an external datasource could be used + // to maintain the list of allowed origins. + return regexp.MatchString(`^https:\/\/labstack\.(net|com)$`, origin) +} + +func main() { + e := echo.New() + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + + // CORS restricted with a custom function to allow origins + // and with the GET, PUT, POST or DELETE methods allowed. + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOriginFunc: allowOrigin, + AllowMethods: []string{http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete}, + })) + + e.GET("/api/users", getUsers) + + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/cookbook/cors/server.go b/cookbook/cors/origin-list/server.go similarity index 100% rename from cookbook/cors/server.go rename to cookbook/cors/origin-list/server.go diff --git a/website/content/cookbook/cors.md b/website/content/cookbook/cors.md index 22e15c1f..0a0d2e0f 100644 --- a/website/content/cookbook/cors.md +++ b/website/content/cookbook/cors.md @@ -7,14 +7,21 @@ description = "CORS recipe for Echo" parent = "cookbook" +++ -## Server +## Server using a list of allowed origins `server.go` -{{< embed "cors/server.go" >}} +{{< embed "cors/origin-list/server.go" >}} + +## Server using a custom function to allow origins + +`server.go` + +{{< embed "cors/origin-func/server.go" >}} ## [Source Code]({{< source "cors" >}}) ## Maintainers - [vishr](https://github.com/vishr) +- [curvegrid](https://github.com/curvegrid) \ No newline at end of file diff --git a/website/content/middleware/cors.md b/website/content/middleware/cors.md index 923e06f8..f4955e9d 100644 --- a/website/content/middleware/cors.md +++ b/website/content/middleware/cors.md @@ -35,34 +35,41 @@ CORSConfig struct { // AllowOrigin defines a list of origins that may access the resource. // Optional. Default value []string{"*"}. - AllowOrigins []string `json:"allow_origins"` + AllowOrigins []string `yaml:"allow_origins"` + + // AllowOriginFunc is a custom function to validate the origin. It takes the + // origin as an argument and returns true if allowed or false otherwise. If + // an error is returned, it is returned by the handler. If this option is + // set, AllowOrigins is ignored. + // Optional. + AllowOriginFunc func(origin string) (bool, error) `yaml:"allow_origin_func"` // AllowMethods defines a list methods allowed when accessing the resource. // This is used in response to a preflight request. // Optional. Default value DefaultCORSConfig.AllowMethods. - AllowMethods []string `json:"allow_methods"` + AllowMethods []string `yaml:"allow_methods"` // AllowHeaders defines a list of request headers that can be used when - // making the actual request. This in response to a preflight request. + // making the actual request. This is in response to a preflight request. // Optional. Default value []string{}. - AllowHeaders []string `json:"allow_headers"` + AllowHeaders []string `yaml:"allow_headers"` // AllowCredentials indicates whether or not the response to the request // can be exposed when the credentials flag is true. When used as part of // a response to a preflight request, this indicates whether or not the // actual request can be made using credentials. // Optional. Default value false. - AllowCredentials bool `json:"allow_credentials"` + AllowCredentials bool `yaml:"allow_credentials"` // ExposeHeaders defines a whitelist headers that clients are allowed to // access. // Optional. Default value []string{}. - ExposeHeaders []string `json:"expose_headers"` + ExposeHeaders []string `yaml:"expose_headers"` // MaxAge indicates how long (in seconds) the results of a preflight request // can be cached. // Optional. Default value 0. - MaxAge int `json:"max_age"` + MaxAge int `yaml:"max_age"` } ```