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/go.mod b/go.mod index bbd3fba..8a85e91 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,18 @@ module github.com/chanioxaris/json-server -go 1.14 +go 1.19 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 ) + +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-20220829200755-d48e67d00261 // indirect +) diff --git a/go.sum b/go.sum index 3e776b1..9d6cc6c 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= @@ -122,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= diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 3e3b4d4..845c54e 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -11,13 +11,31 @@ 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. -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) + if allow_all { + 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. for resourceKey, storageSvc := range resourceStorage { @@ -28,6 +46,8 @@ func Setup(resourceStorage map[string]storage.Storage) http.Handler { } // 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) 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 + } +}