forked from TrueCloudLab/frostfs-http-gw
[#158] Support cors
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
eb62ace99a
commit
239397f86c
6 changed files with 118 additions and 9 deletions
|
@ -7,6 +7,7 @@ This document outlines major changes between releases.
|
||||||
### Added
|
### Added
|
||||||
- Support percent-encoding for GET queries (#134)
|
- Support percent-encoding for GET queries (#134)
|
||||||
- Add `trace_id` to logs (#148)
|
- Add `trace_id` to logs (#148)
|
||||||
|
- Add `cors` config params (#158)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Update go version to 1.22 (#132)
|
- Update go version to 1.22 (#132)
|
||||||
|
|
|
@ -97,6 +97,21 @@ type (
|
||||||
bufferMaxSizeForPut uint64
|
bufferMaxSizeForPut uint64
|
||||||
namespaceHeader string
|
namespaceHeader string
|
||||||
defaultNamespaces []string
|
defaultNamespaces []string
|
||||||
|
corsAllowOrigin string
|
||||||
|
corsAllowMethods []string
|
||||||
|
corsAllowHeaders []string
|
||||||
|
corsExposeHeaders []string
|
||||||
|
corsAllowCredentials bool
|
||||||
|
corsMaxAge int
|
||||||
|
}
|
||||||
|
|
||||||
|
CORS struct {
|
||||||
|
AllowOrigin string
|
||||||
|
AllowMethods []string
|
||||||
|
AllowHeaders []string
|
||||||
|
ExposeHeaders []string
|
||||||
|
AllowCredentials bool
|
||||||
|
MaxAge int
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -178,6 +193,12 @@ func (s *appSettings) update(v *viper.Viper, l *zap.Logger) {
|
||||||
namespaceHeader := v.GetString(cfgResolveNamespaceHeader)
|
namespaceHeader := v.GetString(cfgResolveNamespaceHeader)
|
||||||
defaultNamespaces := v.GetStringSlice(cfgResolveDefaultNamespaces)
|
defaultNamespaces := v.GetStringSlice(cfgResolveDefaultNamespaces)
|
||||||
indexPage, indexEnabled := fetchIndexPageTemplate(v, l)
|
indexPage, indexEnabled := fetchIndexPageTemplate(v, l)
|
||||||
|
corsAllowOrigin := v.GetString(cfgCORSAllowOrigin)
|
||||||
|
corsAllowMethods := v.GetStringSlice(cfgCORSAllowMethods)
|
||||||
|
corsAllowHeaders := v.GetStringSlice(cfgCORSAllowHeaders)
|
||||||
|
corsExposeHeaders := v.GetStringSlice(cfgCORSExposeHeaders)
|
||||||
|
corsAllowCredentials := v.GetBool(cfgCORSAllowCredentials)
|
||||||
|
corsMaxAge := fetchCORSMaxAge(v)
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
@ -191,6 +212,12 @@ func (s *appSettings) update(v *viper.Viper, l *zap.Logger) {
|
||||||
s.defaultNamespaces = defaultNamespaces
|
s.defaultNamespaces = defaultNamespaces
|
||||||
s.returnIndexPage = indexEnabled
|
s.returnIndexPage = indexEnabled
|
||||||
s.indexPageTemplate = indexPage
|
s.indexPageTemplate = indexPage
|
||||||
|
s.corsAllowOrigin = corsAllowOrigin
|
||||||
|
s.corsAllowMethods = corsAllowMethods
|
||||||
|
s.corsAllowHeaders = corsAllowHeaders
|
||||||
|
s.corsExposeHeaders = corsExposeHeaders
|
||||||
|
s.corsAllowCredentials = corsAllowCredentials
|
||||||
|
s.corsMaxAge = corsMaxAge
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *appSettings) DefaultTimestamp() bool {
|
func (s *appSettings) DefaultTimestamp() bool {
|
||||||
|
@ -220,6 +247,29 @@ func (s *appSettings) IndexPageTemplate() string {
|
||||||
return s.indexPageTemplate
|
return s.indexPageTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *appSettings) CORS() CORS {
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
|
||||||
|
allowMethods := make([]string, len(s.corsAllowMethods))
|
||||||
|
copy(allowMethods, s.corsAllowMethods)
|
||||||
|
|
||||||
|
allowHeaders := make([]string, len(s.corsAllowHeaders))
|
||||||
|
copy(allowHeaders, s.corsAllowHeaders)
|
||||||
|
|
||||||
|
exposeHeaders := make([]string, len(s.corsExposeHeaders))
|
||||||
|
copy(exposeHeaders, s.corsExposeHeaders)
|
||||||
|
|
||||||
|
return CORS{
|
||||||
|
AllowOrigin: s.corsAllowOrigin,
|
||||||
|
AllowMethods: allowMethods,
|
||||||
|
AllowHeaders: allowHeaders,
|
||||||
|
ExposeHeaders: exposeHeaders,
|
||||||
|
AllowCredentials: s.corsAllowCredentials,
|
||||||
|
MaxAge: s.corsMaxAge,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *appSettings) ClientCut() bool {
|
func (s *appSettings) ClientCut() bool {
|
||||||
s.mu.RLock()
|
s.mu.RLock()
|
||||||
defer s.mu.RUnlock()
|
defer s.mu.RUnlock()
|
||||||
|
|
|
@ -56,6 +56,8 @@ const (
|
||||||
|
|
||||||
defaultReconnectInterval = time.Minute
|
defaultReconnectInterval = time.Minute
|
||||||
|
|
||||||
|
defaultCORSMaxAge = 600 // seconds
|
||||||
|
|
||||||
cfgServer = "server"
|
cfgServer = "server"
|
||||||
cfgTLSEnabled = "tls.enabled"
|
cfgTLSEnabled = "tls.enabled"
|
||||||
cfgTLSCertFile = "tls.cert_file"
|
cfgTLSCertFile = "tls.cert_file"
|
||||||
|
@ -141,6 +143,14 @@ const (
|
||||||
cfgResolveNamespaceHeader = "resolve_bucket.namespace_header"
|
cfgResolveNamespaceHeader = "resolve_bucket.namespace_header"
|
||||||
cfgResolveDefaultNamespaces = "resolve_bucket.default_namespaces"
|
cfgResolveDefaultNamespaces = "resolve_bucket.default_namespaces"
|
||||||
|
|
||||||
|
// CORS.
|
||||||
|
cfgCORSAllowOrigin = "cors.allow_origin"
|
||||||
|
cfgCORSAllowMethods = "cors.allow_methods"
|
||||||
|
cfgCORSAllowHeaders = "cors.allow_headers"
|
||||||
|
cfgCORSExposeHeaders = "cors.expose_headers"
|
||||||
|
cfgCORSAllowCredentials = "cors.allow_credentials"
|
||||||
|
cfgCORSMaxAge = "cors.max_age"
|
||||||
|
|
||||||
// Command line args.
|
// Command line args.
|
||||||
cmdHelp = "help"
|
cmdHelp = "help"
|
||||||
cmdVersion = "version"
|
cmdVersion = "version"
|
||||||
|
@ -527,6 +537,15 @@ func fetchIndexPageTemplate(v *viper.Viper, l *zap.Logger) (string, bool) {
|
||||||
return string(tmpl), true
|
return string(tmpl), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchCORSMaxAge(v *viper.Viper) int {
|
||||||
|
maxAge := v.GetInt(cfgCORSMaxAge)
|
||||||
|
if maxAge <= 0 {
|
||||||
|
maxAge = defaultCORSMaxAge
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxAge
|
||||||
|
}
|
||||||
|
|
||||||
func fetchServers(v *viper.Viper, log *zap.Logger) []ServerInfo {
|
func fetchServers(v *viper.Viper, log *zap.Logger) []ServerInfo {
|
||||||
var servers []ServerInfo
|
var servers []ServerInfo
|
||||||
seen := make(map[string]struct{})
|
seen := make(map[string]struct{})
|
||||||
|
|
|
@ -126,3 +126,10 @@ HTTP_GW_RESOLVE_BUCKET_DEFAULT_NAMESPACES="" "root"
|
||||||
# Max attempt to make successful tree request.
|
# Max attempt to make successful tree request.
|
||||||
# default value is 0 that means the number of attempts equals to number of nodes in pool.
|
# default value is 0 that means the number of attempts equals to number of nodes in pool.
|
||||||
HTTP_GW_FROSTFS_TREE_POOL_MAX_ATTEMPTS=0
|
HTTP_GW_FROSTFS_TREE_POOL_MAX_ATTEMPTS=0
|
||||||
|
|
||||||
|
HTTP_GW_CORS_ALLOW_ORIGIN="*"
|
||||||
|
HTTP_GW_CORS_ALLOW_METHODS="GET" "POST"
|
||||||
|
HTTP_GW_CORS_ALLOW_HEADERS="*"
|
||||||
|
HTTP_GW_CORS_EXPOSE_HEADERS="*"
|
||||||
|
HTTP_GW_CORS_ALLOW_CREDENTIALS=false
|
||||||
|
HTTP_GW_CORS_MAX_AGE=600
|
||||||
|
|
|
@ -138,3 +138,11 @@ cache:
|
||||||
resolve_bucket:
|
resolve_bucket:
|
||||||
namespace_header: X-Frostfs-Namespace
|
namespace_header: X-Frostfs-Namespace
|
||||||
default_namespaces: [ "", "root" ]
|
default_namespaces: [ "", "root" ]
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allow_origin: ""
|
||||||
|
allow_methods: []
|
||||||
|
allow_headers: []
|
||||||
|
expose_headers: []
|
||||||
|
allow_credentials: false
|
||||||
|
max_age: 600
|
||||||
|
|
|
@ -363,3 +363,27 @@ index_page:
|
||||||
|-----------------|----------|---------------|---------------|---------------------------------------------------------------------------------|
|
|-----------------|----------|---------------|---------------|---------------------------------------------------------------------------------|
|
||||||
| `enabled` | `bool` | yes | `false` | Flag to enable index_page return if no object with specified S3-name was found. |
|
| `enabled` | `bool` | yes | `false` | Flag to enable index_page return if no object with specified S3-name was found. |
|
||||||
| `template_path` | `string` | yes | `""` | Path to .gotmpl file with html template for index_page. |
|
| `template_path` | `string` | yes | `""` | Path to .gotmpl file with html template for index_page. |
|
||||||
|
|
||||||
|
# `cors` section
|
||||||
|
|
||||||
|
Parameters for CORS (used in OPTIONS requests and responses in all handlers).
|
||||||
|
If values are not set, headers will not be included to response.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
cors:
|
||||||
|
allow_origin: "*"
|
||||||
|
allow_methods: ["GET", "HEAD"]
|
||||||
|
allow_headers: ["Authorization"]
|
||||||
|
expose_headers: ["*"]
|
||||||
|
allow_credentials: false
|
||||||
|
max_age: 600
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | SIGHUP reload | Default value | Description |
|
||||||
|
|---------------------|------------|---------------|---------------|--------------------------------------------------------|
|
||||||
|
| `allow_origin` | `string` | yes | | Values for `Access-Control-Allow-Origin` headers. |
|
||||||
|
| `allow_methods` | `[]string` | yes | | Values for `Access-Control-Allow-Methods` headers. |
|
||||||
|
| `allow_headers` | `[]string` | yes | | Values for `Access-Control-Allow-Headers` headers. |
|
||||||
|
| `expose_headers` | `[]string` | yes | | Values for `Access-Control-Expose-Headers` headers. |
|
||||||
|
| `allow_credentials` | `bool` | yes | `false` | Values for `Access-Control-Allow-Credentials` headers. |
|
||||||
|
| `max_age` | `int` | yes | `600` | Values for `Access-Control-Max-Age ` headers. |
|
||||||
|
|
Loading…
Add table
Reference in a new issue