From f81689dfb1771a67a6056051f4b0fe46ae66f617 Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Sat, 30 Jul 2022 16:11:51 +0800 Subject: [PATCH 1/2] Release v2.0.5 (#5033) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: generic cache random time offset expired. * bugfix: Csrf token should be Secure and httpOnly, but not now * fix: expose the Offset property to allow external modifications * improving the concurrency performance of random value calculation * add WithOffsetFunc to define private RandomExpireCache.offset field * fix: add seconds definition * build(deps): bump github.com/stretchr/testify from 1.7.1 to 1.8.0 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.1 to 1.8.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.7.1...v1.8.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix 4907: force admin service http only * Feat: add get all tasks function (#4999) * feat: add get all tasks function * Refine Comments : admin/profile.go,bean/mock.go,config/global.go... (#5009) * Refine Comments * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * refine comments for for four files (#5011) * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * Update db.go * fix pass []any as any in variadic function by asasalint (#5012) * fix pass []any as any in variadic function * add change log * build(deps): bump go.opentelemetry.io/otel/trace from 1.7.0 to 1.8.0 (#5019) Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/trace dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refine comments for package core (#5014) * Refine Comments * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * refine comments * refine comments * Update db.go * refine comments for core * build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace (#5018) Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix 5022: Miss assiging ln to graceful Server (#5028) * prepare for releasing v2.0.5 (#5032) Co-authored-by: auual Co-authored-by: Leon Ding Co-authored-by: dada0z Co-authored-by: kevinzeng Co-authored-by: Kevin Tsang <39397413+ktalg@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 日暮颂歌1991 <448081525@qq.com> Co-authored-by: Regan Yue <1131625869@qq.com> Co-authored-by: alingse --- CHANGELOG.md | 12 +++ adapter/app.go | 2 +- adapter/cache/cache.go | 16 ++-- adapter/context/context.go | 4 +- adapter/context/output.go | 2 +- adapter/doc.go | 2 +- adapter/logs/log.go | 2 +- adapter/orm/db_alias.go | 2 +- adapter/orm/orm.go | 35 ++++---- adapter/orm/orm_log.go | 2 +- adapter/orm/types.go | 32 ++++---- adapter/orm/utils.go | 8 +- adapter/router.go | 2 +- client/cache/cache.go | 12 +-- client/cache/random_expired_cache.go | 75 +++++++++++++++++ client/cache/random_expired_cache_test.go | 99 +++++++++++++++++++++++ client/httplib/client_option.go | 4 +- client/orm/db.go | 44 +++++----- client/orm/mock/mock_orm.go | 2 +- core/admin/profile.go | 2 +- core/bean/doc.go | 2 +- core/bean/mock.go | 2 +- core/berror/error.go | 2 +- core/config/config.go | 10 +-- core/config/global.go | 10 +-- core/config/toml/toml.go | 5 +- core/utils/time.go | 2 +- go.mod | 12 +-- go.sum | 28 +++---- server/web/admin.go | 4 +- server/web/context/context.go | 2 +- server/web/grace/server.go | 1 + task/task.go | 23 +++++- task/task_test.go | 21 +++++ 34 files changed, 356 insertions(+), 127 deletions(-) create mode 100644 client/cache/random_expired_cache.go create mode 100644 client/cache/random_expired_cache_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c4b9949..f25b7dd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,16 @@ # developing + +# v2.0.5 + +Note: now we force the web admin service serving HTTP only. + +- [Fix 4984: random expire cache](https://github.com/beego/beego/pull/4984) +- [Fix 4907: make admin serve HTTP only](https://github.com/beego/beego/pull/5005) +- [Feat 4999: add get all tasks function](https://github.com/beego/beego/pull/4999) +- [Fix 5012: fix some bug, pass []any as any in variadic function](https://github.com/beego/beego/pull/5012) +- [Fix 5022: Miss assigning listener to graceful Server](https://github.com/beego/beego/pull/5028) + + # v2.0.4 Note: now we force the web admin service serving HTTP only. diff --git a/adapter/app.go b/adapter/app.go index 35570616..aaf85a17 100644 --- a/adapter/app.go +++ b/adapter/app.go @@ -245,7 +245,7 @@ func Any(rootpath string, f FilterFunc) *App { // fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) // })) func Handler(rootpath string, h http.Handler, options ...interface{}) *App { - return (*App)(web.Handler(rootpath, h, options)) + return (*App)(web.Handler(rootpath, h, options...)) } // InsertFilter adds a FilterFunc with pattern condition and action constant. diff --git a/adapter/cache/cache.go b/adapter/cache/cache.go index 0465e4c1..bad35cfe 100644 --- a/adapter/cache/cache.go +++ b/adapter/cache/cache.go @@ -47,23 +47,23 @@ import ( // c.Incr("counter") // now is 2 // count := c.Get("counter").(int) type Cache interface { - // get cached value by key. + // Get will get cached value by key. Get(key string) interface{} // GetMulti is a batch version of Get. GetMulti(keys []string) []interface{} - // set cached value with key and expire time. + // Put will set cached value with key and expire time. Put(key string, val interface{}, timeout time.Duration) error - // delete cached value by key. + // Delete will delete cached value by key. Delete(key string) error - // increase cached int value by key, as a counter. + // Incr will increase cached int value by key, as a counter. Incr(key string) error - // decrease cached int value by key, as a counter. + // Decr will decrease cached int value by key, as a counter. Decr(key string) error - // check if cached value exists or not. + // IsExist can check if cached value exists or not. IsExist(key string) bool - // clear all cache. + // ClearAll will clear all cache. ClearAll() error - // start gc routine based on config string settings. + // StartAndGC will start gc routine based on config string settings. StartAndGC(config string) error } diff --git a/adapter/context/context.go b/adapter/context/context.go index c0259139..77a0aa05 100644 --- a/adapter/context/context.go +++ b/adapter/context/context.go @@ -78,7 +78,7 @@ func (ctx *Context) GetCookie(key string) string { // SetCookie Set cookie for response. // It's alias of BeegoOutput.Cookie. func (ctx *Context) SetCookie(name string, value string, others ...interface{}) { - (*context.Context)(ctx).SetCookie(name, value, others) + (*context.Context)(ctx).SetCookie(name, value, others...) } // GetSecureCookie Get secure cookie from request by a given key. @@ -88,7 +88,7 @@ func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) { // SetSecureCookie Set Secure cookie for response. func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) { - (*context.Context)(ctx).SetSecureCookie(Secret, name, value, others) + (*context.Context)(ctx).SetSecureCookie(Secret, name, value, others...) } // XSRFToken creates a xsrf token string and returns. diff --git a/adapter/context/output.go b/adapter/context/output.go index 5152ccf5..46edd343 100644 --- a/adapter/context/output.go +++ b/adapter/context/output.go @@ -47,7 +47,7 @@ func (output *BeegoOutput) Body(content []byte) error { // Cookie sets cookie value via given key. // others are ordered as cookie's max age time, path,domain, secure and httponly. func (output *BeegoOutput) Cookie(name string, value string, others ...interface{}) { - (*context.BeegoOutput)(output).Cookie(name, value, others) + (*context.BeegoOutput)(output).Cookie(name, value, others...) } // JSON writes json to response body. diff --git a/adapter/doc.go b/adapter/doc.go index c8f2174c..ef4bdffd 100644 --- a/adapter/doc.go +++ b/adapter/doc.go @@ -12,5 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// used to keep compatible with v1.x +// Package adapter used to keep compatible with v1.x package adapter diff --git a/adapter/logs/log.go b/adapter/logs/log.go index fc0fdc62..3cedfdde 100644 --- a/adapter/logs/log.go +++ b/adapter/logs/log.go @@ -158,7 +158,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { (*logs.BeeLogger)(bl).EnableFuncCallDepth(b) } -// set prefix +// SetPrefix will set prefix func (bl *BeeLogger) SetPrefix(s string) { (*logs.BeeLogger)(bl).SetPrefix(s) } diff --git a/adapter/orm/db_alias.go b/adapter/orm/db_alias.go index f910c3f9..a196ca23 100644 --- a/adapter/orm/db_alias.go +++ b/adapter/orm/db_alias.go @@ -69,7 +69,7 @@ func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{} } func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { - return (*orm.DB)(d).QueryRow(query, args) + return (*orm.DB)(d).QueryRow(query, args...) } func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { diff --git a/adapter/orm/orm.go b/adapter/orm/orm.go index fd3c3d25..0ebe478e 100644 --- a/adapter/orm/orm.go +++ b/adapter/orm/orm.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build go1.8 // +build go1.8 // Package orm provide ORM for MySQL/PostgreSQL/sqlite @@ -92,7 +93,7 @@ type ormer struct { var _ Ormer = new(ormer) -// read data to model +// Read read data to model func (o *ormer) Read(md interface{}, cols ...string) error { if o.isTx { return o.txDelegate.Read(md, cols...) @@ -100,7 +101,7 @@ func (o *ormer) Read(md interface{}, cols ...string) error { return o.delegate.Read(md, cols...) } -// read data to model, like Read(), but use "SELECT FOR UPDATE" form +// ReadForUpdate read data to model, like Read(), but use "SELECT FOR UPDATE" form func (o *ormer) ReadForUpdate(md interface{}, cols ...string) error { if o.isTx { return o.txDelegate.ReadForUpdate(md, cols...) @@ -108,7 +109,7 @@ func (o *ormer) ReadForUpdate(md interface{}, cols ...string) error { return o.delegate.ReadForUpdate(md, cols...) } -// Try to read a row from the database, or insert one if it doesn't exist +// ReadOrCreate Try to read a row from the database, or insert one if it doesn't exist func (o *ormer) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) { if o.isTx { return o.txDelegate.ReadOrCreate(md, col1, cols...) @@ -116,7 +117,7 @@ func (o *ormer) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, return o.delegate.ReadOrCreate(md, col1, cols...) } -// insert model data to database +// Insert will insert model data to database func (o *ormer) Insert(md interface{}) (int64, error) { if o.isTx { return o.txDelegate.Insert(md) @@ -124,7 +125,7 @@ func (o *ormer) Insert(md interface{}) (int64, error) { return o.delegate.Insert(md) } -// insert some models to database +// InsertMulti will insert some models to database func (o *ormer) InsertMulti(bulk int, mds interface{}) (int64, error) { if o.isTx { return o.txDelegate.InsertMulti(bulk, mds) @@ -140,7 +141,7 @@ func (o *ormer) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int return o.delegate.InsertOrUpdate(md, colConflitAndArgs...) } -// update model to database. +// Update will update model to database. // cols set the columns those want to update. func (o *ormer) Update(md interface{}, cols ...string) (int64, error) { if o.isTx { @@ -149,7 +150,7 @@ func (o *ormer) Update(md interface{}, cols ...string) (int64, error) { return o.delegate.Update(md, cols...) } -// delete model in database +// Delete delete model in database // cols shows the delete conditions values read from. default is pk func (o *ormer) Delete(md interface{}, cols ...string) (int64, error) { if o.isTx { @@ -158,7 +159,7 @@ func (o *ormer) Delete(md interface{}, cols ...string) (int64, error) { return o.delegate.Delete(md, cols...) } -// create a models to models queryer +// QueryM2M create a models to models queryer func (o *ormer) QueryM2M(md interface{}, name string) QueryM2Mer { if o.isTx { return o.txDelegate.QueryM2M(md, name) @@ -166,7 +167,7 @@ func (o *ormer) QueryM2M(md interface{}, name string) QueryM2Mer { return o.delegate.QueryM2M(md, name) } -// load related models to md model. +// LoadRelated load related models to md model. // args are limit, offset int and order string. // // example: @@ -200,7 +201,7 @@ func (o *ormer) LoadRelated(md interface{}, name string, args ...interface{}) (i return o.delegate.LoadRelated(md, name, kvs...) } -// return a QuerySeter for table operations. +// QueryTable return a QuerySeter for table operations. // table name can be string or struct. // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), func (o *ormer) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { @@ -210,7 +211,7 @@ func (o *ormer) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { return o.delegate.QueryTable(ptrStructOrTableName) } -// switch to another registered database driver by given name. +// Using switch to another registered database driver by given name. func (o *ormer) Using(name string) error { if o.isTx { return ErrTxHasBegan @@ -219,7 +220,7 @@ func (o *ormer) Using(name string) error { return nil } -// begin transaction +// Begin will begin transaction func (o *ormer) Begin() error { if o.isTx { return ErrTxHasBegan @@ -240,7 +241,7 @@ func (o *ormer) BeginTx(ctx context.Context, opts *sql.TxOptions) error { return nil } -// commit transaction +// Commit will commit transaction func (o *ormer) Commit() error { if !o.isTx { return ErrTxDone @@ -255,7 +256,7 @@ func (o *ormer) Commit() error { return err } -// rollback transaction +// Rollback will rollback transaction func (o *ormer) Rollback() error { if !o.isTx { return ErrTxDone @@ -270,7 +271,7 @@ func (o *ormer) Rollback() error { return err } -// return a raw query seter for raw sql string. +// Raw return a raw query seter for raw sql string. func (o *ormer) Raw(query string, args ...interface{}) RawSeter { if o.isTx { return o.txDelegate.Raw(query, args...) @@ -278,7 +279,7 @@ func (o *ormer) Raw(query string, args ...interface{}) RawSeter { return o.delegate.Raw(query, args...) } -// return current using database Driver +// Driver return current using database Driver func (o *ormer) Driver() Driver { if o.isTx { return o.txDelegate.Driver() @@ -286,7 +287,7 @@ func (o *ormer) Driver() Driver { return o.delegate.Driver() } -// return sql.DBStats for current database +// DBStats return sql.DBStats for current database func (o *ormer) DBStats() *sql.DBStats { if o.isTx { return o.txDelegate.DBStats() diff --git a/adapter/orm/orm_log.go b/adapter/orm/orm_log.go index 98c1522e..1faab4ba 100644 --- a/adapter/orm/orm_log.go +++ b/adapter/orm/orm_log.go @@ -23,7 +23,7 @@ import ( // Log implement the log.Logger type Log orm.Log -// costomer log func +// LogFunc is costomer log func var LogFunc = orm.LogFunc // NewLog set io.Writer to create a Logger. diff --git a/adapter/orm/types.go b/adapter/orm/types.go index 428f8b14..ecc4d6f4 100644 --- a/adapter/orm/types.go +++ b/adapter/orm/types.go @@ -35,7 +35,7 @@ type Fielder orm.Fielder // Ormer define the orm interface type Ormer interface { - // read data to model + // Read read data to model // for example: // this will find User by Id field // u = &User{Id: user.Id} @@ -44,25 +44,25 @@ type Ormer interface { // u = &User{UserName: "astaxie", Password: "pass"} // err = Ormer.Read(u, "UserName") Read(md interface{}, cols ...string) error - // Like Read(), but with "FOR UPDATE" clause, useful in transaction. + // ReadForUpdate Like Read(), but with "FOR UPDATE" clause, useful in transaction. // Some databases are not support this feature. ReadForUpdate(md interface{}, cols ...string) error - // Try to read a row from the database, or insert one if it doesn't exist + // ReadOrCreate Try to read a row from the database, or insert one if it doesn't exist ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) - // insert model data to database + // Insert will insert model data to database // for example: // user := new(User) // id, err = Ormer.Insert(user) // user must be a pointer and Insert will set user's pk field Insert(interface{}) (int64, error) - // mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value") + // InsertOrUpdate(model,"colu=colu+value") or mysql:InsertOrUpdate(model) // if colu type is integer : can use(+-*/), string : convert(colu,"value") // postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value") // if colu type is integer : can use(+-*/), string : colu || "value" InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) - // insert some models to database + // InsertMulti insert some models to database InsertMulti(bulk int, mds interface{}) (int64, error) - // update model to database. + // Update update model to database. // cols set the columns those want to update. // find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns // for example: @@ -72,9 +72,9 @@ type Ormer interface { // user.Extra.Data = "orm" // num, err = Ormer.Update(&user, "Langs", "Extra") Update(md interface{}, cols ...string) (int64, error) - // delete model in database + // Delete delete model in database Delete(md interface{}, cols ...string) (int64, error) - // load related models to md model. + // LoadRelated load related models to md model. // args are limit, offset int and order string. // // example: @@ -87,25 +87,25 @@ type Ormer interface { // args[3] string order for example : "-Id" // make sure the relation is defined in model struct tags. LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) - // create a models to models queryer + // QueryM2M create a models to models queryer // for example: // post := Post{Id: 4} // m2m := Ormer.QueryM2M(&post, "Tags") QueryM2M(md interface{}, name string) QueryM2Mer - // return a QuerySeter for table operations. + // QueryTable return a QuerySeter for table operations. // table name can be string or struct. // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), QueryTable(ptrStructOrTableName interface{}) QuerySeter // switch to another registered database driver by given name. Using(name string) error - // begin transaction + // Begin begin transaction // for example: // o := NewOrm() // err := o.Begin() // ... // err = o.Rollback() Begin() error - // begin transaction with provided context and option + // BeginTx begin transaction with provided context and option // the provided context is used until the transaction is committed or rolled back. // if the context is canceled, the transaction will be rolled back. // the provided TxOptions is optional and may be nil if defaults should be used. @@ -116,11 +116,11 @@ type Ormer interface { // ... // err = o.Rollback() BeginTx(ctx context.Context, opts *sql.TxOptions) error - // commit transaction + // Commit commit transaction Commit() error - // rollback transaction + // Rollback rollback transaction Rollback() error - // return a raw query seter for raw sql string. + // Raw return a raw query seter for raw sql string. // for example: // ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec() // // update user testing's name to slene diff --git a/adapter/orm/utils.go b/adapter/orm/utils.go index cd54f867..a88836c3 100644 --- a/adapter/orm/utils.go +++ b/adapter/orm/utils.go @@ -246,7 +246,7 @@ func camelString(s string) string { type argString []string -// get string by index from string slice +// Get will get string by index from string slice func (a argString) Get(i int, args ...string) (r string) { if i >= 0 && i < len(a) { r = a[i] @@ -258,7 +258,7 @@ func (a argString) Get(i int, args ...string) (r string) { type argInt []int -// get int by index from int slice +// Get will get int by index from int slice func (a argInt) Get(i int, args ...int) (r int) { if i >= 0 && i < len(a) { r = a[i] @@ -269,13 +269,13 @@ func (a argInt) Get(i int, args ...int) (r int) { return } -// parse time to string with location +// timeParse parse time to string with location func timeParse(dateString, format string) (time.Time, error) { tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) return tp, err } -// get pointer indirect type +// indirectType get pointer indirect type func indirectType(v reflect.Type) reflect.Type { switch v.Kind() { case reflect.Ptr: diff --git a/adapter/router.go b/adapter/router.go index a0add1fe..23f08e1e 100644 --- a/adapter/router.go +++ b/adapter/router.go @@ -212,7 +212,7 @@ func (p *ControllerRegister) AddMethod(method, pattern string, f FilterFunc) { // Handler add user defined Handler func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...interface{}) { - (*web.ControllerRegister)(p).Handler(pattern, h, options) + (*web.ControllerRegister)(p).Handler(pattern, h, options...) } // AddAuto router to ControllerRegister. diff --git a/client/cache/cache.go b/client/cache/cache.go index 2f9dd9bd..1eafccdc 100644 --- a/client/cache/cache.go +++ b/client/cache/cache.go @@ -53,21 +53,21 @@ type Cache interface { Get(ctx context.Context, key string) (interface{}, error) // GetMulti is a batch version of Get. GetMulti(ctx context.Context, keys []string) ([]interface{}, error) - // Set a cached value with key and expire time. + // Put Set a cached value with key and expire time. Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error // Delete cached value by key. // Should not return error if key not found Delete(ctx context.Context, key string) error - // Increment a cached int value by key, as a counter. + // Incr Increment a cached int value by key, as a counter. Incr(ctx context.Context, key string) error - // Decrement a cached int value by key, as a counter. + // Decr Decrement a cached int value by key, as a counter. Decr(ctx context.Context, key string) error - // Check if a cached value exists or not. + // IsExist Check if a cached value exists or not. // if key is expired, return (false, nil) IsExist(ctx context.Context, key string) (bool, error) - // Clear all cache. + // ClearAll Clear all cache. ClearAll(ctx context.Context) error - // Start gc routine based on config string settings. + // StartAndGC Start gc routine based on config string settings. StartAndGC(config string) error } diff --git a/client/cache/random_expired_cache.go b/client/cache/random_expired_cache.go new file mode 100644 index 00000000..26200112 --- /dev/null +++ b/client/cache/random_expired_cache.go @@ -0,0 +1,75 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cache + +import ( + "context" + "math/rand" + "sync/atomic" + "time" +) + +// RandomExpireCacheOption implement genreate random time offset expired option +type RandomExpireCacheOption func(*RandomExpireCache) + +// WithOffsetFunc returns a RandomExpireCacheOption that configures the offset function +func WithOffsetFunc(fn func() time.Duration) RandomExpireCacheOption { + return func(cache *RandomExpireCache) { + cache.offset = fn + } +} + +// RandomExpireCache prevent cache batch invalidation +// Cache random time offset expired +type RandomExpireCache struct { + Cache + offset func() time.Duration +} + +// Put random time offset expired +func (rec *RandomExpireCache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { + timeout += rec.offset() + return rec.Cache.Put(ctx, key, val, timeout) +} + +// NewRandomExpireCache return random expire cache struct +func NewRandomExpireCache(adapter Cache, opts ...RandomExpireCacheOption) Cache { + rec := RandomExpireCache{ + Cache: adapter, + offset: defaultExpiredFunc(), + } + for _, fn := range opts { + fn(&rec) + } + return &rec +} + +// defaultExpiredFunc return a func that used to generate random time offset (range: [3s,8s)) expired +func defaultExpiredFunc() func() time.Duration { + const size = 5 + var randTimes [size]time.Duration + for i := range randTimes { + randTimes[i] = time.Duration(i+3) * time.Second + } + // shuffle values + for i := range randTimes { + n := rand.Intn(size) + randTimes[i], randTimes[n] = randTimes[n], randTimes[i] + } + var i uint64 + return func() time.Duration { + return randTimes[atomic.AddUint64(&i, 1)%size] + } +} diff --git a/client/cache/random_expired_cache_test.go b/client/cache/random_expired_cache_test.go new file mode 100644 index 00000000..1e3bb935 --- /dev/null +++ b/client/cache/random_expired_cache_test.go @@ -0,0 +1,99 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cache + +import ( + "context" + "math/rand" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestRandomExpireCache(t *testing.T) { + bm, err := NewCache("memory", `{"interval":20}`) + assert.Nil(t, err) + + cache := NewRandomExpireCache(bm) + // should not be nil + assert.NotNil(t, cache.(*RandomExpireCache).offset) + + timeoutDuration := 3 * time.Second + + if err = cache.Put(context.Background(), "Leon Ding", 22, timeoutDuration); err != nil { + t.Error("set Error", err) + } + + // testing random expire cache + time.Sleep(timeoutDuration + 3 + time.Second) + + if res, _ := cache.IsExist(context.Background(), "Leon Ding"); !res { + t.Error("check err") + } + + if v, _ := cache.Get(context.Background(), "Leon Ding"); v.(int) != 22 { + t.Error("get err") + } + + cache.Delete(context.Background(), "Leon Ding") + res, _ := cache.IsExist(context.Background(), "Leon Ding") + assert.False(t, res) + + assert.Nil(t, cache.Put(context.Background(), "Leon Ding", "author", timeoutDuration)) + + cache.Delete(context.Background(), "astaxie") + res, _ = cache.IsExist(context.Background(), "astaxie") + assert.False(t, res) + + assert.Nil(t, cache.Put(context.Background(), "astaxie", "author", timeoutDuration)) + + res, _ = cache.IsExist(context.Background(), "astaxie") + assert.True(t, res) + + v, _ := cache.Get(context.Background(), "astaxie") + assert.Equal(t, "author", v) + + assert.Nil(t, cache.Put(context.Background(), "astaxie1", "author1", timeoutDuration)) + + res, _ = cache.IsExist(context.Background(), "astaxie1") + assert.True(t, res) + + vv, _ := cache.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) + assert.Equal(t, 2, len(vv)) + assert.Equal(t, "author", vv[0]) + assert.Equal(t, "author1", vv[1]) + + vv, err = cache.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"}) + assert.Equal(t, 2, len(vv)) + assert.Nil(t, vv[0]) + assert.Equal(t, "author1", vv[1]) + + assert.NotNil(t, err) + assert.True(t, strings.Contains(err.Error(), "key isn't exist")) +} + +func TestWithOffsetFunc(t *testing.T) { + bm, err := NewCache("memory", `{"interval":20}`) + assert.Nil(t, err) + + magic := -time.Duration(rand.Int()) + cache := NewRandomExpireCache(bm, WithOffsetFunc(func() time.Duration { + return magic + })) + // offset should return the magic value + assert.Equal(t, magic, cache.(*RandomExpireCache).offset()) +} diff --git a/client/httplib/client_option.go b/client/httplib/client_option.go index f970e67d..2b8b672c 100644 --- a/client/httplib/client_option.go +++ b/client/httplib/client_option.go @@ -33,7 +33,7 @@ func WithEnableCookie(enable bool) ClientOption { } } -// WithEnableCookie will adds UA in all subsequent request +// WithUserAgent will adds UA in all subsequent request func WithUserAgent(userAgent string) ClientOption { return func(client *Client) { client.Setting.UserAgent = userAgent @@ -105,7 +105,7 @@ func WithCookie(cookie *http.Cookie) BeegoHTTPRequestOption { } } -// Withtokenfactory adds a custom function to set Authorization +// WithTokenFactory adds a custom function to set Authorization func WithTokenFactory(tokenFactory func() string) BeegoHTTPRequestOption { return func(request *BeegoHTTPRequest) { t := tokenFactory() diff --git a/client/orm/db.go b/client/orm/db.go index 5da43d0a..08047a04 100644 --- a/client/orm/db.go +++ b/client/orm/db.go @@ -264,7 +264,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val return value, nil } -// create insert sql preparation statement object. +// PrepareInsert create insert sql preparation statement object. func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) { Q := d.ins.TableQuote() @@ -290,7 +290,7 @@ func (d *dbBase) PrepareInsert(ctx context.Context, q dbQuerier, mi *modelInfo) return stmt, query, err } -// insert struct with prepared statement and given struct reflect value. +// InsertStmt insert struct with prepared statement and given struct reflect value. func (d *dbBase) InsertStmt(ctx context.Context, stmt stmtQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { values, _, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, nil, tz) if err != nil { @@ -371,7 +371,7 @@ func (d *dbBase) Read(ctx context.Context, q dbQuerier, mi *modelInfo, ind refle return nil } -// execute insert sql dbQuerier with given struct reflect.Value. +// Insert execute insert sql dbQuerier with given struct reflect.Value. func (d *dbBase) Insert(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { names := make([]string, 0, len(mi.fields.dbcols)) values, autoFields, err := d.collectValues(mi, ind, mi.fields.dbcols, false, true, &names, tz) @@ -390,7 +390,7 @@ func (d *dbBase) Insert(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref return id, err } -// multi-insert sql with given slice struct reflect.Value. +// InsertMulti multi-insert sql with given slice struct reflect.Value. func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *modelInfo, sind reflect.Value, bulk int, tz *time.Location) (int64, error) { var ( cnt int64 @@ -454,7 +454,7 @@ func (d *dbBase) InsertMulti(ctx context.Context, q dbQuerier, mi *modelInfo, si return cnt, err } -// execute insert sql with given struct and given values. +// InsertValue execute insert sql with given struct and given values. // insert the given values, not the field values in struct. func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { Q := d.ins.TableQuote() @@ -612,7 +612,7 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *modelInfo, return id, err } -// execute update sql dbQuerier with given struct reflect.Value. +// Update execute update sql dbQuerier with given struct reflect.Value. func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { pkName, pkValue, ok := getExistPk(mi, ind) if !ok { @@ -677,7 +677,7 @@ func (d *dbBase) Update(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref return 0, err } -// execute delete sql dbQuerier with given struct reflect.Value. +// Delete execute delete sql dbQuerier with given struct reflect.Value. // delete index is pk. func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { var whereCols []string @@ -725,7 +725,7 @@ func (d *dbBase) Delete(ctx context.Context, q dbQuerier, mi *modelInfo, ind ref return 0, err } -// update table-related record by querySet. +// UpdateBatch update table-related record by querySet. // need querySet not struct reflect.Value to update related records. func (d *dbBase) UpdateBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) { columns := make([]string, 0, len(params)) @@ -843,7 +843,7 @@ func (d *dbBase) deleteRels(ctx context.Context, q dbQuerier, mi *modelInfo, arg return nil } -// delete table-related records. +// DeleteBatch delete table-related records. func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (int64, error) { tables := newDbTables(mi, d.ins) tables.skipEnd = true @@ -920,7 +920,7 @@ func (d *dbBase) DeleteBatch(ctx context.Context, q dbQuerier, qs *querySet, mi return 0, err } -// read related records. +// ReadBatch read related records. func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}, tz *time.Location, cols []string) (int64, error) { val := reflect.ValueOf(container) ind := reflect.Indirect(val) @@ -1145,7 +1145,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m return cnt, nil } -// excute count sql and return count result int64. +// Count excute count sql and return count result int64. func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) { tables := newDbTables(mi, d.ins) tables.parseRelated(qs.related, qs.relDepth) @@ -1173,7 +1173,7 @@ func (d *dbBase) Count(ctx context.Context, q dbQuerier, qs *querySet, mi *model return } -// generate sql with replacing operator string placeholders and replaced values. +// GenerateOperatorSQL generate sql with replacing operator string placeholders and replaced values. func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { var sql string params := getFlatParams(fi, args, tz) @@ -1233,7 +1233,7 @@ func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator stri return sql, params } -// gernerate sql string with inner function, such as UPPER(text). +// GenerateOperatorLeftCol gernerate sql string with inner function, such as UPPER(text). func (d *dbBase) GenerateOperatorLeftCol(*fieldInfo, string, *string) { // default not use } @@ -1615,7 +1615,7 @@ setValue: return value, nil } -// query sql, read values , save to *[]ParamList. +// ReadValues query sql, read values , save to *[]ParamList. func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) { var ( maps []Params @@ -1788,7 +1788,7 @@ func (d *dbBase) ReadValues(ctx context.Context, q dbQuerier, qs *querySet, mi * return cnt, nil } -// flag of update joined record. +// SupportUpdateJoin flag of update joined record. func (d *dbBase) SupportUpdateJoin() bool { return true } @@ -1797,12 +1797,12 @@ func (d *dbBase) MaxLimit() uint64 { return 18446744073709551615 } -// return quote. +// TableQuote return quote. func (d *dbBase) TableQuote() string { return "`" } -// replace value placeholder in parametered sql string. +// ReplaceMarks replace value placeholder in parametered sql string. func (d *dbBase) ReplaceMarks(query *string) { // default use `?` as mark, do nothing } @@ -1817,22 +1817,22 @@ func (d *dbBase) setval(ctx context.Context, db dbQuerier, mi *modelInfo, autoFi return nil } -// convert time from db. +// TimeFromDB convert time from db. func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) { *t = t.In(tz) } -// convert time to db. +// TimeToDB convert time to db. func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) { *t = t.In(tz) } -// get database types. +// DbTypes get database types. func (d *dbBase) DbTypes() map[string]string { return nil } -// gt all tables. +// GetTables gt all tables. func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { tables := make(map[string]bool) query := d.ins.ShowTablesQuery() @@ -1857,7 +1857,7 @@ func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { return tables, nil } -// get all cloumns in table. +// GetColumns get all cloumns in table. func (d *dbBase) GetColumns(ctx context.Context, db dbQuerier, table string) (map[string][3]string, error) { columns := make(map[string][3]string) query := d.ins.ShowColumnsQuery(table) diff --git a/client/orm/mock/mock_orm.go b/client/orm/mock/mock_orm.go index 70bee4f7..ce6712a4 100644 --- a/client/orm/mock/mock_orm.go +++ b/client/orm/mock/mock_orm.go @@ -45,7 +45,7 @@ func MockMethod(method string, resp ...interface{}) *Mock { return NewMock(NewSimpleCondition("", method), resp, nil) } -// MockOrmRead support orm.Read and orm.ReadWithCtx +// MockRead support orm.Read and orm.ReadWithCtx // cb is used to mock read data from DB func MockRead(tableName string, cb func(data interface{}), err error) *Mock { return NewMock(NewSimpleCondition(tableName, "ReadWithCtx"), []interface{}{err}, func(inv *orm.Invocation) { diff --git a/core/admin/profile.go b/core/admin/profile.go index bd9eff4d..f85afaa2 100644 --- a/core/admin/profile.go +++ b/core/admin/profile.go @@ -144,7 +144,7 @@ func avg(items []time.Duration) time.Duration { return time.Duration(int64(sum) / int64(len(items))) } -// format bytes number friendly +// toH format bytes number friendly func toH(bytes uint64) string { switch { case bytes < 1024: diff --git a/core/bean/doc.go b/core/bean/doc.go index f806a081..049fe563 100644 --- a/core/bean/doc.go +++ b/core/bean/doc.go @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// bean is a basic package +// Package bean is a basic package // it should not depend on other modules except common module, log module and config module package bean diff --git a/core/bean/mock.go b/core/bean/mock.go index 0a8d3e29..86d90c74 100644 --- a/core/bean/mock.go +++ b/core/bean/mock.go @@ -7,7 +7,7 @@ import ( "strings" ) -// the mock object must be pointer of struct +// Mock have a mock object ,it must be pointer of struct // the element in mock object can be slices, structures, basic data types, pointers and interface func Mock(v interface{}) (err error) { pv := reflect.ValueOf(v) diff --git a/core/berror/error.go b/core/berror/error.go index ca09798a..c40009c6 100644 --- a/core/berror/error.go +++ b/core/berror/error.go @@ -25,7 +25,7 @@ import ( // code, msg const errFmt = "ERROR-%d, %s" -// Err returns an error representing c and msg. If c is OK, returns nil. +// Error returns an error representing c and msg. If c is OK, returns nil. func Error(c Code, msg string) error { return fmt.Errorf(errFmt, c.Code(), msg) } diff --git a/core/config/config.go b/core/config/config.go index 95a4eb26..9e84f059 100644 --- a/core/config/config.go +++ b/core/config/config.go @@ -53,20 +53,20 @@ import ( // Configer defines how to get and set value from configuration raw data. type Configer interface { - // support section::key type in given key when using ini type. + // Set support section::key type in given key when using ini type. Set(key, val string) error - // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. + // String support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. String(key string) (string, error) - // get string slice + // Strings get string slice Strings(key string) ([]string, error) Int(key string) (int, error) Int64(key string) (int64, error) Bool(key string) (bool, error) Float(key string) (float64, error) - // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. + // DefaultString support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. DefaultString(key string, defaultVal string) string - // get string slice + // DefaultStrings get string slice DefaultStrings(key string, defaultVal []string) []string DefaultInt(key string, defaultVal int) int DefaultInt64(key string, defaultVal int64) int64 diff --git a/core/config/global.go b/core/config/global.go index 3a334cb6..6f692fce 100644 --- a/core/config/global.go +++ b/core/config/global.go @@ -28,17 +28,17 @@ func InitGlobalInstance(name string, cfg string) error { return err } -// support section::key type in given key when using ini type. +// Set support section::key type in given key when using ini type. func Set(key, val string) error { return globalInstance.Set(key, val) } -// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. +// String support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. func String(key string) (string, error) { return globalInstance.String(key) } -// get string slice +// Strings will get string slice func Strings(key string) ([]string, error) { return globalInstance.Strings(key) } @@ -59,12 +59,12 @@ func Float(key string) (float64, error) { return globalInstance.Float(key) } -// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. +// DefaultString support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. func DefaultString(key string, defaultVal string) string { return globalInstance.DefaultString(key, defaultVal) } -// get string slice +// DefaultStrings will get string slice func DefaultStrings(key string, defaultVal []string) []string { return globalInstance.DefaultStrings(key, defaultVal) } diff --git a/core/config/toml/toml.go b/core/config/toml/toml.go index 0c678164..ca4eb74e 100644 --- a/core/config/toml/toml.go +++ b/core/config/toml/toml.go @@ -19,9 +19,8 @@ import ( "os" "strings" - "github.com/pelletier/go-toml" - "github.com/beego/beego/v2/core/config" + "github.com/pelletier/go-toml" ) const keySeparator = "." @@ -135,7 +134,7 @@ func (c *configContainer) Int64(key string) (int64, error) { } } -// bool return bool value +// Bool return bool value // return error if key not found or value is invalid type func (c *configContainer) Bool(key string) (bool, error) { res, err := c.get(key) diff --git a/core/utils/time.go b/core/utils/time.go index 00d13861..2f813a05 100644 --- a/core/utils/time.go +++ b/core/utils/time.go @@ -19,7 +19,7 @@ import ( "time" ) -// short string format +// ToShortTimeFormat short string format func ToShortTimeFormat(d time.Duration) string { u := uint64(d) if u < uint64(time.Second) { diff --git a/go.mod b/go.mod index 24f443b6..6542c5cd 100644 --- a/go.mod +++ b/go.mod @@ -28,17 +28,17 @@ require ( github.com/prometheus/client_golang v1.12.1 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.8.0 go.etcd.io/etcd/client/v3 v3.5.4 - go.opentelemetry.io/otel v1.7.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 - go.opentelemetry.io/otel/sdk v1.7.0 - go.opentelemetry.io/otel/trace v1.7.0 + go.opentelemetry.io/otel v1.8.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.8.0 + go.opentelemetry.io/otel/sdk v1.8.0 + go.opentelemetry.io/otel/trace v1.8.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a google.golang.org/grpc v1.38.0 google.golang.org/protobuf v1.26.0 gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + gopkg.in/yaml.v3 v3.0.1 ) require ( diff --git a/go.sum b/go.sum index dacd50c2..d9ce81a6 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -431,13 +430,15 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112 h1:NBrpnvz0pDPf3+HXZ1C9GcJd1DTpWDLcLWZhNq6uP7o= github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -466,14 +467,14 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= -go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6VWahRvjgLUrNl7rW2hffUEPKXVEM= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0/go.mod h1:K4GDXPY6TjUiwbOh+DkKaEdCF8y+lvMoM6SeAPyfCCM= -go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= -go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= -go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= +go.opentelemetry.io/otel v1.8.0 h1:zcvBFizPbpa1q7FehvFiHbQwGzmPILebO0tyqIR5Djg= +go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.8.0 h1:FVy7BZCjoA2Nk+fHqIdoTmm554J9wTX+YcrDp+mc368= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.8.0/go.mod h1:ztncjvKpotSUQq7rlgPibGt8kZfSI3/jI8EO7JjuY2c= +go.opentelemetry.io/otel/sdk v1.8.0 h1:xwu69/fNuwbSHWe/0PGS888RmjWY181OmcXDQKu7ZQk= +go.opentelemetry.io/otel/sdk v1.8.0/go.mod h1:uPSfc+yfDH2StDM/Rm35WE8gXSNdvCg023J6HeGNO0c= +go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= +go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= @@ -631,7 +632,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= @@ -701,7 +701,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -820,8 +819,9 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/web/admin.go b/server/web/admin.go index 285f7feb..56d2906f 100644 --- a/server/web/admin.go +++ b/server/web/admin.go @@ -16,6 +16,7 @@ package web import ( "fmt" + "net" "net/http" "reflect" "time" @@ -86,7 +87,7 @@ func (admin *adminApp) Run() { " please invoke task.StartTask, or task will not be executed") addr := BConfig.Listen.AdminAddr if BConfig.Listen.AdminPort != 0 { - addr = fmt.Sprintf("%s:%d", BConfig.Listen.AdminAddr, BConfig.Listen.AdminPort) + addr = net.JoinHostPort(BConfig.Listen.AdminAddr, fmt.Sprintf("%d", BConfig.Listen.AdminPort)) } logs.Info("Admin server Running on %s", addr) admin.HttpServer.Run(addr) @@ -102,6 +103,7 @@ func registerAdmin() error { // copy config to avoid conflict adminCfg := *BConfig adminCfg.Listen.EnableHTTPS = false + adminCfg.Listen.EnableMutualHTTPS = false beeAdminApp = &adminApp{ HttpServer: NewHttpServerWithCfg(&adminCfg), } diff --git a/server/web/context/context.go b/server/web/context/context.go index e165527b..c85dc45b 100644 --- a/server/web/context/context.go +++ b/server/web/context/context.go @@ -270,7 +270,7 @@ func (ctx *Context) XSRFToken(key string, expire int64) string { if !ok { token = string(utils.RandomCreateBytes(32)) // TODO make it configurable - ctx.SetSecureCookie(key, "_xsrf", token, expire, "/", "") + ctx.SetSecureCookie(key, "_xsrf", token, expire, "/", "", true, true) } ctx._xsrfToken = token } diff --git a/server/web/grace/server.go b/server/web/grace/server.go index c8a5f840..982849f3 100644 --- a/server/web/grace/server.go +++ b/server/web/grace/server.go @@ -38,6 +38,7 @@ func (srv *Server) Serve() (err error) { } func (srv *Server) ServeWithListener(ln net.Listener) (err error) { + srv.ln = ln go srv.handleSignals() return srv.internalServe(ln) } diff --git a/task/task.go b/task/task.go index 09a08144..7001b9ed 100644 --- a/task/task.go +++ b/task/task.go @@ -465,11 +465,16 @@ func DeleteTask(taskName string) { globalTaskManager.DeleteTask(taskName) } -// ClearTask clear all tasks +// ClearTask clear all tasks func ClearTask() { globalTaskManager.ClearTask() } +// GetAllTasks get all tasks +func GetAllTasks() []Tasker { + return globalTaskManager.GetAllTasks() +} + // GracefulShutdown wait all task done func GracefulShutdown() <-chan struct{} { return globalTaskManager.GracefulShutdown() @@ -635,7 +640,7 @@ func (m *taskManager) DeleteTask(taskname string) { } } -// ClearTask clear all tasks +// ClearTask clear all tasks func (m *taskManager) ClearTask() { isChanged := false @@ -653,6 +658,20 @@ func (m *taskManager) ClearTask() { } } +// GetAllTasks get all tasks +func (m *taskManager) GetAllTasks() []Tasker { + m.taskLock.RLock() + + l := make([]Tasker, 0, len(m.adminTaskList)) + + for _, t := range m.adminTaskList { + l = append(l, t) + } + m.taskLock.RUnlock() + + return l +} + // MapSorter sort map for tasker type MapSorter struct { Keys []string diff --git a/task/task_test.go b/task/task_test.go index 8d274e8f..1fdfd4b9 100644 --- a/task/task_test.go +++ b/task/task_test.go @@ -206,3 +206,24 @@ func wait(wg *sync.WaitGroup) chan bool { }() return ch } + +func TestGetAllTasks(t *testing.T) { + m := newTaskManager() + defer m.ClearTask() + + tk := NewTask("task1", "0/30 * * * * *", func(ctx context.Context) error { + return nil + }) + + tk2 := NewTask("task2", "0/40 * * * * *", func(ctx context.Context) error { + return nil + }) + + m.AddTask("task1", tk) + m.AddTask("task2", tk2) + + tasks := m.GetAllTasks() + total := len(tasks) + + assert.Equal(t, 2, total) +} From 76343e4422710373ed4838e7262c4d54524e3b94 Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Wed, 23 Nov 2022 00:06:32 +0800 Subject: [PATCH 2/2] Prepare Release 2.0.6 (#5104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add: generic cache random time offset expired. * bugfix: Csrf token should be Secure and httpOnly, but not now * fix: expose the Offset property to allow external modifications * improving the concurrency performance of random value calculation * add WithOffsetFunc to define private RandomExpireCache.offset field * fix: add seconds definition * build(deps): bump github.com/stretchr/testify from 1.7.1 to 1.8.0 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.1 to 1.8.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.7.1...v1.8.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix 4907: force admin service http only * Feat: add get all tasks function (#4999) * feat: add get all tasks function * Refine Comments : admin/profile.go,bean/mock.go,config/global.go... (#5009) * Refine Comments * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * refine comments for for four files (#5011) * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * Update db.go * fix pass []any as any in variadic function by asasalint (#5012) * fix pass []any as any in variadic function * add change log * build(deps): bump go.opentelemetry.io/otel/trace from 1.7.0 to 1.8.0 (#5019) Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/trace dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refine comments for package core (#5014) * Refine Comments * refine comments for cache.go * refine comments for log.go * Update orm.go * refine comments for orm_log.go,types.go * Update utils.go * Update doc.go * refine comments * refine comments * Update db.go * refine comments for core * build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace (#5018) Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix 5022: Miss assiging ln to graceful Server (#5028) * prepare for releasing v2.0.5 * prepare for releasing v2.0.5 (#5032) * feat: make commands and docker compose for ORM unit tests (#5031) * feat: make commands and docker compose for ORM unit tests Signed-off-by: mango * add changelog Signed-off-by: mango Signed-off-by: mango * Modify comment syntax error (#5094) * fix: revise the body wrapper to handle empty body case (#5102) Fix the router.go serverHttp method, wrap the body if the request body is empty, which can avoid panic when calling the CopyBody method. Signed-off-by: chlins Signed-off-by: chlins Signed-off-by: dependabot[bot] Signed-off-by: mango Signed-off-by: chlins Co-authored-by: auual Co-authored-by: Leon Ding Co-authored-by: dada0z Co-authored-by: kevinzeng Co-authored-by: Kevin Tsang <39397413+ktalg@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 日暮颂歌1991 <448081525@qq.com> Co-authored-by: Regan Yue <1131625869@qq.com> Co-authored-by: alingse Co-authored-by: mango <35127166+mangoGoForward@users.noreply.github.com> Co-authored-by: 王哈哈 <31426858+wanghaha-dev@users.noreply.github.com> Co-authored-by: Chlins Zhang --- CHANGELOG.md | 1 + Makefile | 64 +++++++++ adapter/context/input.go | 2 +- adapter/orm/orm_conds.go | 6 +- client/httplib/error_code.go | 6 +- client/httplib/httplib.go | 2 +- client/orm/db.go | 4 +- client/orm/db_mysql.go | 2 +- client/orm/orm_conds.go | 6 +- client/orm/orm_queryset.go | 2 +- client/orm/types.go | 2 +- core/config/ini.go | 2 +- core/logs/es/es.go | 4 +- scripts/orm_docker_compose.yaml | 124 +++++++++++++++++ server/web/captcha/siprng.go | 2 +- server/web/context/input.go | 2 +- server/web/router.go | 223 +++++++++++++++++-------------- server/web/session/sess_utils.go | 2 +- server/web/template.go | 2 +- task/task.go | 2 +- 20 files changed, 339 insertions(+), 121 deletions(-) create mode 100644 Makefile create mode 100644 scripts/orm_docker_compose.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index f25b7dd5..7e803c99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Note: now we force the web admin service serving HTTP only. - [Feat 4999: add get all tasks function](https://github.com/beego/beego/pull/4999) - [Fix 5012: fix some bug, pass []any as any in variadic function](https://github.com/beego/beego/pull/5012) - [Fix 5022: Miss assigning listener to graceful Server](https://github.com/beego/beego/pull/5028) +- [Fix 4955: Make commands and Docker compose for ORM unit tests](https://github.com/beego/beego/pull/5031) # v2.0.4 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d2a2e169 --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +# Copyright 2020 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + + +##@ Test + +test-orm-mysql5: ## Run ORM unit tests on mysql5. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=mysql + export ORM_SOURCE="beego:test@tcp(localhost:13306)/orm_test?charset=utf8" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-mysql8: ## Run ORM unit tests on mysql8. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=mysql + export ORM_SOURCE="beego:test@tcp(localhost:23306)/orm_test?charset=utf8" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-pgsql: ## Run ORM unit tests on postgresql. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=postgres + export ORM_SOURCE="user=postgres password=postgres dbname=orm_test sslmode=disable" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-tidb: ## Run ORM unit tests on tidb. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=tidb + export ORM_SOURCE="memory://test/test" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +.PHONY: test-orm-all +test-orm-all: test-orm-mysql5 test-orm-mysql8 test-orm-pgsql test-orm-tidb diff --git a/adapter/context/input.go b/adapter/context/input.go index ac3e0c72..def81bf8 100644 --- a/adapter/context/input.go +++ b/adapter/context/input.go @@ -94,7 +94,7 @@ func (input *BeegoInput) IsHead() bool { return (*context.BeegoInput)(input).IsHead() } -// IsOptions Is this a OPTIONS method request? +// IsOptions Is this an OPTIONS method request? func (input *BeegoInput) IsOptions() bool { return (*context.BeegoInput)(input).IsOptions() } diff --git a/adapter/orm/orm_conds.go b/adapter/orm/orm_conds.go index 387caac2..4a713fcd 100644 --- a/adapter/orm/orm_conds.go +++ b/adapter/orm/orm_conds.go @@ -52,7 +52,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).AndCond((*orm.Condition)(cond))) } -// AndNotCond combine a AND NOT condition to current condition +// AndNotCond combine an AND NOT condition to current condition func (c *Condition) AndNotCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).AndNotCond((*orm.Condition)(cond))) } @@ -67,12 +67,12 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { return (*Condition)((orm.Condition)(c).OrNot(expr, args...)) } -// OrCond combine a OR condition to current condition +// OrCond combine an OR condition to current condition func (c *Condition) OrCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).OrCond((*orm.Condition)(cond))) } -// OrNotCond combine a OR NOT condition to current condition +// OrNotCond combine an OR NOT condition to current condition func (c *Condition) OrNotCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).OrNotCond((*orm.Condition)(cond))) } diff --git a/client/httplib/error_code.go b/client/httplib/error_code.go index f87041e4..43a68186 100644 --- a/client/httplib/error_code.go +++ b/client/httplib/error_code.go @@ -19,17 +19,17 @@ import ( ) var InvalidUrl = berror.DefineCode(4001001, moduleName, "InvalidUrl", ` -You pass a invalid url to httplib module. Please check your url, be careful about special character. +You pass an invalid url to httplib module. Please check your url, be careful about special character. `) var InvalidUrlProtocolVersion = berror.DefineCode(4001002, moduleName, "InvalidUrlProtocolVersion", ` -You pass a invalid protocol version. In practice, we use HTTP/1.0, HTTP/1.1, HTTP/1.2 +You pass an invalid protocol version. In practice, we use HTTP/1.0, HTTP/1.1, HTTP/1.2 But something like HTTP/3.2 is valid for client, and the major version is 3, minor version is 2. but you must confirm that server support those abnormal protocol version. `) var UnsupportedBodyType = berror.DefineCode(4001003, moduleName, "UnsupportedBodyType", ` -You use a invalid data as request body. +You use an invalid data as request body. For now, we only support type string and byte[]. `) diff --git a/client/httplib/httplib.go b/client/httplib/httplib.go index 147f595b..a9347395 100644 --- a/client/httplib/httplib.go +++ b/client/httplib/httplib.go @@ -112,7 +112,7 @@ func Head(url string) *BeegoHTTPRequest { return NewBeegoRequest(url, "HEAD") } -// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url. +// BeegoHTTPRequest provides more useful methods than http.Request for requesting an url. type BeegoHTTPRequest struct { url string req *http.Request diff --git a/client/orm/db.go b/client/orm/db.go index 08047a04..cbaa81ad 100644 --- a/client/orm/db.go +++ b/client/orm/db.go @@ -1111,7 +1111,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m ind.Set(mind) } else { if cnt == 0 { - // you can use a empty & caped container list + // you can use an empty & caped container list // orm will not replace it if ind.Len() != 0 { // if container is not empty @@ -1135,7 +1135,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m ind.Set(slice) } else { // when a result is empty and container is nil - // to set a empty container + // to set an empty container if ind.IsNil() { ind.Set(reflect.MakeSlice(ind.Type(), 0, 0)) } diff --git a/client/orm/db_mysql.go b/client/orm/db_mysql.go index 5b3333e0..75d24b2a 100644 --- a/client/orm/db_mysql.go +++ b/client/orm/db_mysql.go @@ -155,7 +155,7 @@ func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *model if isMulti { qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks } - // conflitValue maybe is a int,can`t use fmt.Sprintf + // conflitValue maybe is an int,can`t use fmt.Sprintf query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr) d.ins.ReplaceMarks(&query) diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index 7d6eabe2..9946e595 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -90,7 +90,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { return c } -// AndNotCond combine a AND NOT condition to current condition +// AndNotCond combine an AND NOT condition to current condition func (c *Condition) AndNotCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -121,7 +121,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { return &c } -// OrCond combine a OR condition to current condition +// OrCond combine an OR condition to current condition func (c *Condition) OrCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -133,7 +133,7 @@ func (c *Condition) OrCond(cond *Condition) *Condition { return c } -// OrNotCond combine a OR NOT condition to current condition +// OrNotCond combine an OR NOT condition to current condition func (c *Condition) OrNotCond(cond *Condition) *Condition { c = c.clone() if c == cond { diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 9f7b8441..82325899 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -257,7 +257,7 @@ func (o *querySet) DeleteWithCtx(ctx context.Context) (int64, error) { return o.orm.alias.DbBaser.DeleteBatch(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) } -// return a insert queryer. +// return an insert queryer. // it can be used in times. // example: // i,err := sq.PrepareInsert() diff --git a/client/orm/types.go b/client/orm/types.go index 145f2897..df50a500 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -405,7 +405,7 @@ type QuerySeter interface { // //delete two user who's name is testing1 or testing2 Delete() (int64, error) DeleteWithCtx(context.Context) (int64, error) - // return a insert queryer. + // return an insert queryer. // it can be used in times. // example: // i,err := sq.PrepareInsert() diff --git a/core/config/ini.go b/core/config/ini.go index e3a395e5..d4dea2e3 100644 --- a/core/config/ini.go +++ b/core/config/ini.go @@ -98,7 +98,7 @@ func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, e break } - // It might be a good idea to throw a error on all unknonw errors? + // It might be a good idea to throw an error on all unknonw errors? if _, ok := err.(*os.PathError); ok { return nil, err } diff --git a/core/logs/es/es.go b/core/logs/es/es.go index 2073ab3d..a07ee83c 100644 --- a/core/logs/es/es.go +++ b/core/logs/es/es.go @@ -105,11 +105,11 @@ func (el *esLogger) WriteMsg(lm *logs.LogMsg) error { return err } -// Destroy is a empty method +// Destroy is an empty method func (el *esLogger) Destroy() { } -// Flush is a empty method +// Flush is an empty method func (el *esLogger) Flush() { } diff --git a/scripts/orm_docker_compose.yaml b/scripts/orm_docker_compose.yaml new file mode 100644 index 00000000..0ccf93d0 --- /dev/null +++ b/scripts/orm_docker_compose.yaml @@ -0,0 +1,124 @@ +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: "3.8" +services: + # mysql5.7 + mysql5: + container_name: "beego-mysql5" + image: mysql:5.7.30 + ports: + - "13306:3306" + environment: + - MYSQL_ROOT_PASSWORD=1q2w3e + - MYSQL_DATABASE=orm_test + - MYSQL_USER=beego + - MYSQL_PASSWORD=test + + # mysql8.0 + mysql8: + container_name: "beego-mysql8" + image: mysql:8.0 + ports: + - "23306:3306" + environment: + - MYSQL_ROOT_PASSWORD=1q2w3e + - MYSQL_DATABASE=orm_test + - MYSQL_USER=beego + - MYSQL_PASSWORD=test + + # postgresql + postgresql: + container_name: "beego-postgresql" + image: bitnami/postgresql:latest + ports: + - "5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=orm_test + + # tidb + pd0: + image: pingcap/pd:latest + ports: + - "2379:2379" + volumes: + - ./config/pd.toml:/pd.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --name=pd0 + - --client-urls=http://0.0.0.0:2379 + - --peer-urls=http://0.0.0.0:2380 + - --advertise-client-urls=http://pd0:2379 + - --advertise-peer-urls=http://pd0:2380 + - --initial-cluster=pd0=http://pd0:2380 + - --data-dir=/data/pd0 + - --config=/pd.toml + - --log-file=/logs/pd0.log + restart: on-failure + + tikv0: + image: pingcap/tikv:latest + volumes: + - ./config/tikv.toml:/tikv.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --addr=0.0.0.0:20160 + - --advertise-addr=tikv0:20160 + - --data-dir=/data/tikv0 + - --pd=pd0:2379 + - --config=/tikv.toml + - --log-file=/logs/tikv0.log + depends_on: + - "pd0" + restart: on-failure + + tikv1: + image: pingcap/tikv:latest + volumes: + - ./config/tikv.toml:/tikv.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --addr=0.0.0.0:20160 + - --advertise-addr=tikv1:20160 + - --data-dir=/data/tikv1 + - --pd=pd0:2379 + - --config=/tikv.toml + - --log-file=/logs/tikv1.log + depends_on: + - "pd0" + restart: on-failure + + tidb: + image: pingcap/tidb:latest + ports: + - "4000:4000" + - "10080:10080" + volumes: + - ./config/tidb.toml:/tidb.toml:ro + - ./logs:/logs + command: + - --store=tikv + - --path=pd0:2379 + - --config=/tidb.toml + - --log-file=/logs/tidb.log + - --advertise-address=tidb + depends_on: + - "tikv0" + - "tikv1" + restart: on-failure diff --git a/server/web/captcha/siprng.go b/server/web/captcha/siprng.go index 5e256cf9..4fdf3143 100644 --- a/server/web/captcha/siprng.go +++ b/server/web/captcha/siprng.go @@ -27,7 +27,7 @@ type siprng struct { k0, k1, ctr uint64 } -// siphash implements SipHash-2-4, accepting a uint64 as a message. +// siphash implements SipHash-2-4, accepting an uint64 as a message. func siphash(k0, k1, m uint64) uint64 { // Initialization. v0 := k0 ^ 0x736f6d6570736575 diff --git a/server/web/context/input.go b/server/web/context/input.go index 241ef8bc..dfb14dfb 100644 --- a/server/web/context/input.go +++ b/server/web/context/input.go @@ -153,7 +153,7 @@ func (input *BeegoInput) IsHead() bool { return input.Is("HEAD") } -// IsOptions Is this a OPTIONS method request? +// IsOptions Is this an OPTIONS method request? func (input *BeegoInput) IsOptions() bool { return input.Is("OPTIONS") } diff --git a/server/web/router.go b/server/web/router.go index e37da0b7..1536bae4 100644 --- a/server/web/router.go +++ b/server/web/router.go @@ -15,8 +15,10 @@ package web import ( + "bytes" "errors" "fmt" + "io" "net/http" "path" "reflect" @@ -211,6 +213,7 @@ func (p *ControllerRegister) Init() { // Add controller handler and pattern rules to ControllerRegister. // usage: +// // default methods is the same name as method // Add("/user",&UserController{}) // Add("/api/list",&RestController{},"*:ListFood") @@ -348,9 +351,10 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) { // GetContext returns a context from pool, so usually you should remember to call Reset function to clean the context // And don't forget to give back context to pool // example: -// ctx := p.GetContext() -// ctx.Reset(w, q) -// defer p.GiveBackContext(ctx) +// +// ctx := p.GetContext() +// ctx.Reset(w, q) +// defer p.GiveBackContext(ctx) func (p *ControllerRegister) GetContext() *beecontext.Context { return p.pool.Get().(*beecontext.Context) } @@ -362,14 +366,16 @@ func (p *ControllerRegister) GiveBackContext(ctx *beecontext.Context) { // CtrlGet add get method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlGet("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlGet("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlGet("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlGet(pattern string, f interface{}) { p.AddRouterMethod(http.MethodGet, pattern, f) @@ -377,14 +383,16 @@ func (p *ControllerRegister) CtrlGet(pattern string, f interface{}) { // CtrlPost add post method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlPost("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlPost("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlPost("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlPost(pattern string, f interface{}) { p.AddRouterMethod(http.MethodPost, pattern, f) @@ -392,14 +400,16 @@ func (p *ControllerRegister) CtrlPost(pattern string, f interface{}) { // CtrlHead add head method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlHead("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlHead("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlHead("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlHead(pattern string, f interface{}) { p.AddRouterMethod(http.MethodHead, pattern, f) @@ -422,70 +432,75 @@ func (p *ControllerRegister) CtrlPut(pattern string, f interface{}) { // CtrlPatch add patch method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlPatch("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlPatch("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlPatch(pattern string, f interface{}) { p.AddRouterMethod(http.MethodPatch, pattern, f) } // CtrlDelete add delete method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlDelete("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlDelete("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlDelete(pattern string, f interface{}) { p.AddRouterMethod(http.MethodDelete, pattern, f) } // CtrlOptions add options method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlOptions("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlOptions("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlOptions(pattern string, f interface{}) { p.AddRouterMethod(http.MethodOptions, pattern, f) } // CtrlAny add all method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlAny("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlAny("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlAny(pattern string, f interface{}) { p.AddRouterMethod("*", pattern, f) } // AddRouterMethod add http method router // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// AddRouterMethod("get","/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// AddRouterMethod("get","/api/:id", MyController.Ping) func (p *ControllerRegister) AddRouterMethod(httpMethod, pattern string, f interface{}) { httpMethod = p.getUpperMethodString(httpMethod) ct, methodName := getReflectTypeAndMethod(f) @@ -624,81 +639,90 @@ type HandleFunc func(ctx *beecontext.Context) // Get add get method // usage: -// Get("/", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Get("/", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Get(pattern string, f HandleFunc) { p.AddMethod("get", pattern, f) } // Post add post method // usage: -// Post("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Post("/api", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Post(pattern string, f HandleFunc) { p.AddMethod("post", pattern, f) } // Put add put method // usage: -// Put("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Put("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Put(pattern string, f HandleFunc) { p.AddMethod("put", pattern, f) } // Delete add delete method // usage: -// Delete("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Delete("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Delete(pattern string, f HandleFunc) { p.AddMethod("delete", pattern, f) } // Head add head method // usage: -// Head("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Head("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Head(pattern string, f HandleFunc) { p.AddMethod("head", pattern, f) } // Patch add patch method // usage: -// Patch("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Patch("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Patch(pattern string, f HandleFunc) { p.AddMethod("patch", pattern, f) } // Options add options method // usage: -// Options("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Options("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Options(pattern string, f HandleFunc) { p.AddMethod("options", pattern, f) } // Any add all method // usage: -// Any("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Any("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Any(pattern string, f HandleFunc) { p.AddMethod("*", pattern, f) } // AddMethod add http method router // usage: -// AddMethod("get","/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// AddMethod("get","/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) AddMethod(method, pattern string, f HandleFunc) { method = p.getUpperMethodString(method) @@ -772,8 +796,8 @@ func (p *ControllerRegister) addAutoPrefixMethod(prefix, controllerName, methodN // InsertFilter Add a FilterFunc with pattern rule and action constant. // params is for: -// 1. setting the returnOnOutput value (false allows multiple filters to execute) -// 2. determining whether or not params need to be reset. +// 1. setting the returnOnOutput value (false allows multiple filters to execute) +// 2. determining whether or not params need to be reset. func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, opts ...FilterOpt) error { opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive)) mr := newFilterRouter(pattern, filter, opts...) @@ -784,13 +808,14 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter // but it will using chainRoot.filterFunc as input to build a new filterFunc // for example, assume that chainRoot is funcA // and we add new FilterChain -// fc := func(next) { -// return func(ctx) { -// // do something -// next(ctx) -// // do something -// } -// } +// +// fc := func(next) { +// return func(ctx) { +// // do something +// next(ctx) +// // do something +// } +// } func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, opts ...FilterOpt) { opts = append([]FilterOpt{WithCaseSensitive(p.cfg.RouterCaseSensitive)}, opts...) p.filterChains = append(p.filterChains, filterChainConfig{ @@ -1025,10 +1050,14 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) { } if r.Method != http.MethodGet && r.Method != http.MethodHead { + body := ctx.Input.Context.Request.Body + if body == nil { + body = io.NopCloser(bytes.NewReader([]byte{})) + } if ctx.Input.IsUpload() { ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter, - ctx.Input.Context.Request.Body, + body, p.cfg.MaxUploadSize) } else if p.cfg.CopyRequestBody { // connection will close if the incoming data are larger (RFC 7231, 6.5.11) @@ -1040,7 +1069,7 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) { ctx.Input.CopyBody(p.cfg.MaxMemory) } else { ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter, - ctx.Input.Context.Request.Body, + body, p.cfg.MaxMemory) } diff --git a/server/web/session/sess_utils.go b/server/web/session/sess_utils.go index 23242d7a..b2649336 100644 --- a/server/web/session/sess_utils.go +++ b/server/web/session/sess_utils.go @@ -98,7 +98,7 @@ func encrypt(block cipher.Block, value []byte) ([]byte, error) { // decrypt decrypts a value using the given block in counter mode. // -// The value to be decrypted must be prepended by a initialization vector +// The value to be decrypted must be prepended by an initialization vector // (http://goo.gl/zF67k) with the length of the block size. func decrypt(block cipher.Block, value []byte) ([]byte, error) { size := block.BlockSize() diff --git a/server/web/template.go b/server/web/template.go index c683c565..715c992d 100644 --- a/server/web/template.go +++ b/server/web/template.go @@ -103,7 +103,7 @@ func init() { beegoTplFuncMap["lt"] = lt // < beegoTplFuncMap["ne"] = ne // != - beegoTplFuncMap["urlfor"] = URLFor // build a URL to match a Controller and it's method + beegoTplFuncMap["urlfor"] = URLFor // build an URL to match a Controller and it's method } // AddFuncMap let user to register a func in the template. diff --git a/task/task.go b/task/task.go index 7001b9ed..91b8d2f8 100644 --- a/task/task.go +++ b/task/task.go @@ -221,7 +221,7 @@ func (f optionFunc) apply(t *Task) { f(t) } -// TimeoutOption return a option to set timeout duration for task +// TimeoutOption return an option to set timeout duration for task func TimeoutOption(timeout time.Duration) Option { return optionFunc(func(t *Task) { t.Timeout = timeout