From d8c9f7e8c6d4021907c3e6a254f398bba804e261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20P=C3=A9rez?= Date: Fri, 10 May 2019 13:06:02 +0200 Subject: [PATCH 1/5] WIP create struct Config to read config file and parse flags --- cmd/killgrave/main.go | 19 +++++++++++++++---- internal/config.go | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 internal/config.go diff --git a/cmd/killgrave/main.go b/cmd/killgrave/main.go index fda1b09..f42ea83 100644 --- a/cmd/killgrave/main.go +++ b/cmd/killgrave/main.go @@ -21,21 +21,32 @@ func main() { port := flag.Int("port", 3000, "por to run the server") imposters := flag.String("imposters", "imposters", "directory where your imposters are saved") v := flag.Bool("version", false, "show the version of the application") + c := flag.String("config", "", "path with configuration file") + flag.Parse() if *v { fmt.Printf("%s version %s\n", name, version) return } - + var config killgrave.Config + if *c != "" { + //TODO: Read file + } else { + config = killgrave.Config{ + ImpostersPath: *imposters, + Port: *port, + Host: *host, + } + } r := mux.NewRouter() - s := killgrave.NewServer(*imposters, r) + s := killgrave.NewServer(config.ImpostersPath, r) if err := s.Build(); err != nil { log.Fatal(err) } - httpAddr := fmt.Sprintf("%s:%d", *host, *port) - log.Printf("The fake server is on tap now: http://%s:%d\n", *host, *port) + httpAddr := fmt.Sprintf("%s:%d", config.Host, config.Port) + log.Printf("The fake server is on tap now: http://%s:%d\n", config.Host, config.Port) log.Fatal(http.ListenAndServe(httpAddr, handlers.CORS(s.AccessControl()...)(r))) } diff --git a/internal/config.go b/internal/config.go new file mode 100644 index 0000000..836cabd --- /dev/null +++ b/internal/config.go @@ -0,0 +1,17 @@ +package killgrave + +// Config representation of config file yaml +type Config struct { + ImpostersPath string `yaml:"imposters_path"` + Port int `yaml:"port"` + Host string `yaml:"host"` + Cors ConfigCors `yaml:"cors"` +} + +// ConfigCors representation of section CORS of the yaml +type ConfigCors struct { + Methods []string `yaml:"methods"` + Headers []string `yaml:"headers"` + Origins []string `yaml:"origins"` + ExposeHeaders []string `yaml:"expose_headers"` +} From bd321b51494345c5c9e7d4b0283dd1e3faf8b3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20P=C3=A9rez?= Date: Sat, 11 May 2019 11:46:57 +0200 Subject: [PATCH 2/5] Read the config file --- cmd/killgrave/main.go | 4 ++-- go.mod | 1 + go.sum | 4 ++++ internal/config.go | 37 ++++++++++++++++++++++++++++++------- internal/server.go | 27 ++++++++++++++++++++++++--- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/cmd/killgrave/main.go b/cmd/killgrave/main.go index f42ea83..1f4ddd1 100644 --- a/cmd/killgrave/main.go +++ b/cmd/killgrave/main.go @@ -31,7 +31,7 @@ func main() { } var config killgrave.Config if *c != "" { - //TODO: Read file + killgrave.ReadConfigFile(*c, &config) } else { config = killgrave.Config{ ImpostersPath: *imposters, @@ -48,5 +48,5 @@ func main() { httpAddr := fmt.Sprintf("%s:%d", config.Host, config.Port) log.Printf("The fake server is on tap now: http://%s:%d\n", config.Host, config.Port) - log.Fatal(http.ListenAndServe(httpAddr, handlers.CORS(s.AccessControl()...)(r))) + log.Fatal(http.ListenAndServe(httpAddr, handlers.CORS(s.AccessControl(config.CORS)...)(r))) } diff --git a/go.mod b/go.mod index f90153f..a2665b8 100644 --- a/go.mod +++ b/go.mod @@ -10,4 +10,5 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.1.0 + gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index af7a1c5..cf2c144 100644 --- a/go.sum +++ b/go.sum @@ -17,3 +17,7 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg= github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/config.go b/internal/config.go index 836cabd..5ee3ef3 100644 --- a/internal/config.go +++ b/internal/config.go @@ -1,17 +1,40 @@ package killgrave +import ( + "io/ioutil" + "os" + + "github.com/pkg/errors" + "gopkg.in/yaml.v2" +) + // Config representation of config file yaml type Config struct { ImpostersPath string `yaml:"imposters_path"` Port int `yaml:"port"` Host string `yaml:"host"` - Cors ConfigCors `yaml:"cors"` + CORS ConfigCORS `yaml:"cors"` } -// ConfigCors representation of section CORS of the yaml -type ConfigCors struct { - Methods []string `yaml:"methods"` - Headers []string `yaml:"headers"` - Origins []string `yaml:"origins"` - ExposeHeaders []string `yaml:"expose_headers"` +// ConfigCORS representation of section CORS of the yaml +type ConfigCORS struct { + Methods []string `yaml:"methods"` + Headers []string `yaml:"headers"` + Origins []string `yaml:"origins"` + ExposedHeaders []string `yaml:"exposed_headers"` +} + +// ReadConfigFile unmarshal content of config file to Config struct +func ReadConfigFile(path string, config *Config) error { + configFile, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "error trying to read config file: %s", path) + } + defer configFile.Close() + + bytes, _ := ioutil.ReadAll(configFile) + if err := yaml.Unmarshal(bytes, config); err != nil { + return errors.Wrapf(err, "error while unmarshall configFile file %s", path) + } + return nil } diff --git a/internal/server.go b/internal/server.go index 50c7089..2fec971 100644 --- a/internal/server.go +++ b/internal/server.go @@ -12,6 +12,11 @@ import ( "github.com/pkg/errors" ) +var ( + defaultCORSMethods = []string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"} + defaultCORSHeaders = []string{"X-Requested-With", "Content-Type", "Authorization", "*"} +) + // Server definition of mock server type Server struct { impostersPath string @@ -27,9 +32,25 @@ func NewServer(p string, r *mux.Router) *Server { } // AccessControl Return options to initialize the mock server with default access control -func (s *Server) AccessControl() (h []handlers.CORSOption) { - h = append(h, handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"})) - h = append(h, handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "*"})) +func (s *Server) AccessControl(config ConfigCORS) (h []handlers.CORSOption) { + h = append(h, handlers.AllowedMethods(defaultCORSMethods)) + h = append(h, handlers.AllowedHeaders(defaultCORSHeaders)) + + if len(config.Methods) > 0 { + h = append(h, handlers.AllowedMethods(config.Methods)) + } + + if len(config.Origins) > 0 { + h = append(h, handlers.AllowedOrigins(config.Origins)) + } + + if len(config.Headers) > 0 { + h = append(h, handlers.AllowedHeaders(config.Headers)) + } + + if len(config.ExposedHeaders) > 0 { + h = append(h, handlers.ExposedHeaders(config.ExposedHeaders)) + } return } From 9de929ea1230b43d0dd45251743ae5fc9f7df6af Mon Sep 17 00:00:00 2001 From: aperezg Date: Sat, 11 May 2019 14:43:20 +0200 Subject: [PATCH 3/5] Testing how to read config file and improve route_matchers tests --- internal/config.go | 9 ++-- internal/config_test.go | 55 +++++++++++++++++++++++++ internal/route_matchers_test.go | 34 +++++++++------ internal/server.go | 13 +++++- internal/server_test.go | 15 ++++++- internal/test/testdata/config.yml | 9 ++++ internal/test/testdata/wrong_config.yml | 1 + 7 files changed, 116 insertions(+), 20 deletions(-) create mode 100644 internal/config_test.go create mode 100644 internal/test/testdata/config.yml create mode 100644 internal/test/testdata/wrong_config.yml diff --git a/internal/config.go b/internal/config.go index 5ee3ef3..2b262bb 100644 --- a/internal/config.go +++ b/internal/config.go @@ -18,10 +18,11 @@ type Config struct { // ConfigCORS representation of section CORS of the yaml type ConfigCORS struct { - Methods []string `yaml:"methods"` - Headers []string `yaml:"headers"` - Origins []string `yaml:"origins"` - ExposedHeaders []string `yaml:"exposed_headers"` + Methods []string `yaml:"methods"` + Headers []string `yaml:"headers"` + Origins []string `yaml:"origins"` + ExposedHeaders []string `yaml:"exposed_headers"` + AllowCredentials bool `yaml:"allow_credentials"` } // ReadConfigFile unmarshal content of config file to Config struct diff --git a/internal/config_test.go b/internal/config_test.go new file mode 100644 index 0000000..2ee0328 --- /dev/null +++ b/internal/config_test.go @@ -0,0 +1,55 @@ +package killgrave + +import ( + "reflect" + "testing" + + "github.com/pkg/errors" +) + +func TestReadConfigFile(t *testing.T) { + tests := map[string]struct { + input string + expected Config + err error + }{ + "valid config file": {"test/testdata/config.yml", validConfig(), nil}, + "file not found": {"test/testdata/file.yml", Config{}, errors.New("error")}, + "wrong yaml file": {"test/testdata/wrong_config.yml", Config{}, errors.New("error")}, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + var got Config + err := ReadConfigFile(tc.input, &got) + + if err != nil && tc.err == nil { + t.Fatalf("not expected any erros and got %v", err) + } + + if err == nil && tc.err != nil { + t.Fatalf("expected an error and got nil") + } + + if !reflect.DeepEqual(tc.expected, got) { + t.Fatalf("expected: %v, got: %v", tc.expected, got) + } + + }) + } +} + +func validConfig() Config { + return Config{ + ImpostersPath: "imposters", + Port: 3000, + Host: "localhost", + CORS: ConfigCORS{ + Methods: []string{"GET"}, + Origins: []string{"*"}, + Headers: []string{"Content-Type"}, + ExposedHeaders: []string{"Cache-Control"}, + AllowCredentials: true, + }, + } +} diff --git a/internal/route_matchers_test.go b/internal/route_matchers_test.go index 21081f4..b883cfe 100644 --- a/internal/route_matchers_test.go +++ b/internal/route_matchers_test.go @@ -7,12 +7,14 @@ import ( "testing" "github.com/gorilla/mux" + "github.com/pkg/errors" ) func TestMatcherBySchema(t *testing.T) { bodyA := ioutil.NopCloser(bytes.NewReader([]byte("{\"type\": \"gopher\"}"))) bodyB := ioutil.NopCloser(bytes.NewReader([]byte("{\"type\": \"cat\"}"))) emptyBody := ioutil.NopCloser(bytes.NewReader([]byte(""))) + wrongBody := ioutil.NopCloser(errReader(0)) schemaGopherFile := "test/testdata/imposters/schemas/type_gopher.json" schemaCatFile := "test/testdata/imposters/schemas/type_cat.json" @@ -46,22 +48,22 @@ func TestMatcherBySchema(t *testing.T) { httpRequestB := &http.Request{Body: bodyB} okResponse := Response{Status: http.StatusOK} - var matcherData = []struct { - name string - fn mux.MatcherFunc - req *http.Request - res bool + var matcherData = map[string]struct { + fn mux.MatcherFunc + req *http.Request + res bool }{ - {"correct request schema", MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), httpRequestA, true}, - {"imposter without request schema", MatcherBySchema(Imposter{Request: requestWithoutSchema, Response: okResponse}), httpRequestA, true}, - {"malformatted schema file", MatcherBySchema(Imposter{Request: requestWithWrongSchema, Response: okResponse}), httpRequestA, false}, - {"incorrect request schema", MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), httpRequestB, false}, - {"non-existing schema file", MatcherBySchema(Imposter{Request: requestWithNonExistingSchema, Response: okResponse}), httpRequestB, false}, - {"empty body with required schema file", MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), &http.Request{Body: emptyBody}, false}, + "correct request schema": {MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), httpRequestA, true}, + "imposter without request schema": {MatcherBySchema(Imposter{Request: requestWithoutSchema, Response: okResponse}), httpRequestA, true}, + "malformatted schema file": {MatcherBySchema(Imposter{Request: requestWithWrongSchema, Response: okResponse}), httpRequestA, false}, + "incorrect request schema": {MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), httpRequestB, false}, + "non-existing schema file": {MatcherBySchema(Imposter{Request: requestWithNonExistingSchema, Response: okResponse}), httpRequestB, false}, + "empty body with required schema file": {MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), &http.Request{Body: emptyBody}, false}, + "invalid request body": {MatcherBySchema(Imposter{Request: requestWithSchema, Response: okResponse}), &http.Request{Body: wrongBody}, false}, } - for _, tt := range matcherData { - t.Run(tt.name, func(t *testing.T) { + for name, tt := range matcherData { + t.Run(name, func(t *testing.T) { res := tt.fn(tt.req, nil) if res != tt.res { t.Fatalf("error while matching by request schema - expected: %t, given: %t", tt.res, res) @@ -70,3 +72,9 @@ func TestMatcherBySchema(t *testing.T) { } } + +type errReader int + +func (errReader) Read(p []byte) (n int, err error) { + return 0, errors.New("test error") +} diff --git a/internal/server.go b/internal/server.go index 2fec971..0dae391 100644 --- a/internal/server.go +++ b/internal/server.go @@ -2,6 +2,7 @@ package killgrave import ( "encoding/json" + "fmt" "io/ioutil" "log" "os" @@ -13,8 +14,9 @@ import ( ) var ( - defaultCORSMethods = []string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"} - defaultCORSHeaders = []string{"X-Requested-With", "Content-Type", "Authorization", "*"} + defaultCORSMethods = []string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"} + defaultCORSHeaders = []string{"X-Requested-With", "Content-Type", "Authorization"} + defaultCORSExposedHeaders = []string{"Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma"} ) // Server definition of mock server @@ -35,6 +37,7 @@ func NewServer(p string, r *mux.Router) *Server { func (s *Server) AccessControl(config ConfigCORS) (h []handlers.CORSOption) { h = append(h, handlers.AllowedMethods(defaultCORSMethods)) h = append(h, handlers.AllowedHeaders(defaultCORSHeaders)) + h = append(h, handlers.ExposedHeaders(defaultCORSExposedHeaders)) if len(config.Methods) > 0 { h = append(h, handlers.AllowedMethods(config.Methods)) @@ -51,6 +54,12 @@ func (s *Server) AccessControl(config ConfigCORS) (h []handlers.CORSOption) { if len(config.ExposedHeaders) > 0 { h = append(h, handlers.ExposedHeaders(config.ExposedHeaders)) } + + fmt.Println(config) + if config.AllowCredentials { + h = append(h, handlers.AllowCredentials()) + } + return } diff --git a/internal/server_test.go b/internal/server_test.go index 2c8a84a..c870954 100644 --- a/internal/server_test.go +++ b/internal/server_test.go @@ -39,7 +39,20 @@ func TestRunServer(t *testing.T) { func TestAccessControl(t *testing.T) { s := NewServer("test/testdata/imposters", mux.NewRouter()) - h := s.AccessControl() + config := Config{ + ImpostersPath: "imposters", + Port: 3000, + Host: "localhost", + CORS: ConfigCORS{ + Methods: []string{"GET"}, + Origins: []string{"*"}, + Headers: []string{"Content-Type"}, + ExposedHeaders: []string{"Cache-Control"}, + AllowCredentials: true, + }, + } + + h := s.AccessControl(config.CORS) if len(h) <= 0 { t.Fatal("Expected any CORS options and got empty") diff --git a/internal/test/testdata/config.yml b/internal/test/testdata/config.yml new file mode 100644 index 0000000..b3bc62d --- /dev/null +++ b/internal/test/testdata/config.yml @@ -0,0 +1,9 @@ +imposters_path: "imposters" +port: 3000 +host: "localhost" +cors: + methods: ["GET"] + headers: ["Content-Type"] + exposed_headers: ["Cache-Control"] + origins: ["*"] + allow_credentials: true diff --git a/internal/test/testdata/wrong_config.yml b/internal/test/testdata/wrong_config.yml new file mode 100644 index 0000000..8276753 --- /dev/null +++ b/internal/test/testdata/wrong_config.yml @@ -0,0 +1 @@ +error From 5e7db4ad4d41e3869bf834937ac03e1fc7302bf0 Mon Sep 17 00:00:00 2001 From: aperezg Date: Sat, 11 May 2019 15:36:44 +0200 Subject: [PATCH 4/5] Adapt the changelog and REAMDME to new version v0.3.3.Fixes #16 --- CHANGELOG.md | 14 ++++++++- README.md | 71 +++++++++++++++++++++++++++++++++++++++++----- internal/server.go | 2 -- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fef0a6..c461827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## v0.3.3 (2019/05/11) + +* Improve default CORS options +* Allow up mock server via config file +* Allow configure CORS options + * Access-Control-Request-Method + * Access-Control-Request-Headers + * Access-Control-Allow-Origin + * Access-Control-Expose-Headers + * Access-Control-Allow-Credentials +* Improve route_mateches unit tests + ## v0.3.2 (2019/05/08) * Fix CORS add AccessControl allowing methods and headers @@ -37,4 +49,4 @@ * Convert headers into canonical mime type * Run server with imposter configuration * Processing and parsing imposters file -* Initial version \ No newline at end of file +* Initial version diff --git a/README.md b/README.md index 52b1275..9549cf1 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,17 @@ Or you can download the binary for your arch on: [https://github.com/friendsofgo/killgrave/releases](https://github.com/friendsofgo/killgrave/releases) +### Docker + +The application is also available through [Docker](https://hub.docker.com/r/friendsofgo/killgrave), just run: + +```bash +docker run -it --rm -p 3000:3000 -v $PWD/:/home -w /home friendsofgo/killgrave +``` +Remember to use the [-p](https://docs.docker.com/engine/reference/run/) flag to expose the container port where the application is listening (3000 by default). + +NOTE: If you want to use `killgrave` through Docker at the same time you use your own dockerised HTTP-based API, be careful with networking issues. + ## Using Killgrave Use `killgrave` with default flags: @@ -39,6 +50,8 @@ $ killgrave ``` Or custome your server with this flags: ```sh + -config string + path with configuration file -host string if you run your server on a different host (default "localhost") -imposters string @@ -49,6 +62,28 @@ Or custome your server with this flags: show the version of the application ``` +Use `killgrave` with config file: + +First of all you need create a file with a valid config, i.e: + +```yaml +#config.yml + +imposters_path: "imposters" +port: 3000 +host: "localhost" +cors: + methods: ["GET"] + headers: ["Content-Type"] + exposed_headers: ["Cache-Control"] + origins: ["*"] + allow_credentials: true +``` + +The parameter `cors` is optional and his options can be empty array, the other options `imposters_path`, `port`, `host` are mandatory. + +If you want more information about the CORS options, visit the [CORS section](#CORS). + ## How to use ### Create an imposter @@ -178,17 +213,37 @@ curl --header "Content-Type: application/json" \ http://localhost:3000/gophers ``` -### Docker +## CORS -The application is also available through [Docker](https://hub.docker.com/r/friendsofgo/killgrave), just run: +If you want to use `killgrave` on your client application you must consider to configure correctly all about CORS, thus we offer the possibility to configure as you need through a config file. -```bash -docker run -it --rm -p 3000:3000 friendsofgo/killgrave -``` +In the CORS section of the file you can found the next options: -Remember to use the [-p](https://docs.docker.com/engine/reference/run/) flag to expose the container port where the application is listening (3000 by default). +- **methods** (string array) + + Represent the **Access-Control-Request-Method header**, if you not specified or leave as empty array the default value will be: -NOTE: If you want to use `killgrave` through Docker at the same time you use your own dockerised HTTP-based API, be careful with networking issues. + `"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"` + +- **headers** (string array) + + Represent the **Access-Control-Request-Headers header**, if you not specified or leave as empty array the default value will be: + + `"X-Requested-With", "Content-Type", "Authorization"` + +- **exposed_headers** (string array) + + Represent the **Access-Control-Expose-Headers header**, if you not specified or leave as empty array the default value will be: + + `"Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma"` + +- **origins** (string array) + + Represent the **Access-Control-Allow-Origin header**, if you not specified or leave as empty array this options has not default value + +- **allow_credentials** (boolean) + + Represent the **Access-Control-Allow-Credentials header** you must indicate if true or false ## Features * Imposters created in json @@ -206,6 +261,8 @@ NOTE: If you want to use `killgrave` through Docker at the same time you use you * Dynamic responses based on query params * Allow organize your imposters with structured folders * Allow write multiple imposters by file +* Run mock server with predefined configuration with config yaml file +* Configure your CORS server options ## Next Features - [ ] Proxy server diff --git a/internal/server.go b/internal/server.go index 0dae391..e3a5eac 100644 --- a/internal/server.go +++ b/internal/server.go @@ -2,7 +2,6 @@ package killgrave import ( "encoding/json" - "fmt" "io/ioutil" "log" "os" @@ -55,7 +54,6 @@ func (s *Server) AccessControl(config ConfigCORS) (h []handlers.CORSOption) { h = append(h, handlers.ExposedHeaders(config.ExposedHeaders)) } - fmt.Println(config) if config.AllowCredentials { h = append(h, handlers.AllowCredentials()) } From b2c09ad412935750bf5dcb857f1664ca882ad382 Mon Sep 17 00:00:00 2001 From: aperezg Date: Sat, 11 May 2019 23:41:23 +0200 Subject: [PATCH 5/5] fixes PR comments --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9549cf1..846fd6c 100644 --- a/README.md +++ b/README.md @@ -217,29 +217,29 @@ curl --header "Content-Type: application/json" \ If you want to use `killgrave` on your client application you must consider to configure correctly all about CORS, thus we offer the possibility to configure as you need through a config file. -In the CORS section of the file you can found the next options: +In the CORS section of the file you can find the next options: - **methods** (string array) - Represent the **Access-Control-Request-Method header**, if you not specified or leave as empty array the default value will be: + Represent the **Access-Control-Request-Method header**, if you don't specify it or if you do leave it as any empty array, the default values will be: `"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE", "PATCH", "TRACE", "CONNECT"` - **headers** (string array) - Represent the **Access-Control-Request-Headers header**, if you not specified or leave as empty array the default value will be: + Represent the **Access-Control-Request-Headers header**, if you don't specify it or if you do leave it as any empty array, the default values will be: `"X-Requested-With", "Content-Type", "Authorization"` - **exposed_headers** (string array) - Represent the **Access-Control-Expose-Headers header**, if you not specified or leave as empty array the default value will be: + Represent the **Access-Control-Expose-Headers header**, if you don't specify it or if you do leave it as any empty array, the default values will be: `"Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma"` - **origins** (string array) - Represent the **Access-Control-Allow-Origin header**, if you not specified or leave as empty array this options has not default value + Represent the **Access-Control-Allow-Origin header**, if you don't specify or leave as empty array this options has not default value - **allow_credentials** (boolean)