/
cors.go
128 lines (113 loc) · 4.04 KB
/
cors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package middleware
import (
"net/http"
"strconv"
"strings"
"github.com/webx-top/echo"
)
type (
// CORSConfig defines the config for CORS middleware.
CORSConfig struct {
// Skipper defines a function to skip middleware.
Skipper echo.Skipper
// AllowOrigin defines a list of origins that may access the resource.
// Optional with default value as []string{"*"}.
AllowOrigins []string
// AllowMethods defines a list methods allowed when accessing the resource.
// This is used in response to a preflight request.
// Optional with default value as `DefaultCORSConfig.AllowMethods`.
AllowMethods []string
// AllowHeaders defines a list of request headers that can be used when
// making the actual request. This in response to a preflight request.
// Optional with default value as []string{}.
AllowHeaders []string
// 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 with default value as false.
AllowCredentials bool
// ExposeHeaders defines a whitelist headers that clients are allowed to
// access.
// Optional with default value as []string{}.
ExposeHeaders []string
// MaxAge indicates how long (in seconds) the results of a preflight request
// can be cached.
// Optional with default value as 0.
MaxAge int
}
)
var (
// DefaultCORSConfig is the default CORS middleware config.
DefaultCORSConfig = CORSConfig{
Skipper: echo.DefaultSkipper,
AllowOrigins: []string{"*"},
AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.POST, echo.DELETE},
}
)
// CORS returns a cross-origin HTTP request (CORS) middleware.
// See https://developer.mozilla.org/en/docs/Web/HTTP/Access_control_CORS
func CORS() echo.MiddlewareFunc {
return CORSWithConfig(DefaultCORSConfig)
}
// CORSFromConfig returns a CORS middleware from config.
// See `CORS()`.
func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
// Defaults
if config.Skipper == nil {
config.Skipper = DefaultCORSConfig.Skipper
}
if len(config.AllowOrigins) == 0 {
config.AllowOrigins = DefaultCORSConfig.AllowOrigins
}
if len(config.AllowMethods) == 0 {
config.AllowMethods = DefaultCORSConfig.AllowMethods
}
allowOrigins := strings.Join(config.AllowOrigins, ",")
allowMethods := strings.Join(config.AllowMethods, ",")
allowHeaders := strings.Join(config.AllowHeaders, ",")
exposeHeaders := strings.Join(config.ExposeHeaders, ",")
maxAge := strconv.Itoa(config.MaxAge)
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
if config.Skipper(c) {
return next.Handle(c)
}
req := c.Request()
header := c.Response().Header()
// Simple request
if req.Method() != echo.OPTIONS {
header.Add(echo.HeaderVary, echo.HeaderOrigin)
header.Set(echo.HeaderAccessControlAllowOrigin, allowOrigins)
if config.AllowCredentials {
header.Set(echo.HeaderAccessControlAllowCredentials, "true")
}
if exposeHeaders != "" {
header.Set(echo.HeaderAccessControlExposeHeaders, exposeHeaders)
}
return next.Handle(c)
}
// Preflight request
header.Add(echo.HeaderVary, echo.HeaderOrigin)
header.Add(echo.HeaderVary, echo.HeaderAccessControlRequestMethod)
header.Add(echo.HeaderVary, echo.HeaderAccessControlRequestHeaders)
header.Set(echo.HeaderAccessControlAllowOrigin, allowOrigins)
header.Set(echo.HeaderAccessControlAllowMethods, allowMethods)
if config.AllowCredentials {
header.Set(echo.HeaderAccessControlAllowCredentials, "true")
}
if allowHeaders != "" {
header.Set(echo.HeaderAccessControlAllowHeaders, allowHeaders)
} else {
h := req.Header().Get(echo.HeaderAccessControlRequestHeaders)
if h != "" {
header.Set(echo.HeaderAccessControlAllowHeaders, h)
}
}
if config.MaxAge > 0 {
header.Set(echo.HeaderAccessControlMaxAge, maxAge)
}
return c.NoContent(http.StatusNoContent)
})
}
}