-
Notifications
You must be signed in to change notification settings - Fork 0
/
cors.go
107 lines (83 loc) · 3.4 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
package cors
import (
"strconv"
"strings"
"github.com/savsgio/atreugo/v11"
"github.com/valyala/fasthttp"
)
const strHeaderDelim = ", "
// Config configuration.
type Config struct {
// Specifies either the origins, which tells browsers to allow that origin
// to access the resource; or else — for requests without credentials —
// the "*" wildcard, to tell browsers to allow any origin to access the resource.
AllowedOrigins []string
// Specifies the method or methods allowed when accessing the resource.
// This is used in response to a preflight request.
// The conditions under which a request is preflighted are discussed above.
AllowedMethods []string
// This is used in response to a preflight request to indicate which HTTP headers
// can be used when making the actual request.
AllowedHeaders []string
// 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.
// Note that simple GET requests are not preflighted, and so if a request is made
// for a resource with credentials, if this header is not returned with the resource,
// the response is ignored by the browser and not returned to web content.
AllowCredentials bool
// Indicates how long, in seconds, the results of a preflight request can be cached
AllowMaxAge int
// Header or headers to lets a server whitelist headers that browsers are allowed to access.
ExposedHeaders []string
}
func isAllowedOrigin(allowed []string, origin string) bool {
for _, v := range allowed {
if v == origin || v == "*" {
return true
}
}
return false
}
// New returns the middleware with the configured properties
//
// IMPORTANT: always use as last middleware (`server.UseAfter(...)`).
func New(cfg Config) atreugo.Middleware {
allowedHeaders := strings.Join(cfg.AllowedHeaders, strHeaderDelim)
allowedMethods := strings.Join(cfg.AllowedMethods, strHeaderDelim)
exposedHeaders := strings.Join(cfg.ExposedHeaders, strHeaderDelim)
maxAge := strconv.Itoa(cfg.AllowMaxAge)
return func(ctx *atreugo.RequestCtx) error {
origin := string(ctx.Request.Header.Peek(fasthttp.HeaderOrigin))
if !isAllowedOrigin(cfg.AllowedOrigins, origin) {
return ctx.Next() // nolint:wrapcheck
}
ctx.Response.Header.Set(fasthttp.HeaderAccessControlAllowOrigin, origin)
if cfg.AllowCredentials {
ctx.Response.Header.Set(fasthttp.HeaderAccessControlAllowCredentials, "true")
}
varyHeader := ctx.Response.Header.Peek(fasthttp.HeaderVary)
if len(varyHeader) > 0 {
varyHeader = append(varyHeader, strHeaderDelim...)
}
varyHeader = append(varyHeader, fasthttp.HeaderOrigin...)
ctx.Response.Header.SetBytesV(fasthttp.HeaderVary, varyHeader)
if len(cfg.ExposedHeaders) > 0 {
ctx.Response.Header.Set(fasthttp.HeaderAccessControlExposeHeaders, exposedHeaders)
}
method := string(ctx.Method())
if method != fasthttp.MethodOptions {
return ctx.Next() // nolint:wrapcheck
}
if len(cfg.AllowedHeaders) > 0 {
ctx.Response.Header.Set(fasthttp.HeaderAccessControlAllowHeaders, allowedHeaders)
}
if len(cfg.AllowedMethods) > 0 {
ctx.Response.Header.Set(fasthttp.HeaderAccessControlAllowMethods, allowedMethods)
}
if cfg.AllowMaxAge > 0 {
ctx.Response.Header.Set(fasthttp.HeaderAccessControlMaxAge, maxAge)
}
return ctx.Next() // nolint:wrapcheck
}
}