CORS

Hertz provides implementation of CORS middleware.

The CORS (Cross-Origin Resource Sharing) mechanism allows a server to identify any origin other than its own so that browsers can access and load those resources. This mechanism is also used to check whether the server allows the browser to send a real request by sending a “precheck” request through the browser. In the “precheck” request header, there are HTTP methods and headers that the real request will use.

Hertz provides implementation of CORS middleware. The implementation here refers to GIN’s cors.

Install

go get github.com/hertz-contrib/cors

Example

package main

import (
    "time"

    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    // CORS for https://foo.com and https://github.com origins, allowing:
    // - PUT and PATCH methods
    // - Origin header
    // - Credentials share
    // - Preflight requests cached for 12 hours
    h.Use(cors.New(cors.Config{
        AllowOrigins:     []string{"https://foo.com"},
        AllowMethods:     []string{"PUT", "PATCH"},
        AllowHeaders:     []string{"Origin"},
        ExposeHeaders:    []string{"Content-Length"},
        AllowCredentials: true,
        AllowOriginFunc: func(origin string) bool {
            return origin == "https://github.com"
        },
        MaxAge: 12 * time.Hour,
    }))
    h.Spin()
}

Preflight request

For cross-origin access, in the case of a simple request, this is essentially adding an Origin field to the HTTP request header to describe where the source comes from, and the server can respond directly.

For non-simple cross-origin access requests (e.g. request method is PUT or PATCH, Content-Type field type is application/json, etc.), an HTTP preflight request is sent to verify that the client has access to the server before formal communication directly. A preflight request is a browser-initiated action that uses the HTTP Method OPTIONS.

Note: Some of the hertz-cors configurations will only take effect when a preflight request occurs.

Config

Hertz allows clients to access resources across origins through the use of cors middleware. You can finely control the extent to which server-side resources are allowed to be accessed across origins by customizing the configuration parameters of the Config structure. And you can also choose the default configuration of hertz-cors to allow clients from any origin to access resources.

Only part of the optional parameters are configured in the above Example, the full list of parameters for Config is as follows:

Parameter Introduction
AllowAllOrigins The property used to allow clients from any origin to access server-side resources, the default value is false
AllowOrigins The property used to set the list of origins a cross-domain request can be executed from, the default value is []
AllowOriginFunc The property used to set a custom function to validate the origin, if this option is set, the content of AllowOrigins is ignored
AllowMethods The property used to set the list of methods the client is allowed to use with cross-domain requests (takes effect when a preflight request is received)
AllowHeaders The property used to set the list of non-simple headers the client is allowed to use with cross-domain requests, the default value is [] (takes effect when a preflight request is received)
AllowCredentials The property indicates whether the request can include user credentials like cookies, HTTP authentication, or client-side SSL certificates, the default value is false
ExposeHeaders The property used to indicate which headers are safe to expose to the API of a CORS API specification, the default value is []
MaxAge The property used to set how long (in seconds) the results of a preflight request can be cached
AllowWildcard The property used to allow to add of origins like http://some-domain/*, https://api.*, or http://some.*.subdomain.com, the default value is false
AllowBrowserExtensions The property used to allow usage of popular browser extensions schemas, the default value is false
AllowWebSockets The property used to allow usage of WebSocket protocol, the default value is false
AllowFiles The property used to allow usage of file:// schema (dangerous!) use it only when you 100% sure it’s needed, the default value is false

AllowAllOrigins

If the property value is true, all cross-domain requests will be allowed.

When AllowAllOrigins is true, AllowOriginFunc and AllowOrigins must not be used, otherwise, conflicts will occur.

AllowOrigins

The property set a list of origins that can be accessed cross-domain, any cross-domain requests that satisfies the matching logic can access resource (only one * is allowed within each origin).

Conflicts with AllowAllOrigins, only one of which can be configured at a time.

When used together with AllowOriginFunc, AllowOriginFunc takes precedence over AllowOrigins.

If you want to use an origin with wildcards, the AllowWildcard parameter must also be set to true.

Sample Code1:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        AllowOrigins:     []string{"https://foo.com"},
    }))
    h.Spin()
}

Sample Code2:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        AllowWildcard: 	  true,
        AllowOrigins:     []string{"http://some-domain/*"},
    }))
    h.Spin()
}

AllowOriginFunc

It takes the origin as an argument and returns true if allowed or false otherwise.

Conflicts with AllowAllOrigins, only one of which can be configured at a time.

When used together with AllowOrigins, AllowOriginFunc takes precedence over AllowOrigins.

Function signatures:

func(origin string) bool

Sample Code:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        AllowOriginFunc: func(origin string) bool {
            return origin == "https://github.com"
        },
    }))
    h.Spin()
}

AllowMethods

This configuration takes effect only when a preflight request is received and is used to set the list of HTTP methods the client is allowed to use with cross-domain requests.

If the request is a simple request initiated by GET or POST, no additional settings are required.

Sample Code:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        AllowWildcard:    true,
        AllowMethods:     []string{"PUT", "PATCH"},
    }))
    h.Spin()
}

AllowHeaders

This configuration takes effect only when a preflight request is received. The Access-Control-Allow-Headers field is required if the browser request includes the Access-Control-Request-Headers field. It is a comma-separated string indicating all the header fields supported by the server.

Sample Code:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        AllowHeaders:     []string{"Origin"},
    }))
    h.Spin()
}

ExposeHeaders

The property indicates which headers are safe to expose to the API of a CORS API specification.

Sample Code:

package main

import (
    "github.com/cloudwego/hertz/pkg/app/server"
    "github.com/hertz-contrib/cors"
)

func main() {
    h := server.Default()
    h.Use(cors.New(cors.Config{
        ExposeHeaders:    []string{"Content-Length"},
    }))
    h.Spin()
}

As for usage, you may refer to hertz cors


Last modified March 19, 2024 : chore: slack to discord (#1044) (4c2f994)