mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
Set allowed origins in config (#5109)
* Add a way to use a JWT in an HTTP only cookie If a JWT is not included in the Authorization header or a query string, attempt to get a JWT from an HTTP only cookie. * Added a way to specify allowed origins header from config * Removed unecessary log * Check list of domains from config or command flag * Handle default wildcard and change name of config value to cors
This commit is contained in:
parent
3c9bcfb864
commit
06343f8976
|
@ -61,6 +61,7 @@ type FilerOptions struct {
|
||||||
showUIDirectoryDelete *bool
|
showUIDirectoryDelete *bool
|
||||||
downloadMaxMBps *int
|
downloadMaxMBps *int
|
||||||
diskType *string
|
diskType *string
|
||||||
|
allowedOrigins *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -91,6 +92,7 @@ func init() {
|
||||||
f.showUIDirectoryDelete = cmdFiler.Flag.Bool("ui.deleteDir", true, "enable filer UI show delete directory button")
|
f.showUIDirectoryDelete = cmdFiler.Flag.Bool("ui.deleteDir", true, "enable filer UI show delete directory button")
|
||||||
f.downloadMaxMBps = cmdFiler.Flag.Int("downloadMaxMBps", 0, "download max speed for each download request, in MB per second")
|
f.downloadMaxMBps = cmdFiler.Flag.Int("downloadMaxMBps", 0, "download max speed for each download request, in MB per second")
|
||||||
f.diskType = cmdFiler.Flag.String("disk", "", "[hdd|ssd|<tag>] hard drive or solid state drive or any tag")
|
f.diskType = cmdFiler.Flag.String("disk", "", "[hdd|ssd|<tag>] hard drive or solid state drive or any tag")
|
||||||
|
f.allowedOrigins = cmdFiler.Flag.String("allowedOrigins", "*", "comma separated list of allowed origins")
|
||||||
|
|
||||||
// start s3 on filer
|
// start s3 on filer
|
||||||
filerStartS3 = cmdFiler.Flag.Bool("s3", false, "whether to start S3 gateway")
|
filerStartS3 = cmdFiler.Flag.Bool("s3", false, "whether to start S3 gateway")
|
||||||
|
@ -229,6 +231,9 @@ func (fo *FilerOptions) startFiler() {
|
||||||
if *fo.bindIp == "" {
|
if *fo.bindIp == "" {
|
||||||
*fo.bindIp = *fo.ip
|
*fo.bindIp = *fo.ip
|
||||||
}
|
}
|
||||||
|
if *fo.allowedOrigins == "" {
|
||||||
|
*fo.allowedOrigins = "*"
|
||||||
|
}
|
||||||
|
|
||||||
defaultLevelDbDirectory := util.ResolvePath(*fo.defaultLevelDbDirectory + "/filerldb2")
|
defaultLevelDbDirectory := util.ResolvePath(*fo.defaultLevelDbDirectory + "/filerldb2")
|
||||||
|
|
||||||
|
@ -253,6 +258,7 @@ func (fo *FilerOptions) startFiler() {
|
||||||
ShowUIDirectoryDelete: *fo.showUIDirectoryDelete,
|
ShowUIDirectoryDelete: *fo.showUIDirectoryDelete,
|
||||||
DownloadMaxBytesPs: int64(*fo.downloadMaxMBps) * 1024 * 1024,
|
DownloadMaxBytesPs: int64(*fo.downloadMaxMBps) * 1024 * 1024,
|
||||||
DiskType: *fo.diskType,
|
DiskType: *fo.diskType,
|
||||||
|
AllowedOrigins: strings.Split(*fo.allowedOrigins, ","),
|
||||||
})
|
})
|
||||||
if nfs_err != nil {
|
if nfs_err != nil {
|
||||||
glog.Fatalf("Filer startup error: %v", nfs_err)
|
glog.Fatalf("Filer startup error: %v", nfs_err)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
||||||
|
@ -42,6 +43,7 @@ type S3Options struct {
|
||||||
portGrpc *int
|
portGrpc *int
|
||||||
config *string
|
config *string
|
||||||
domainName *string
|
domainName *string
|
||||||
|
allowedOrigins *string
|
||||||
tlsPrivateKey *string
|
tlsPrivateKey *string
|
||||||
tlsCertificate *string
|
tlsCertificate *string
|
||||||
tlsCACertificate *string
|
tlsCACertificate *string
|
||||||
|
@ -64,6 +66,7 @@ func init() {
|
||||||
s3StandaloneOptions.portHttps = cmdS3.Flag.Int("port.https", 0, "s3 server https listen port")
|
s3StandaloneOptions.portHttps = cmdS3.Flag.Int("port.https", 0, "s3 server https listen port")
|
||||||
s3StandaloneOptions.portGrpc = cmdS3.Flag.Int("port.grpc", 0, "s3 server grpc listen port")
|
s3StandaloneOptions.portGrpc = cmdS3.Flag.Int("port.grpc", 0, "s3 server grpc listen port")
|
||||||
s3StandaloneOptions.domainName = cmdS3.Flag.String("domainName", "", "suffix of the host name in comma separated list, {bucket}.{domainName}")
|
s3StandaloneOptions.domainName = cmdS3.Flag.String("domainName", "", "suffix of the host name in comma separated list, {bucket}.{domainName}")
|
||||||
|
s3StandaloneOptions.allowedOrigins = cmdS3.Flag.String("allowedOrigins", "*", "comma separated list of allowed origins")
|
||||||
s3StandaloneOptions.dataCenter = cmdS3.Flag.String("dataCenter", "", "prefer to read and write to volumes in this data center")
|
s3StandaloneOptions.dataCenter = cmdS3.Flag.String("dataCenter", "", "prefer to read and write to volumes in this data center")
|
||||||
s3StandaloneOptions.config = cmdS3.Flag.String("config", "", "path to the config file")
|
s3StandaloneOptions.config = cmdS3.Flag.String("config", "", "path to the config file")
|
||||||
s3StandaloneOptions.auditLogConfig = cmdS3.Flag.String("auditLogConfig", "", "path to the audit log config file")
|
s3StandaloneOptions.auditLogConfig = cmdS3.Flag.String("auditLogConfig", "", "path to the audit log config file")
|
||||||
|
@ -220,6 +223,7 @@ func (s3opt *S3Options) startS3Server() bool {
|
||||||
Port: *s3opt.port,
|
Port: *s3opt.port,
|
||||||
Config: *s3opt.config,
|
Config: *s3opt.config,
|
||||||
DomainName: *s3opt.domainName,
|
DomainName: *s3opt.domainName,
|
||||||
|
AllowedOrigins: strings.Split(*s3opt.allowedOrigins, ","),
|
||||||
BucketsPath: filerBucketsPath,
|
BucketsPath: filerBucketsPath,
|
||||||
GrpcDialOption: grpcDialOption,
|
GrpcDialOption: grpcDialOption,
|
||||||
AllowEmptyFolder: *s3opt.allowEmptyFolder,
|
AllowEmptyFolder: *s3opt.allowEmptyFolder,
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
# /etc/seaweedfs/security.toml
|
# /etc/seaweedfs/security.toml
|
||||||
# this file is read by master, volume server, and filer
|
# this file is read by master, volume server, and filer
|
||||||
|
|
||||||
|
# comma separated origins allowed to make requests to the filer and s3 gateway.
|
||||||
|
# enter in this format: https://domain.com, or http://localhost:port
|
||||||
|
[cors.allowed_origins]
|
||||||
|
values = "*"
|
||||||
|
|
||||||
# this jwt signing key is read by master and volume server, and it is used for write operations:
|
# this jwt signing key is read by master and volume server, and it is used for write operations:
|
||||||
# - the Master server generates the JWT, which can be used to write a certain file on a volume server
|
# - the Master server generates the JWT, which can be used to write a certain file on a volume server
|
||||||
# - the Volume server validates the JWT on writing
|
# - the Volume server validates the JWT on writing
|
||||||
|
|
|
@ -106,6 +106,7 @@ func init() {
|
||||||
filerOptions.port = cmdServer.Flag.Int("filer.port", 8888, "filer server http listen port")
|
filerOptions.port = cmdServer.Flag.Int("filer.port", 8888, "filer server http listen port")
|
||||||
filerOptions.portGrpc = cmdServer.Flag.Int("filer.port.grpc", 0, "filer server grpc listen port")
|
filerOptions.portGrpc = cmdServer.Flag.Int("filer.port.grpc", 0, "filer server grpc listen port")
|
||||||
filerOptions.publicPort = cmdServer.Flag.Int("filer.port.public", 0, "filer server public http listen port")
|
filerOptions.publicPort = cmdServer.Flag.Int("filer.port.public", 0, "filer server public http listen port")
|
||||||
|
filerOptions.allowedOrigins = cmdServer.Flag.String("filer.allowedOrigins", "*", "comma separated list of allowed origins")
|
||||||
filerOptions.defaultReplicaPlacement = cmdServer.Flag.String("filer.defaultReplicaPlacement", "", "default replication type. If not specified, use master setting.")
|
filerOptions.defaultReplicaPlacement = cmdServer.Flag.String("filer.defaultReplicaPlacement", "", "default replication type. If not specified, use master setting.")
|
||||||
filerOptions.disableDirListing = cmdServer.Flag.Bool("filer.disableDirListing", false, "turn off directory listing")
|
filerOptions.disableDirListing = cmdServer.Flag.Bool("filer.disableDirListing", false, "turn off directory listing")
|
||||||
filerOptions.maxMB = cmdServer.Flag.Int("filer.maxMB", 4, "split files larger than the limit")
|
filerOptions.maxMB = cmdServer.Flag.Int("filer.maxMB", 4, "split files larger than the limit")
|
||||||
|
@ -142,6 +143,7 @@ func init() {
|
||||||
s3Options.portHttps = cmdServer.Flag.Int("s3.port.https", 0, "s3 server https listen port")
|
s3Options.portHttps = cmdServer.Flag.Int("s3.port.https", 0, "s3 server https listen port")
|
||||||
s3Options.portGrpc = cmdServer.Flag.Int("s3.port.grpc", 0, "s3 server grpc listen port")
|
s3Options.portGrpc = cmdServer.Flag.Int("s3.port.grpc", 0, "s3 server grpc listen port")
|
||||||
s3Options.domainName = cmdServer.Flag.String("s3.domainName", "", "suffix of the host name in comma separated list, {bucket}.{domainName}")
|
s3Options.domainName = cmdServer.Flag.String("s3.domainName", "", "suffix of the host name in comma separated list, {bucket}.{domainName}")
|
||||||
|
s3Options.allowedOrigins = cmdServer.Flag.String("s3.allowedOrigins", "*", "comma separated list of allowed origins")
|
||||||
s3Options.tlsPrivateKey = cmdServer.Flag.String("s3.key.file", "", "path to the TLS private key file")
|
s3Options.tlsPrivateKey = cmdServer.Flag.String("s3.key.file", "", "path to the TLS private key file")
|
||||||
s3Options.tlsCertificate = cmdServer.Flag.String("s3.cert.file", "", "path to the TLS certificate file")
|
s3Options.tlsCertificate = cmdServer.Flag.String("s3.cert.file", "", "path to the TLS certificate file")
|
||||||
s3Options.tlsCACertificate = cmdServer.Flag.String("s3.cacert.file", "", "path to the TLS CA certificate file")
|
s3Options.tlsCACertificate = cmdServer.Flag.String("s3.cacert.file", "", "path to the TLS CA certificate file")
|
||||||
|
|
|
@ -3,12 +3,13 @@ package filer
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/cluster/lock_manager"
|
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/cluster/lock_manager"
|
||||||
|
|
||||||
"github.com/seaweedfs/seaweedfs/weed/cluster"
|
"github.com/seaweedfs/seaweedfs/weed/cluster"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/pb"
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
||||||
|
|
|
@ -40,6 +40,10 @@ func writeSuccessResponseEmpty(w http.ResponseWriter, r *http.Request) {
|
||||||
s3err.WriteEmptyResponse(w, r, http.StatusOK)
|
s3err.WriteEmptyResponse(w, r, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeFailureResponse(w http.ResponseWriter, r *http.Request, errCode s3err.ErrorCode) {
|
||||||
|
s3err.WriteErrorResponse(w, r, errCode)
|
||||||
|
}
|
||||||
|
|
||||||
func validateContentMd5(h http.Header) ([]byte, error) {
|
func validateContentMd5(h http.Header) ([]byte, error) {
|
||||||
md5B64, ok := h["Content-Md5"]
|
md5B64, ok := h["Content-Md5"]
|
||||||
if ok {
|
if ok {
|
||||||
|
|
|
@ -3,15 +3,16 @@ package s3api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/filer"
|
|
||||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
|
||||||
"github.com/seaweedfs/seaweedfs/weed/pb/s3_pb"
|
|
||||||
"github.com/seaweedfs/seaweedfs/weed/util/grace"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/filer"
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/pb/s3_pb"
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/util/grace"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/seaweedfs/seaweedfs/weed/pb"
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
||||||
. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
||||||
|
@ -26,6 +27,7 @@ type S3ApiServerOption struct {
|
||||||
Port int
|
Port int
|
||||||
Config string
|
Config string
|
||||||
DomainName string
|
DomainName string
|
||||||
|
AllowedOrigins []string
|
||||||
BucketsPath string
|
BucketsPath string
|
||||||
GrpcDialOption grpc.DialOption
|
GrpcDialOption grpc.DialOption
|
||||||
AllowEmptyFolder bool
|
AllowEmptyFolder bool
|
||||||
|
@ -56,6 +58,14 @@ func NewS3ApiServer(router *mux.Router, option *S3ApiServerOption) (s3ApiServer
|
||||||
v.SetDefault("jwt.filer_signing.read.expires_after_seconds", 60)
|
v.SetDefault("jwt.filer_signing.read.expires_after_seconds", 60)
|
||||||
readExpiresAfterSec := v.GetInt("jwt.filer_signing.read.expires_after_seconds")
|
readExpiresAfterSec := v.GetInt("jwt.filer_signing.read.expires_after_seconds")
|
||||||
|
|
||||||
|
v.SetDefault("cors.allowed_origins.values", "*")
|
||||||
|
|
||||||
|
if (option.AllowedOrigins == nil) || (len(option.AllowedOrigins) == 0) {
|
||||||
|
allowedOrigins := v.GetString("cors.allowed_origins.values")
|
||||||
|
domains := strings.Split(allowedOrigins, ",")
|
||||||
|
option.AllowedOrigins = domains
|
||||||
|
}
|
||||||
|
|
||||||
s3ApiServer = &S3ApiServer{
|
s3ApiServer = &S3ApiServer{
|
||||||
option: option,
|
option: option,
|
||||||
iam: NewIdentityAccessManagement(option),
|
iam: NewIdentityAccessManagement(option),
|
||||||
|
@ -103,7 +113,25 @@ func (s3a *S3ApiServer) registerRouter(router *mux.Router) {
|
||||||
|
|
||||||
apiRouter.Methods("OPTIONS").HandlerFunc(
|
apiRouter.Methods("OPTIONS").HandlerFunc(
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
origin := r.Header.Get("Origin")
|
||||||
|
if origin != "" {
|
||||||
|
if s3a.option.AllowedOrigins == nil || len(s3a.option.AllowedOrigins) == 0 || s3a.option.AllowedOrigins[0] == "*" {
|
||||||
|
origin = "*"
|
||||||
|
} else {
|
||||||
|
originFound := false
|
||||||
|
for _, allowedOrigin := range s3a.option.AllowedOrigins {
|
||||||
|
if origin == allowedOrigin {
|
||||||
|
originFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !originFound {
|
||||||
|
writeFailureResponse(w, r, http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||||
w.Header().Set("Access-Control-Expose-Headers", "*")
|
w.Header().Set("Access-Control-Expose-Headers", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "*")
|
w.Header().Set("Access-Control-Allow-Methods", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ type FilerOption struct {
|
||||||
ShowUIDirectoryDelete bool
|
ShowUIDirectoryDelete bool
|
||||||
DownloadMaxBytesPs int64
|
DownloadMaxBytesPs int64
|
||||||
DiskType string
|
DiskType string
|
||||||
|
AllowedOrigins []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilerServer struct {
|
type FilerServer struct {
|
||||||
|
@ -107,6 +109,14 @@ func NewFilerServer(defaultMux, readonlyMux *http.ServeMux, option *FilerOption)
|
||||||
v.SetDefault("jwt.filer_signing.read.expires_after_seconds", 60)
|
v.SetDefault("jwt.filer_signing.read.expires_after_seconds", 60)
|
||||||
readExpiresAfterSec := v.GetInt("jwt.filer_signing.read.expires_after_seconds")
|
readExpiresAfterSec := v.GetInt("jwt.filer_signing.read.expires_after_seconds")
|
||||||
|
|
||||||
|
v.SetDefault("cors.allowed_origins.values", "*")
|
||||||
|
|
||||||
|
if (option.AllowedOrigins == nil) || (len(option.AllowedOrigins) == 0) {
|
||||||
|
allowedOrigins := v.GetString("cors.allowed_origins.values")
|
||||||
|
domains := strings.Split(allowedOrigins, ",")
|
||||||
|
option.AllowedOrigins = domains
|
||||||
|
}
|
||||||
|
|
||||||
fs = &FilerServer{
|
fs = &FilerServer{
|
||||||
option: option,
|
option: option,
|
||||||
grpcDialOption: security.LoadClientTLS(util.GetViper(), "grpc.filer"),
|
grpcDialOption: security.LoadClientTLS(util.GetViper(), "grpc.filer"),
|
||||||
|
|
|
@ -3,6 +3,7 @@ package weed_server
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
@ -17,8 +18,24 @@ import (
|
||||||
func (fs *FilerServer) filerHandler(w http.ResponseWriter, r *http.Request) {
|
func (fs *FilerServer) filerHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if r.Header.Get("Origin") != "" {
|
origin := r.Header.Get("Origin")
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
if origin != "" {
|
||||||
|
if fs.option.AllowedOrigins == nil || len(fs.option.AllowedOrigins) == 0 || fs.option.AllowedOrigins[0] == "*" {
|
||||||
|
origin = "*"
|
||||||
|
} else {
|
||||||
|
originFound := false
|
||||||
|
for _, allowedOrigin := range fs.option.AllowedOrigins {
|
||||||
|
if origin == allowedOrigin {
|
||||||
|
originFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !originFound {
|
||||||
|
writeJsonError(w, r, http.StatusForbidden, errors.New("origin not allowed"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||||
w.Header().Set("Access-Control-Expose-Headers", "*")
|
w.Header().Set("Access-Control-Expose-Headers", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
|
@ -99,9 +116,27 @@ func (fs *FilerServer) readonlyFilerHandler(w http.ResponseWriter, r *http.Reque
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if r.Header.Get("Origin") != "" {
|
os.Stdout.WriteString("Request: " + r.Method + " " + r.URL.String() + "\n")
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
origin := r.Header.Get("Origin")
|
||||||
|
if origin != "" {
|
||||||
|
if fs.option.AllowedOrigins == nil || len(fs.option.AllowedOrigins) == 0 || fs.option.AllowedOrigins[0] == "*" {
|
||||||
|
origin = "*"
|
||||||
|
} else {
|
||||||
|
originFound := false
|
||||||
|
for _, allowedOrigin := range fs.option.AllowedOrigins {
|
||||||
|
if origin == allowedOrigin {
|
||||||
|
originFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !originFound {
|
||||||
|
writeJsonError(w, r, http.StatusForbidden, errors.New("origin not allowed"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||||
|
w.Header().Set("Access-Control-Allow-Headers", "OPTIONS, GET, HEAD")
|
||||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +172,6 @@ func OptionsHandler(w http.ResponseWriter, r *http.Request, isReadOnly bool) {
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS")
|
w.Header().Set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS")
|
||||||
w.Header().Set("Access-Control-Expose-Headers", "*")
|
w.Header().Set("Access-Control-Expose-Headers", "*")
|
||||||
}
|
}
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "*")
|
w.Header().Set("Access-Control-Allow-Headers", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue