From 30e31e546f88bf52786caca19d8b304f9ae1b249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ph=C6=B0=E1=BB=9Bc=20Trung?= Date: Tue, 9 Aug 2022 16:37:29 +0700 Subject: [PATCH 01/11] Fires 404 HTTP Code when use gRPC strict mode --- mvc/grpc.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mvc/grpc.go b/mvc/grpc.go index e3cbe86f..34f9c87b 100644 --- a/mvc/grpc.go +++ b/mvc/grpc.go @@ -47,7 +47,14 @@ func (g GRPC) Apply(c *ControllerActivator) { return } - // If strict was false, allow common HTTP clients, consumes and produces JSON. + // If strict was true fires 404 on common HTTP clients. + if g.Strict { + ctx.NotFound() + ctx.StopExecution() + return + } + + // Allow common HTTP clients, consumes and produces JSON. ctx.Next() } From dd4bc50f7842bb4baf6e565f6712028644c4d98a Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 12 Aug 2022 00:05:44 +0300 Subject: [PATCH 02/11] improvements on the x/jsonx/iso8601 time format --- x/jsonx/iso8601.go | 99 ++++++++++++++++++++++++++++++++++++++++- x/jsonx/iso8601_test.go | 81 +++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 x/jsonx/iso8601_test.go diff --git a/x/jsonx/iso8601.go b/x/jsonx/iso8601.go index c5d22b8e..8fc26512 100644 --- a/x/jsonx/iso8601.go +++ b/x/jsonx/iso8601.go @@ -1,18 +1,34 @@ package jsonx import ( + "database/sql/driver" + "errors" "fmt" "strconv" "strings" "time" ) +var fixedEastUTCLocations = make(map[int]*time.Location) + +func registerFixedEastUTCLocation(name string, secondsFromUTC int) { + loc := time.FixedZone(name, secondsFromUTC) + fixedEastUTCLocations[secondsFromUTC] = loc +} + +func init() { + registerFixedEastUTCLocation("EEST", 3*60*60) // + 3 hours. +} + const ( // ISO8601Layout holds the time layout for the the javascript iso time. // Read more at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString. ISO8601Layout = "2006-01-02T15:04:05" // ISO8601ZLayout same as ISO8601Layout but with the timezone suffix. ISO8601ZLayout = "2006-01-02T15:04:05Z" + // ISO8601ZUTCOffsetLayout ISO 8601 format, with full time and zone with UTC offset. + // Example: 2022-08-10T03:21:00.000000+03:00. + ISO8601ZUTCOffsetLayout = "2006-01-02T15:04:05.999999Z07:00" ) // ISO8601 describes a time compatible with javascript time format. @@ -29,7 +45,28 @@ func ParseISO8601(s string) (ISO8601, error) { err error ) - if s[len(s)-1] == 'Z' { + if idx := strings.LastIndexFunc(s, startUTCOffsetIndexFunc); idx > 20 /* should have some distance, e.g. 26 */ { + length := parseSignedOffset(s[idx:]) + + if idx+1 > idx+length || len(s) <= idx+length+1 { + return ISO8601{}, fmt.Errorf("ISO8601: invalid timezone format: %s", s[idx:]) + } + + offsetText := s[idx+1 : idx+length] + offset, parseErr := strconv.Atoi(offsetText) + if parseErr != nil { + return ISO8601{}, err + } + + // E.g. offset of +0300 is returned as 10800 which is - (3 * 60 * 60). + secondsEastUTC := offset * 60 * 60 + + if loc, ok := fixedEastUTCLocations[secondsEastUTC]; ok { // Specific (fixed) zone. + tt, err = time.ParseInLocation(ISO8601ZUTCOffsetLayout, s, loc) + } else { // Local or UTC. + tt, err = time.Parse(ISO8601ZUTCOffsetLayout, s) + } + } else if s[len(s)-1] == 'Z' { tt, err = time.Parse(ISO8601ZLayout, s) } else { tt, err = time.Parse(ISO8601Layout, s) @@ -39,7 +76,7 @@ func ParseISO8601(s string) (ISO8601, error) { return ISO8601{}, err } - return ISO8601(tt.UTC()), nil + return ISO8601(tt), nil } // UnmarshalJSON parses the "b" into ISO8601 time. @@ -90,6 +127,11 @@ func (t ISO8601) String() string { return tt.Format(ISO8601Layout) } +// Value returns the database value of time.Time. +func (t ISO8601) Value() (driver.Value, error) { + return time.Time(t), nil +} + // Scan completes the sql driver.Scanner interface. func (t *ISO8601) Scan(src interface{}) error { switch v := src.(type) { @@ -104,6 +146,8 @@ func (t *ISO8601) Scan(src interface{}) error { return err } *t = tt + case []byte: + return t.Scan(string(v)) case nil: *t = ISO8601(time.Time{}) default: @@ -112,3 +156,54 @@ func (t *ISO8601) Scan(src interface{}) error { return nil } + +// parseSignedOffset parses a signed timezone offset (e.g. "+03" or "-04"). +// The function checks for a signed number in the range -23 through +23 excluding zero. +// Returns length of the found offset string or 0 otherwise. +// +// Language internal function. +func parseSignedOffset(value string) int { + sign := value[0] + if sign != '-' && sign != '+' { + return 0 + } + x, rem, err := leadingInt(value[1:]) + + // fail if nothing consumed by leadingInt + if err != nil || value[1:] == rem { + return 0 + } + if x > 23 { + return 0 + } + return len(value) - len(rem) +} + +var errLeadingInt = errors.New("ISO8601: time: bad [0-9]*") // never printed. + +// leadingInt consumes the leading [0-9]* from s. +// +// Language internal function. +func leadingInt(s string) (x uint64, rem string, err error) { + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if x > 1<<63/10 { + // overflow + return 0, "", errLeadingInt + } + x = x*10 + uint64(c) - '0' + if x > 1<<63 { + // overflow + return 0, "", errLeadingInt + } + } + return x, s[i:], nil +} + +func startUTCOffsetIndexFunc(char rune) bool { + return char == '+' || char == '-' +} diff --git a/x/jsonx/iso8601_test.go b/x/jsonx/iso8601_test.go new file mode 100644 index 00000000..cba8defd --- /dev/null +++ b/x/jsonx/iso8601_test.go @@ -0,0 +1,81 @@ +package jsonx + +import ( + "encoding/json" + "testing" + "time" +) + +func TestISO8601(t *testing.T) { + data := `{"start": "2021-08-20T10:05:01", "end": "2021-12-01T17:05:06", "nothing": null, "empty": ""}` + v := struct { + Start ISO8601 `json:"start"` + End ISO8601 `json:"end"` + Nothing ISO8601 `json:"nothing"` + Empty ISO8601 `json:"empty"` + }{} + err := json.Unmarshal([]byte(data), &v) + if err != nil { + t.Fatal(err) + } + + if !v.Nothing.IsZero() { + t.Fatalf("expected 'nothing' to be zero but got: %v", v.Nothing) + } + + if !v.Empty.IsZero() { + t.Fatalf("expected 'empty' to be zero but got: %v", v.Empty) + } + + loc := time.UTC + + if expected, got := time.Date(2021, time.August, 20, 10, 5, 1, 0, loc), v.Start.ToTime(); expected != got { + t.Fatalf("expected 'start' to be: %v but got: %v", expected, got) + } + + if expected, got := time.Date(2021, time.December, 1, 17, 5, 6, 0, loc), v.End.ToTime(); expected != got { + t.Fatalf("expected 'start' to be: %v but got: %v", expected, got) + } +} + +func TestISO8601WithZoneUTCOffset(t *testing.T) { + data := `{"start": "2022-08-10T03:21:00.000000+03:00", "end": "2022-08-10T09:49:00.000000+03:00", "nothing": null, "empty": ""}` + v := struct { + Start ISO8601 `json:"start"` + End ISO8601 `json:"end"` + Nothing ISO8601 `json:"nothing"` + Empty ISO8601 `json:"empty"` + }{} + err := json.Unmarshal([]byte(data), &v) + if err != nil { + t.Fatalf("unmarshal: %v", err) + } + + // t.Logf("Start: %s, location: %s\n", v.Start.String(), v.Start.ToTime().Location().String()) + + if !v.Nothing.IsZero() { + t.Fatalf("expected 'nothing' to be zero but got: %v", v.Nothing) + } + + if !v.Empty.IsZero() { + t.Fatalf("expected 'empty' to be zero but got: %v", v.Empty) + } + + loc := time.FixedZone("EEST", 10800) + + if expected, got := time.Date(2022, time.August, 10, 3, 21, 0, 0, loc).String(), v.Start.ToTime().String(); expected != got { + t.Fatalf("expected 'start' string to be: %v but got: %v", expected, got) + } + + if expected, got := time.Date(2022, time.August, 10, 9, 49, 0, 0, loc).String(), v.End.ToTime().String(); expected != got { + t.Fatalf("expected 'start' string to be: %v but got: %v", expected, got) + } + + if expected, got := time.Date(2022, time.August, 10, 3, 21, 0, 0, loc), v.Start.ToTime().In(loc); expected != got { + t.Fatalf("expected 'start' to be: %v but got: %v", expected, got) + } + + if expected, got := time.Date(2022, time.August, 10, 9, 49, 0, 0, loc), v.End.ToTime().In(loc); expected != got { + t.Fatalf("expected 'start' to be: %v but got: %v", expected, got) + } +} From 3715a66ef06ca0f28f04d3b6940b765abf19ed25 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 12 Aug 2022 21:07:39 +0300 Subject: [PATCH 03/11] fix #1949 --- context/context.go | 23 ++++++++++++++++++++--- x/jsonx/iso8601.go | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/context/context.go b/context/context.go index 900785fc..1f2a1f52 100644 --- a/context/context.go +++ b/context/context.go @@ -2575,8 +2575,12 @@ func (ctx *Context) RecordRequestBody(b bool) { // IsRecordingBody reports whether the request body can be readen multiple times. func (ctx *Context) IsRecordingBody() bool { - return ctx.values.GetBoolDefault(disableRequestBodyConsumptionContextKey, - ctx.app.ConfigurationReadOnly().GetDisableBodyConsumptionOnUnmarshal()) + if ctx.app.ConfigurationReadOnly().GetDisableBodyConsumptionOnUnmarshal() { + return true + } + + value, _ := ctx.values.GetBool(disableRequestBodyConsumptionContextKey) + return value } // GetBody reads and returns the request body. @@ -2672,7 +2676,20 @@ type JSONReader struct { // Note(@kataras): struct instead of optional funcs to } var ReadJSON = func(ctx *Context, outPtr interface{}, opts ...JSONReader) error { - decoder := json.NewDecoder(ctx.request.Body) + var body io.Reader + + if ctx.IsRecordingBody() { + data, err := io.ReadAll(ctx.request.Body) + if err != nil { + return err + } + setBody(ctx.request, data) + body = bytes.NewReader(data) + } else { + body = ctx.request.Body + } + + decoder := json.NewDecoder(body) // decoder := gojson.NewDecoder(ctx.Request().Body) if len(opts) > 0 { options := opts[0] diff --git a/x/jsonx/iso8601.go b/x/jsonx/iso8601.go index 8fc26512..cae75ebe 100644 --- a/x/jsonx/iso8601.go +++ b/x/jsonx/iso8601.go @@ -27,7 +27,7 @@ const ( // ISO8601ZLayout same as ISO8601Layout but with the timezone suffix. ISO8601ZLayout = "2006-01-02T15:04:05Z" // ISO8601ZUTCOffsetLayout ISO 8601 format, with full time and zone with UTC offset. - // Example: 2022-08-10T03:21:00.000000+03:00. + // Example: 2022-08-10T03:21:00.000000+03:00, 2022-08-09T00:00:00.000000. ISO8601ZUTCOffsetLayout = "2006-01-02T15:04:05.999999Z07:00" ) From f91269130ed30b72578334844d10c0d17dc42221 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 13 Aug 2022 09:07:00 +0300 Subject: [PATCH 04/11] add a more straightforward example for #1953 --- _examples/README.md | 1 + .../routing/dynamic-path/at-username/main.go | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 _examples/routing/dynamic-path/at-username/main.go diff --git a/_examples/README.md b/_examples/README.md index 4dbe6f81..55e5ddda 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -55,6 +55,7 @@ * [Not Found - Intelligence](routing/intelligence/main.go) * [Not Found - Suggest Closest Paths](routing/intelligence/manual/main.go) * [Dynamic Path](routing/dynamic-path/main.go) + * [At-username](routing/dynamic-path/at-username/main.go) * [Root Wildcard](routing/dynamic-path/root-wildcard/main.go) * [Implement a Parameter Type](routing/macros/main.go) * [Same Path Pattern but Func](routing/dynamic-path/same-pattern-different-func/main.go) diff --git a/_examples/routing/dynamic-path/at-username/main.go b/_examples/routing/dynamic-path/at-username/main.go new file mode 100644 index 00000000..36e88cb3 --- /dev/null +++ b/_examples/routing/dynamic-path/at-username/main.go @@ -0,0 +1,30 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.Get("/", func(c iris.Context) { + c.Writef("Hello %s", "world") + }) + + // This is an Iris-only feature across all web frameworks + // in every programming language for years. + // Dynamic Route Path Parameters Functions. + // Set min length characters to 2. + // Prefix of the username is '@' + // Otherwise 404. + // + // You can also use the regexp(...) function for more advanced expressions. + app.Get("/{username:string min(2) prefix(@)}", func(ctx iris.Context) { + username := ctx.Params().Get("username")[1:] + ctx.Writef("Username is %s", username) + }) + + // http://localhost:8080 -> FOUND (Hello world) + // http://localhost:8080/other -> NOT FOUND + // http://localhost/@ -> NOT FOUND + // http://localhost:8080/@kataras -> FOUND (username is kataras) + app.Listen(":8080") +} From 5e0bea81122375b6467ad5b6e3635cec8c827feb Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sun, 14 Aug 2022 23:59:07 +0300 Subject: [PATCH 05/11] fix https://github.com/kataras/iris/issues/1841 --- _examples/routing/dynamic-path/at-username/main.go | 6 +++--- sessions/sessiondb/redis/database.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/_examples/routing/dynamic-path/at-username/main.go b/_examples/routing/dynamic-path/at-username/main.go index 36e88cb3..e6496d01 100644 --- a/_examples/routing/dynamic-path/at-username/main.go +++ b/_examples/routing/dynamic-path/at-username/main.go @@ -5,8 +5,8 @@ import "github.com/kataras/iris/v12" func main() { app := iris.New() - app.Get("/", func(c iris.Context) { - c.Writef("Hello %s", "world") + app.Get("/", func(ctx iris.Context) { + ctx.Writef("Hello %s", "world") }) // This is an Iris-only feature across all web frameworks @@ -24,7 +24,7 @@ func main() { // http://localhost:8080 -> FOUND (Hello world) // http://localhost:8080/other -> NOT FOUND - // http://localhost/@ -> NOT FOUND + // http://localhost:8080/@ -> NOT FOUND // http://localhost:8080/@kataras -> FOUND (username is kataras) app.Listen(":8080") } diff --git a/sessions/sessiondb/redis/database.go b/sessions/sessiondb/redis/database.go index 1773a208..ed40b257 100644 --- a/sessions/sessiondb/redis/database.go +++ b/sessions/sessiondb/redis/database.go @@ -267,7 +267,8 @@ func (db *Database) Delete(sid string, key string) (deleted bool) { // Clear removes all session key values but it keeps the session entry. func (db *Database) Clear(sid string) error { - keys := db.keys(db.makeSID(sid)) + sid = db.makeSID(sid) + keys := db.keys(sid) for _, key := range keys { if key == SessionIDKey { continue From 0d63ef41b82cacd60778c337060d2d7be0963bed Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 15 Aug 2022 00:37:26 +0300 Subject: [PATCH 06/11] accept feature request: #1941 --- context/context.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/context/context.go b/context/context.go index 1f2a1f52..08f56f71 100644 --- a/context/context.go +++ b/context/context.go @@ -2795,6 +2795,24 @@ var ( // A shortcut for the `schema#IsErrPath`. IsErrPath = schema.IsErrPath + // IsErrPathCRSFToken reports whether the given "err" is caused + // by unknown key error on "csrf.token". See `context#ReadForm` for more. + IsErrPathCRSFToken = func(err error) bool { + if err == nil || CSRFTokenFormKey == "" { + return false + } + + if m, ok := err.(schema.MultiError); ok { + if csrfErr, hasCSRFToken := m[CSRFTokenFormKey]; hasCSRFToken { + _, is := csrfErr.(schema.UnknownKeyError) + return is + + } + } + + return false + } + // ErrEmptyForm is returned by // - `context#ReadForm` // - `context#ReadQuery` @@ -2837,6 +2855,11 @@ var ( } ) +// CSRFTokenFormKey the CSRF token key of the form data. +// +// See ReadForm method for more. +const CSRFTokenFormKey = "csrf.token" + // ReadForm binds the request body of a form to the "formObject". // It supports any kind of type, including custom structs. // It will return nothing if request data are empty. @@ -2848,6 +2871,9 @@ var ( // If a client sent an unknown field, this method will return an error, // in order to ignore that error use the `err != nil && !iris.IsErrPath(err)`. // +// As of 15 Aug 2022, ReadForm does not return an error over unknown CSRF token form key, +// to change this behavior globally, set the `context.CSRFTokenFormKey` to an empty value. +// // Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-form/main.go func (ctx *Context) ReadForm(formObject interface{}) error { values := ctx.FormValues() @@ -2859,7 +2885,7 @@ func (ctx *Context) ReadForm(formObject interface{}) error { } err := schema.DecodeForm(values, formObject) - if err != nil { + if err != nil && !IsErrPathCRSFToken(err) { return err } From 16af6d017fc885775cca156a2ee68a006454d49e Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 15 Aug 2022 00:44:26 +0300 Subject: [PATCH 07/11] update deps, go 1.19 --- .github/workflows/ci.yml | 2 +- HISTORY.md | 2 ++ README.md | 2 +- README_FA.md | 2 +- go.mod | 14 +++++++------- go.sum | 23 ++++++++++++----------- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9eaca0bb..8e75794c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: - go_version: [1.18.x] + go_version: [1.19.x] steps: - name: Set up Go 1.x diff --git a/HISTORY.md b/HISTORY.md index 65df6d2e..3c88a5b6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -28,6 +28,8 @@ The codebase for Dependency Injection, Internationalization and localization and ## Fixes and Improvements +- Ignore `"csrf.token"` form data key when missing on `ctx.ReadForm` by default as requested at [#1941](https://github.com/kataras/iris/issues/1941). + - Fix [CVE-2020-5398](https://github.com/advisories/GHSA-8wx2-9q48-vm9r). - New `{x:weekday}` path parameter type, example code: diff --git a/README.md b/README.md index a0d5b016..1fb740dd 100644 --- a/README.md +++ b/README.md @@ -470,7 +470,7 @@ $ go get github.com/kataras/iris/v12@master **Run** ```sh -$ go mod tidy -compat=1.18 +$ go mod tidy -compat=1.19 $ go run . ``` diff --git a/README_FA.md b/README_FA.md index 89c1f3a8..a5df3f46 100644 --- a/README_FA.md +++ b/README_FA.md @@ -261,7 +261,7 @@ $ go get github.com/kataras/iris/v12@master ```txt module myapp -go 1.18 +go 1.19 require github.com/kataras/iris/v12 master ``` diff --git a/go.mod b/go.mod index faf4da1d..21e959f7 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/kataras/iris/v12 -go 1.18 +go 1.19 // retract v12.1.8 // please update to @master require ( github.com/BurntSushi/toml v1.2.0 github.com/CloudyKit/jet/v6 v6.1.0 - github.com/Shopify/goreferrer v0.0.0-20210630161223-536fa16abd6f + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 github.com/andybalholm/brotli v1.0.4 github.com/blang/semver/v4 v4.0.0 github.com/dgraph-io/badger/v2 v2.2007.4 @@ -40,11 +40,11 @@ require ( github.com/vmihailenco/msgpack/v5 v5.3.5 github.com/yosssi/ace v0.0.5 go.etcd.io/bbolt v1.3.6 - golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 - golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa + golang.org/x/net v0.0.0-20220812174116-3211cb980234 + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab golang.org/x/text v0.3.7 - golang.org/x/time v0.0.0-20220411224347-583f2d630306 + golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 google.golang.org/protobuf v1.28.1 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v3 v3.0.1 @@ -81,7 +81,7 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/nats-io/jwt/v2 v2.2.0 // indirect + github.com/nats-io/jwt/v2 v2.3.0 // indirect github.com/nats-io/nats.go v1.16.0 // indirect github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect diff --git a/go.sum b/go.sum index 4fac3f0e..3d620f7d 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/Shopify/goreferrer v0.0.0-20210630161223-536fa16abd6f h1:XeOBnoBP7K19tMBEKeUo1NOxOO+h5FFi2HGzQvvkb44= -github.com/Shopify/goreferrer v0.0.0-20210630161223-536fa16abd6f/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -150,8 +150,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nats-io/jwt/v2 v2.2.0 h1:Yg/4WFK6vsqMudRg91eBb7Dh6XeVcDMPHycDE8CfltE= -github.com/nats-io/jwt/v2 v2.2.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= +github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI= +github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4= github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g= github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= @@ -245,13 +245,13 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8= -golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= +golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -266,15 +266,16 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= -golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 057fa462f496303e3ad05355d6e9bacbc27c5f9e Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 15 Aug 2022 00:58:49 +0300 Subject: [PATCH 08/11] allow setting a custom go-redis client at Iris go redis sessions driver as request at https://chat.iris-go.com --- HISTORY.md | 1 + _examples/sessions/database/redis/main.go | 7 +++- sessions/sessiondb/redis/database.go | 1 + sessions/sessiondb/redis/driver_goredis.go | 44 ++++++++++++++-------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 3c88a5b6..05cee57e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -28,6 +28,7 @@ The codebase for Dependency Injection, Internationalization and localization and ## Fixes and Improvements +- Enable setting a custom "go-redis" client through `SetClient` go redis driver method or `Client` struct field on sessions/database/redis driver as requested at [chat](https://chat.iris-go.com). - Ignore `"csrf.token"` form data key when missing on `ctx.ReadForm` by default as requested at [#1941](https://github.com/kataras/iris/issues/1941). - Fix [CVE-2020-5398](https://github.com/advisories/GHSA-8wx2-9q48-vm9r). diff --git a/_examples/sessions/database/redis/main.go b/_examples/sessions/database/redis/main.go index 81a15c12..e7f7cea5 100644 --- a/_examples/sessions/database/redis/main.go +++ b/_examples/sessions/database/redis/main.go @@ -30,11 +30,16 @@ func main() { Password: "", Database: "", Prefix: "myapp-", - Driver: redis.GoRedis(), // defaults. + Driver: redis.GoRedis(), // defaults to this driver. + // To set a custom, existing go-redis client, use the "SetClient" method: + // Driver: redis.GoRedis().SetClient(customGoRedisClient) }) // Optionally configure the underline driver: // driver := redis.GoRedis() + // // To set a custom client: + // driver.SetClient(customGoRedisClient) + // OR: // driver.ClientOptions = redis.Options{...} // driver.ClusterOptions = redis.ClusterOptions{...} // redis.New(redis.Config{Driver: driver, ...}) diff --git a/sessions/sessiondb/redis/database.go b/sessions/sessiondb/redis/database.go index ed40b257..3307b1af 100644 --- a/sessions/sessiondb/redis/database.go +++ b/sessions/sessiondb/redis/database.go @@ -30,6 +30,7 @@ type Config struct { Addr string // Clusters a list of network addresses for clusters. // If not empty "Addr" is ignored and Redis clusters feature is used instead. + // Note that this field is ignored when setgging a custom `GoRedisClient`. Clusters []string // Use the specified Username to authenticate the current connection // with one of the connections defined in the ACL list when connecting diff --git a/sessions/sessiondb/redis/driver_goredis.go b/sessions/sessiondb/redis/driver_goredis.go index 6477cd75..50e994d0 100644 --- a/sessions/sessiondb/redis/driver_goredis.go +++ b/sessions/sessiondb/redis/driver_goredis.go @@ -27,7 +27,9 @@ type GoRedisClient interface { // for the go-redis redis driver. See driver.go file. type GoRedisDriver struct { // Both Client and ClusterClient implements this interface. - client GoRedisClient + // Custom one can be directly passed but if so, the + // Connect method does nothing (so all connection and client settings are ignored). + Client GoRedisClient // Customize any go-redis fields manually // before Connect. ClientOptions Options @@ -111,12 +113,24 @@ func (r *GoRedisDriver) mergeClusterOptions(c Config) *ClusterOptions { return &opts } +// SetClient sets an existing go redis client to the sessions redis driver. +// +// Returns itself. +func (r *GoRedisDriver) SetClient(goRedisClient GoRedisClient) *GoRedisDriver { + r.Client = goRedisClient + return r +} + // Connect initializes the redis client. func (r *GoRedisDriver) Connect(c Config) error { + if r.Client != nil { // if a custom one was given through SetClient. + return nil + } + if len(c.Clusters) > 0 { - r.client = redis.NewClusterClient(r.mergeClusterOptions(c)) + r.Client = redis.NewClusterClient(r.mergeClusterOptions(c)) } else { - r.client = redis.NewClient(r.mergeClientOptions(c)) + r.Client = redis.NewClient(r.mergeClientOptions(c)) } return nil @@ -125,29 +139,29 @@ func (r *GoRedisDriver) Connect(c Config) error { // PingPong sends a ping message and reports whether // the PONG message received successfully. func (r *GoRedisDriver) PingPong() (bool, error) { - pong, err := r.client.Ping(defaultContext).Result() + pong, err := r.Client.Ping(defaultContext).Result() return pong == "PONG", err } // CloseConnection terminates the underline redis connection. func (r *GoRedisDriver) CloseConnection() error { - return r.client.Close() + return r.Client.Close() } // Set stores a "value" based on the session's "key". // The value should be type of []byte, so unmarshal can happen. func (r *GoRedisDriver) Set(sid, key string, value interface{}) error { - return r.client.HSet(defaultContext, sid, key, value).Err() + return r.Client.HSet(defaultContext, sid, key, value).Err() } // Get returns the associated value of the session's given "key". func (r *GoRedisDriver) Get(sid, key string) (interface{}, error) { - return r.client.HGet(defaultContext, sid, key).Bytes() + return r.Client.HGet(defaultContext, sid, key).Bytes() } // Exists reports whether a session exists or not. func (r *GoRedisDriver) Exists(sid string) bool { - n, err := r.client.Exists(defaultContext, sid).Result() + n, err := r.Client.Exists(defaultContext, sid).Result() if err != nil { return false } @@ -157,7 +171,7 @@ func (r *GoRedisDriver) Exists(sid string) bool { // TTL returns any TTL value of the session. func (r *GoRedisDriver) TTL(sid string) time.Duration { - dur, err := r.client.TTL(defaultContext, sid).Result() + dur, err := r.Client.TTL(defaultContext, sid).Result() if err != nil { return 0 } @@ -167,29 +181,29 @@ func (r *GoRedisDriver) TTL(sid string) time.Duration { // UpdateTTL sets expiration duration of the session. func (r *GoRedisDriver) UpdateTTL(sid string, newLifetime time.Duration) error { - _, err := r.client.Expire(defaultContext, sid, newLifetime).Result() + _, err := r.Client.Expire(defaultContext, sid, newLifetime).Result() return err } // GetAll returns all the key values under the session. func (r *GoRedisDriver) GetAll(sid string) (map[string]string, error) { - return r.client.HGetAll(defaultContext, sid).Result() + return r.Client.HGetAll(defaultContext, sid).Result() } // GetKeys returns all keys under the session. func (r *GoRedisDriver) GetKeys(sid string) ([]string, error) { - return r.client.HKeys(defaultContext, sid).Result() + return r.Client.HKeys(defaultContext, sid).Result() } // Len returns the total length of key-values of the session. func (r *GoRedisDriver) Len(sid string) int { - return int(r.client.HLen(defaultContext, sid).Val()) + return int(r.Client.HLen(defaultContext, sid).Val()) } // Delete removes a value from the redis store. func (r *GoRedisDriver) Delete(sid, key string) error { if key == "" { - return r.client.Del(defaultContext, sid).Err() + return r.Client.Del(defaultContext, sid).Err() } - return r.client.HDel(defaultContext, sid, key).Err() + return r.Client.HDel(defaultContext, sid, key).Err() } From 0d86a9628dc0464d0376208d4ca14d7e678f92b9 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 15 Aug 2022 01:23:41 +0300 Subject: [PATCH 09/11] go1.19: core/errgroup minor fix --- core/errgroup/errgroup.go | 2 +- core/errgroup/errgroup_test.go | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/errgroup/errgroup.go b/core/errgroup/errgroup.go index c22d447a..ba8c4dc0 100644 --- a/core/errgroup/errgroup.go +++ b/core/errgroup/errgroup.go @@ -147,7 +147,7 @@ func (e *Error) As(target interface{}) bool { } } - return errors.As(e.Err, &te.Err) + return errors.As(te.Err, &e) } return ok diff --git a/core/errgroup/errgroup_test.go b/core/errgroup/errgroup_test.go index f01fbfff..bb82a798 100644 --- a/core/errgroup/errgroup_test.go +++ b/core/errgroup/errgroup_test.go @@ -32,13 +32,22 @@ func TestErrorIs(t *testing.T) { } } +// errorString is a trivial implementation of error. +type errorString struct { + s string +} + +func (e *errorString) Error() string { + return e.s +} + func TestErrorAs(t *testing.T) { - testErr := errors.New("as") + testErr := &errorString{"as"} err := &Error{Err: testErr} if expected, got := true, errors.As(err, &testErr); expected != got { t.Fatalf("[testErr as err] expected %v but got %v", expected, got) } - if expected, got := true, errors.As(testErr, &err); expected != got { + if expected, got := false, errors.As(testErr, &err); expected != got /* errorString does not implemeny As, so the std/default functionality will be applied */ { t.Fatalf("[err as testErr] expected %v but got %v", expected, got) } } From 7bd47bf446c5c61aad806ee9c492264bb3854940 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Mon, 15 Aug 2022 01:36:22 +0300 Subject: [PATCH 10/11] README: update donators :heart: --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 1fb740dd..1f1fc2b2 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,7 @@ With your help, we can improve Open Source web development for everyone! lexrus li3p se77en + simpleittools sumjoe vincent-li sascha11110 @@ -337,6 +338,7 @@ With your help, we can improve Open Source web development for everyone! edwindna2 fenriz07 ffelipelimao + geGao123 gnosthi goten002 guanzi008 @@ -368,6 +370,7 @@ With your help, we can improve Open Source web development for everyone! ozfive paulxu21 pitt134 + qiepeipei qiuzhanghua rapita relaera @@ -380,6 +383,7 @@ With your help, we can improve Open Source web development for everyone! sbenimeli sebyno seun-otosho + su1gen svirmi unixedia vguhesan @@ -393,6 +397,7 @@ With your help, we can improve Open Source web development for everyone! mdamschen mtrense netbaalzovf + oliverjosefzimmer lfaynman ArturWierzbicki NA From 3c474097c64df7bf91a1576c04e51603d8e6a4e9 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 27 Aug 2022 00:22:42 +0300 Subject: [PATCH 11/11] https://github.com/kataras/iris/issues/1945#issuecomment-1226678256 --- context/context.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/context/context.go b/context/context.go index 08f56f71..2882ae3b 100644 --- a/context/context.go +++ b/context/context.go @@ -1012,6 +1012,10 @@ var GetDomain = func(hostport string) string { // loopback. return "localhost" default: + if net.ParseIP(host) != nil { // if it's an IP, see #1945. + return host + } + if domain, err := publicsuffix.EffectiveTLDPlusOne(host); err == nil { host = domain }