From 7b02762060ea2c5ce0df67beea7298ae34e9b8d1 Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Thu, 3 Feb 2022 13:23:01 +1100 Subject: [PATCH 1/7] Add "Access-Control-Allow-Origin: *" to the header to avoid CORS issues --- internal/handler/handler.go | 1 + internal/web/middleware/cors.go | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 internal/web/middleware/cors.go diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 3e3b4d4..f94241f 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -18,6 +18,7 @@ func Setup(resourceStorage map[string]storage.Storage) http.Handler { router := mux.NewRouter().StrictSlash(true) router.Use(middleware.Recovery) router.Use(middleware.Logger) + router.Use(middleware.CorsAllowAll) // For each resource create the appropriate endpoint handlers. for resourceKey, storageSvc := range resourceStorage { diff --git a/internal/web/middleware/cors.go b/internal/web/middleware/cors.go new file mode 100644 index 0000000..104cbc2 --- /dev/null +++ b/internal/web/middleware/cors.go @@ -0,0 +1,11 @@ +package middleware + +import "net/http" + +func CorsAllowAll(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + + next.ServeHTTP(w, r) + }) +} From 48bc20cfd651957f018a5dfcc7c2160f1627958a Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Thu, 3 Feb 2022 14:05:43 +1100 Subject: [PATCH 2/7] Add a setting to allow all access. --- README.md | 7 +++++++ cmd/start.go | 10 +++++++++- internal/handler/handler.go | 6 ++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3df6300..fd0e60a 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,13 @@ When doing requests, it's good to know that: `go run main.go start -l` + - Disable CORS. To allow access from any host (not secure) `-a` or `--allorigins`. Default value is `false`. + +This adds the header "Access-Control-Allow-Origin: *" which tells the browser to allow from any origin. + +`go run main.go start -a` + + ## Known issues - For users running **macOS Catalina** and newer versions, apple will prevent binary from run as it hasn't been notarized and signed. To overcome this issue, you can [add a security exception](https://support.apple.com/en-us/HT202491) diff --git a/cmd/start.go b/cmd/start.go index a3c866f..6803577 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -50,6 +50,9 @@ Please note that only array data type resources are supported`, // Optional flag to enable logs. startCmd.Flags().BoolP("logs", "l", false, "Enable logs") + // Optional flag to allow all origins + startCmd.Flags().BoolP("allorigins", "a", false, "Allow any Origin ie 'Access-Control-Allow-Origin: *' in the header") + return startCmd } @@ -72,6 +75,11 @@ func runStart(cmd *cobra.Command, _ []string) error { return fmt.Errorf("%w: logs", errFailedParseFlag) } + allorigins, err := cmd.Flags().GetBool("allorigins") + if err != nil { + return fmt.Errorf("%w: logs", errFailedParseFlag) + } + // Setup logger. logger.Setup(logs) @@ -90,7 +98,7 @@ func runStart(cmd *cobra.Command, _ []string) error { // Setup API server. api := &http.Server{ Addr: ":" + port, - Handler: handler.Setup(resourceStorage), + Handler: handler.Setup(resourceStorage, allorigins), // Good practice to set timeouts to avoid Slowloris attacks. WriteTimeout: time.Second * 15, ReadTimeout: time.Second * 15, diff --git a/internal/handler/handler.go b/internal/handler/handler.go index f94241f..1fbcb6a 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -14,11 +14,13 @@ import ( ) // Setup API handler based on provided resources. -func Setup(resourceStorage map[string]storage.Storage) http.Handler { +func Setup(resourceStorage map[string]storage.Storage, allow_all bool) http.Handler { router := mux.NewRouter().StrictSlash(true) router.Use(middleware.Recovery) router.Use(middleware.Logger) - router.Use(middleware.CorsAllowAll) + if allow_all { + router.Use(middleware.CorsAllowAll) + } // For each resource create the appropriate endpoint handlers. for resourceKey, storageSvc := range resourceStorage { From 4c4a1378fcf7cc8a8db2d89d96f1eb29f554c53e Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Wed, 31 Aug 2022 09:48:20 +1000 Subject: [PATCH 3/7] Use github.com/rs/cors for CORS --- go.mod | 1 + go.sum | 2 ++ internal/handler/handler.go | 3 ++- internal/web/middleware/cors.go | 11 ----------- 4 files changed, 5 insertions(+), 12 deletions(-) delete mode 100644 internal/web/middleware/cors.go diff --git a/go.mod b/go.mod index bbd3fba..fc62f98 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.14 require ( github.com/gookit/color v1.2.7 github.com/gorilla/mux v1.7.4 + github.com/rs/cors v1.8.2 github.com/sirupsen/logrus v1.6.0 github.com/spf13/cobra v1.0.0 ) diff --git a/go.sum b/go.sum index 3e776b1..53c2d11 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 1fbcb6a..990ac1b 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -11,6 +11,7 @@ import ( "github.com/chanioxaris/json-server/internal/handler/common" "github.com/chanioxaris/json-server/internal/storage" "github.com/chanioxaris/json-server/internal/web/middleware" + "github.com/rs/cors" ) // Setup API handler based on provided resources. @@ -19,7 +20,7 @@ func Setup(resourceStorage map[string]storage.Storage, allow_all bool) http.Hand router.Use(middleware.Recovery) router.Use(middleware.Logger) if allow_all { - router.Use(middleware.CorsAllowAll) + router.Use(cors.AllowAll().Handler) } // For each resource create the appropriate endpoint handlers. diff --git a/internal/web/middleware/cors.go b/internal/web/middleware/cors.go deleted file mode 100644 index 104cbc2..0000000 --- a/internal/web/middleware/cors.go +++ /dev/null @@ -1,11 +0,0 @@ -package middleware - -import "net/http" - -func CorsAllowAll(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - - next.ServeHTTP(w, r) - }) -} From a9bf1fc9c82a5091961316cb08dfe42188f05d43 Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Wed, 31 Aug 2022 09:48:39 +1000 Subject: [PATCH 4/7] Handle OPTIONS to return CORS headers --- internal/handler/handler.go | 1 + internal/handler/options.go | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 internal/handler/options.go diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 990ac1b..998d47a 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -32,6 +32,7 @@ func Setup(resourceStorage map[string]storage.Storage, allow_all bool) http.Hand } // Register all default endpoint handlers for resource. + router.HandleFunc(fmt.Sprintf("/%s", resourceKey), Options(storageSvc)).Methods(http.MethodOptions) router.HandleFunc(fmt.Sprintf("/%s", resourceKey), List(storageSvc)).Methods(http.MethodGet) router.HandleFunc(fmt.Sprintf("/%s/{id}", resourceKey), Read(storageSvc)).Methods(http.MethodGet) router.HandleFunc(fmt.Sprintf("/%s", resourceKey), Create(storageSvc)).Methods(http.MethodPost) diff --git a/internal/handler/options.go b/internal/handler/options.go new file mode 100644 index 0000000..345867b --- /dev/null +++ b/internal/handler/options.go @@ -0,0 +1,12 @@ +package handler + +import ( + "github.com/chanioxaris/json-server/internal/storage" + "net/http" +) + +func Options(storageSvc storage.Storage) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + return + } +} From 49191e3a93c97c9a62f21b910e8c2e4987515e2a Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Wed, 31 Aug 2022 10:19:25 +1000 Subject: [PATCH 5/7] Use go 1.19 --- go.mod | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index fc62f98..43c51bb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/chanioxaris/json-server -go 1.14 +go 1.19 require ( github.com/gookit/color v1.2.7 @@ -9,3 +9,10 @@ require ( github.com/sirupsen/logrus v1.6.0 github.com/spf13/cobra v1.0.0 ) + +require ( + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect + github.com/spf13/pflag v1.0.3 // indirect + golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect +) From 0e6a053c446bdcbaa0eee33c0a0c3a417e052785 Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Wed, 31 Aug 2022 10:24:58 +1000 Subject: [PATCH 6/7] Upgrade golang.org/x/sys --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 43c51bb..8a85e91 100644 --- a/go.mod +++ b/go.mod @@ -14,5 +14,5 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/spf13/pflag v1.0.3 // indirect - golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect + golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect ) diff --git a/go.sum b/go.sum index 53c2d11..9d6cc6c 100644 --- a/go.sum +++ b/go.sum @@ -124,8 +124,9 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 4bd18375482df6e63c6722f32a6f37144dac0b79 Mon Sep 17 00:00:00 2001 From: Scott Warren Date: Wed, 31 Aug 2022 10:52:49 +1000 Subject: [PATCH 7/7] Handle OPTIONS for /resource and /resource/id --- internal/handler/handler.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 998d47a..845c54e 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -20,7 +20,21 @@ func Setup(resourceStorage map[string]storage.Storage, allow_all bool) http.Hand router.Use(middleware.Recovery) router.Use(middleware.Logger) if allow_all { - router.Use(cors.AllowAll().Handler) + corsHandler := cors.New(cors.Options{ + AllowedOrigins: []string{"*"}, + AllowedMethods: []string{ + http.MethodHead, + http.MethodGet, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + }, + AllowedHeaders: []string{"*"}, + AllowCredentials: false, + OptionsPassthrough: false, + }) + router.Use(corsHandler.Handler) } // For each resource create the appropriate endpoint handlers. @@ -33,6 +47,7 @@ func Setup(resourceStorage map[string]storage.Storage, allow_all bool) http.Hand // Register all default endpoint handlers for resource. router.HandleFunc(fmt.Sprintf("/%s", resourceKey), Options(storageSvc)).Methods(http.MethodOptions) + router.HandleFunc(fmt.Sprintf("/%s/{id}", resourceKey), Options(storageSvc)).Methods(http.MethodOptions) router.HandleFunc(fmt.Sprintf("/%s", resourceKey), List(storageSvc)).Methods(http.MethodGet) router.HandleFunc(fmt.Sprintf("/%s/{id}", resourceKey), Read(storageSvc)).Methods(http.MethodGet) router.HandleFunc(fmt.Sprintf("/%s", resourceKey), Create(storageSvc)).Methods(http.MethodPost)