From 0d77a3f8d2d4b7f27169d2652ca3da9b9c9e94db Mon Sep 17 00:00:00 2001 From: DennisMao Date: Thu, 6 Dec 2018 10:49:50 +0800 Subject: [PATCH 001/112] FixOrmDescrptionTag --- orm/models_info_f.go | 2 +- orm/models_utils.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/orm/models_info_f.go b/orm/models_info_f.go index 479f5ae6..7044b0bd 100644 --- a/orm/models_info_f.go +++ b/orm/models_info_f.go @@ -301,7 +301,7 @@ checkType: fi.sf = sf fi.fullName = mi.fullName + mName + "." + sf.Name - fi.description = sf.Tag.Get("description") + fi.description = tags["description"] fi.null = attrs["null"] fi.index = attrs["index"] fi.auto = attrs["auto"] diff --git a/orm/models_utils.go b/orm/models_utils.go index 31f8fb5a..8faa7683 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -44,6 +44,7 @@ var supportTag = map[string]int{ "decimals": 2, "on_delete": 2, "type": 2, + "description": 2, } // get reflect.Type name with package path. From bf468c8d0c75364947225be7f100f6611dec327d Mon Sep 17 00:00:00 2001 From: DennisMao Date: Thu, 6 Dec 2018 10:57:32 +0800 Subject: [PATCH 002/112] fix format --- orm/models_utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orm/models_utils.go b/orm/models_utils.go index 8faa7683..13a22aca 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -44,7 +44,7 @@ var supportTag = map[string]int{ "decimals": 2, "on_delete": 2, "type": 2, - "description": 2, + "description": 2, } // get reflect.Type name with package path. From 5e4241fc875385899a24641a258e9a278810f339 Mon Sep 17 00:00:00 2001 From: zav8 Date: Thu, 6 Dec 2018 16:07:07 +0800 Subject: [PATCH 003/112] add support for field of type sql.NullXxx in rawSet.setFieldValue() --- orm/orm_raw.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/orm/orm_raw.go b/orm/orm_raw.go index c8ef4398..08efa4e5 100644 --- a/orm/orm_raw.go +++ b/orm/orm_raw.go @@ -150,8 +150,10 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Struct: if value == nil { ind.Set(reflect.Zero(ind.Type())) - - } else if _, ok := ind.Interface().(time.Time); ok { + return + } + switch indi := ind.Interface().(type) { + case time.Time: var str string switch d := value.(type) { case time.Time: @@ -178,6 +180,26 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { } } } + case sql.NullString: + err := indi.Scan(value) + if err == nil { + ind.Set(reflect.ValueOf(indi)) + } + case sql.NullInt64: + err := indi.Scan(value) + if err == nil { + ind.Set(reflect.ValueOf(indi)) + } + case sql.NullFloat64: + err := indi.Scan(value) + if err == nil { + ind.Set(reflect.ValueOf(indi)) + } + case sql.NullBool: + err := indi.Scan(value) + if err == nil { + ind.Set(reflect.ValueOf(indi)) + } } } } From 6da4a66c20b284e78d4508013310f0872ae81eb8 Mon Sep 17 00:00:00 2001 From: zav8 Date: Thu, 6 Dec 2018 16:09:39 +0800 Subject: [PATCH 004/112] merge switch cases --- orm/orm_raw.go | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/orm/orm_raw.go b/orm/orm_raw.go index 08efa4e5..27651fe4 100644 --- a/orm/orm_raw.go +++ b/orm/orm_raw.go @@ -152,7 +152,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { ind.Set(reflect.Zero(ind.Type())) return } - switch indi := ind.Interface().(type) { + switch ind.Interface().(type) { case time.Time: var str string switch d := value.(type) { @@ -180,25 +180,15 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { } } } - case sql.NullString: - err := indi.Scan(value) - if err == nil { - ind.Set(reflect.ValueOf(indi)) + case sql.NullString, sql.NullInt64, sql.NullFloat64, sql.NullBool: + indi := reflect.New(ind.Type()).Interface() + sc, ok := indi.(sql.Scanner) + if !ok { + return } - case sql.NullInt64: - err := indi.Scan(value) + err := sc.Scan(value) if err == nil { - ind.Set(reflect.ValueOf(indi)) - } - case sql.NullFloat64: - err := indi.Scan(value) - if err == nil { - ind.Set(reflect.ValueOf(indi)) - } - case sql.NullBool: - err := indi.Scan(value) - if err == nil { - ind.Set(reflect.ValueOf(indi)) + ind.Set(reflect.Indirect(reflect.ValueOf(sc))) } } } From f03a7d11288879aa8b394f8dd5afbb08b30087f9 Mon Sep 17 00:00:00 2001 From: Chance Date: Thu, 13 Dec 2018 15:37:19 +0800 Subject: [PATCH 005/112] add GetProvider --- session/session.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/session/session.go b/session/session.go index c7e7dc69..46a9f1f0 100644 --- a/session/session.go +++ b/session/session.go @@ -81,6 +81,15 @@ func Register(name string, provide Provider) { provides[name] = provide } +//GetProvider +func GetProvider(name string) (Provider, error) { + provider, ok := provides[name] + if !ok { + return nil, fmt.Errorf("session: unknown provide %q (forgotten import?)", name) + } + return provider, nil +} + // ManagerConfig define the session config type ManagerConfig struct { CookieName string `json:"cookieName"` From c8f22be6750371ce1396f4357873da8dc9f030f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=AD=E4=B8=80=E9=B8=A3?= <281499083@qq.com> Date: Mon, 17 Dec 2018 21:47:47 +0800 Subject: [PATCH 006/112] Add redis sentinel session support (#3427) Add Redis Sentinel session support --- session/redis_sentinel/sess_redis_sentinel.go | 234 ++++++++++++++++++ .../sess_redis_sentinel_test.go | 84 +++++++ 2 files changed, 318 insertions(+) create mode 100644 session/redis_sentinel/sess_redis_sentinel.go create mode 100644 session/redis_sentinel/sess_redis_sentinel_test.go diff --git a/session/redis_sentinel/sess_redis_sentinel.go b/session/redis_sentinel/sess_redis_sentinel.go new file mode 100644 index 00000000..6ecb2977 --- /dev/null +++ b/session/redis_sentinel/sess_redis_sentinel.go @@ -0,0 +1,234 @@ +// 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 redis for session provider +// +// depend on github.com/go-redis/redis +// +// go install github.com/go-redis/redis +// +// Usage: +// import( +// _ "github.com/astaxie/beego/session/redis_sentinel" +// "github.com/astaxie/beego/session" +// ) +// +// func init() { +// globalSessions, _ = session.NewManager("redis_sentinel", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:26379;127.0.0.2:26379"}``) +// go globalSessions.GC() +// } +// +// more detail about params: please check the notes on the function SessionInit in this package +package redis_sentinel + +import ( + "github.com/astaxie/beego/session" + "github.com/go-redis/redis" + "net/http" + "strconv" + "strings" + "sync" + "time" +) + +var redispder = &Provider{} + +// DefaultPoolSize redis_sentinel default pool size +var DefaultPoolSize = 100 + +// SessionStore redis_sentinel session store +type SessionStore struct { + p *redis.Client + sid string + lock sync.RWMutex + values map[interface{}]interface{} + maxlifetime int64 +} + +// Set value in redis_sentinel session +func (rs *SessionStore) Set(key, value interface{}) error { + rs.lock.Lock() + defer rs.lock.Unlock() + rs.values[key] = value + return nil +} + +// Get value in redis_sentinel session +func (rs *SessionStore) Get(key interface{}) interface{} { + rs.lock.RLock() + defer rs.lock.RUnlock() + if v, ok := rs.values[key]; ok { + return v + } + return nil +} + +// Delete value in redis_sentinel session +func (rs *SessionStore) Delete(key interface{}) error { + rs.lock.Lock() + defer rs.lock.Unlock() + delete(rs.values, key) + return nil +} + +// Flush clear all values in redis_sentinel session +func (rs *SessionStore) Flush() error { + rs.lock.Lock() + defer rs.lock.Unlock() + rs.values = make(map[interface{}]interface{}) + return nil +} + +// SessionID get redis_sentinel session id +func (rs *SessionStore) SessionID() string { + return rs.sid +} + +// SessionRelease save session values to redis_sentinel +func (rs *SessionStore) SessionRelease(w http.ResponseWriter) { + b, err := session.EncodeGob(rs.values) + if err != nil { + return + } + c := rs.p + c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second) +} + +// Provider redis_sentinel session provider +type Provider struct { + maxlifetime int64 + savePath string + poolsize int + password string + dbNum int + poollist *redis.Client + masterName string +} + +// SessionInit init redis_sentinel session +// savepath like redis sentinel addr,pool size,password,dbnum,masterName +// e.g. 127.0.0.1:26379;127.0.0.2:26379,100,1qaz2wsx,0,mymaster +func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error { + rp.maxlifetime = maxlifetime + configs := strings.Split(savePath, ",") + if len(configs) > 0 { + rp.savePath = configs[0] + } + if len(configs) > 1 { + poolsize, err := strconv.Atoi(configs[1]) + if err != nil || poolsize < 0 { + rp.poolsize = DefaultPoolSize + } else { + rp.poolsize = poolsize + } + } else { + rp.poolsize = DefaultPoolSize + } + if len(configs) > 2 { + rp.password = configs[2] + } + if len(configs) > 3 { + dbnum, err := strconv.Atoi(configs[3]) + if err != nil || dbnum < 0 { + rp.dbNum = 0 + } else { + rp.dbNum = dbnum + } + } else { + rp.dbNum = 0 + } + if len(configs) > 4 { + if configs[4] != "" { + rp.masterName = configs[4] + } else { + rp.masterName = "mymaster" + } + } else { + rp.masterName = "mymaster" + } + + rp.poollist = redis.NewFailoverClient(&redis.FailoverOptions{ + SentinelAddrs: strings.Split(rp.savePath, ";"), + Password: rp.password, + PoolSize: rp.poolsize, + DB: rp.dbNum, + MasterName: rp.masterName, + }) + + return rp.poollist.Ping().Err() +} + +// SessionRead read redis_sentinel session by sid +func (rp *Provider) SessionRead(sid string) (session.Store, error) { + var kv map[interface{}]interface{} + kvs, err := rp.poollist.Get(sid).Result() + if err != nil && err != redis.Nil { + return nil, err + } + if len(kvs) == 0 { + kv = make(map[interface{}]interface{}) + } else { + if kv, err = session.DecodeGob([]byte(kvs)); err != nil { + return nil, err + } + } + + rs := &SessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime} + return rs, nil +} + +// SessionExist check redis_sentinel session exist by sid +func (rp *Provider) SessionExist(sid string) bool { + c := rp.poollist + if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 { + return false + } + return true +} + +// SessionRegenerate generate new sid for redis_sentinel session +func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { + c := rp.poollist + + if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 { + // oldsid doesn't exists, set the new sid directly + // ignore error here, since if it return error + // the existed value will be 0 + c.Set(sid, "", time.Duration(rp.maxlifetime)*time.Second) + } else { + c.Rename(oldsid, sid) + c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second) + } + return rp.SessionRead(sid) +} + +// SessionDestroy delete redis session by id +func (rp *Provider) SessionDestroy(sid string) error { + c := rp.poollist + c.Del(sid) + return nil +} + +// SessionGC Impelment method, no used. +func (rp *Provider) SessionGC() { +} + +// SessionAll return all activeSession +func (rp *Provider) SessionAll() int { + return 0 +} + +func init() { + session.Register("redis_sentinel", redispder) +} diff --git a/session/redis_sentinel/sess_redis_sentinel_test.go b/session/redis_sentinel/sess_redis_sentinel_test.go new file mode 100644 index 00000000..851fe804 --- /dev/null +++ b/session/redis_sentinel/sess_redis_sentinel_test.go @@ -0,0 +1,84 @@ +package redis_sentinel + +import ( + "github.com/astaxie/beego/session" + "net/http" + "net/http/httptest" + "testing" +) + +func TestRedisSentinel(t *testing.T) { + sessionConfig := &session.ManagerConfig{ + CookieName: "gosessionid", + EnableSetCookie: true, + Gclifetime: 3600, + Maxlifetime: 3600, + Secure: false, + CookieLifeTime: 3600, + ProviderConfig: "119.23.132.234:26379,100,,0,master", + } + globalSessions, _ := session.NewManager("redis_sentinel", sessionConfig) + go globalSessions.GC() + + r, _ := http.NewRequest("GET", "/", nil) + w := httptest.NewRecorder() + + sess, err := globalSessions.SessionStart(w, r) + if err != nil { + t.Fatal("session start failed:", err) + } + defer sess.SessionRelease(w) + + // SET AND GET + err = sess.Set("username", "astaxie") + if err != nil { + t.Fatal("set username failed:", err) + } + username := sess.Get("username") + if username != "astaxie" { + t.Fatal("get username failed") + } + + // DELETE + err = sess.Delete("username") + if err != nil { + t.Fatal("delete username failed:", err) + } + username = sess.Get("username") + if username != nil { + t.Fatal("delete username failed") + } + + // FLUSH + err = sess.Set("username", "astaxie") + if err != nil { + t.Fatal("set failed:", err) + } + err = sess.Set("password", "1qaz2wsx") + if err != nil { + t.Fatal("set failed:", err) + } + username = sess.Get("username") + if username != "astaxie" { + t.Fatal("get username failed") + } + password := sess.Get("password") + if password != "1qaz2wsx" { + t.Fatal("get password failed") + } + err = sess.Flush() + if err != nil { + t.Fatal("flush failed:", err) + } + username = sess.Get("username") + if username != nil { + t.Fatal("flush failed") + } + password = sess.Get("password") + if password != nil { + t.Fatal("flush failed") + } + + sess.SessionRelease(w) + +} From d2c289193ab2dfb5c981f3da66f6adb2eefa10b6 Mon Sep 17 00:00:00 2001 From: zav8 Date: Tue, 18 Dec 2018 10:37:41 +0800 Subject: [PATCH 007/112] add test case for QueryRow and QueryRows --- orm/orm_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/orm/orm_test.go b/orm/orm_test.go index 89a714b6..4f499a7c 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -1679,6 +1679,31 @@ func TestRawQueryRow(t *testing.T) { throwFail(t, AssertIs(uid, 4)) throwFail(t, AssertIs(*status, 3)) throwFail(t, AssertIs(pid, nil)) + + // test for sql.Null* fields + nData := &DataNull{ + NullString: sql.NullString{String: "test sql.null", Valid: true}, + NullBool: sql.NullBool{Bool: true, Valid: true}, + NullInt64: sql.NullInt64{Int64: 42, Valid: true}, + NullFloat64: sql.NullFloat64{Float64: 42.42, Valid: true}, + } + newId, err := dORM.Insert(nData) + throwFailNow(t, err) + + var nd *DataNull + query = fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q) + err = dORM.Raw(query, newId).QueryRow(&nd) + throwFailNow(t, err) + + throwFailNow(t, AssertNot(nd, nil)) + throwFail(t, AssertIs(nd.NullBool.Valid, true)) + throwFail(t, AssertIs(nd.NullBool.Bool, true)) + throwFail(t, AssertIs(nd.NullString.Valid, true)) + throwFail(t, AssertIs(nd.NullString.String, "test sql.null")) + throwFail(t, AssertIs(nd.NullInt64.Valid, true)) + throwFail(t, AssertIs(nd.NullInt64.Int64, 42)) + throwFail(t, AssertIs(nd.NullFloat64.Valid, true)) + throwFail(t, AssertIs(nd.NullFloat64.Float64, 42.42)) } // user_profile table @@ -1771,6 +1796,32 @@ func TestQueryRows(t *testing.T) { throwFailNow(t, AssertIs(l[1].UserName, "astaxie")) throwFailNow(t, AssertIs(l[1].Age, 30)) + // test for sql.Null* fields + nData := &DataNull{ + NullString: sql.NullString{String: "test sql.null", Valid: true}, + NullBool: sql.NullBool{Bool: true, Valid: true}, + NullInt64: sql.NullInt64{Int64: 42, Valid: true}, + NullFloat64: sql.NullFloat64{Float64: 42.42, Valid: true}, + } + newId, err := dORM.Insert(nData) + throwFailNow(t, err) + + var nDataList []*DataNull + query = fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q) + num, err = dORM.Raw(query, newId).QueryRows(&nDataList) + throwFailNow(t, err) + throwFailNow(t, AssertIs(num, 1)) + + nd := nDataList[0] + throwFailNow(t, AssertNot(nd, nil)) + throwFail(t, AssertIs(nd.NullBool.Valid, true)) + throwFail(t, AssertIs(nd.NullBool.Bool, true)) + throwFail(t, AssertIs(nd.NullString.Valid, true)) + throwFail(t, AssertIs(nd.NullString.String, "test sql.null")) + throwFail(t, AssertIs(nd.NullInt64.Valid, true)) + throwFail(t, AssertIs(nd.NullInt64.Int64, 42)) + throwFail(t, AssertIs(nd.NullFloat64.Valid, true)) + throwFail(t, AssertIs(nd.NullFloat64.Float64, 42.42)) } func TestRawValues(t *testing.T) { From 1dea80d4ea05fd88c97119c7fdfb38565506b93e Mon Sep 17 00:00:00 2001 From: James Pettyjohn Date: Sun, 13 Aug 2017 14:09:42 -0700 Subject: [PATCH 008/112] Fixed error handling in memcache sessions --- session/memcache/sess_memcache.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/session/memcache/sess_memcache.go b/session/memcache/sess_memcache.go index 755979c4..85a2d815 100644 --- a/session/memcache/sess_memcache.go +++ b/session/memcache/sess_memcache.go @@ -128,9 +128,12 @@ func (rp *MemProvider) SessionRead(sid string) (session.Store, error) { } } item, err := client.Get(sid) - if err != nil && err == memcache.ErrCacheMiss { - rs := &SessionStore{sid: sid, values: make(map[interface{}]interface{}), maxlifetime: rp.maxlifetime} - return rs, nil + if err != nil { + if err == memcache.ErrCacheMiss { + rs := &SessionStore{sid: sid, values: make(map[interface{}]interface{}), maxlifetime: rp.maxlifetime} + return rs, nil + } + return nil, err } var kv map[interface{}]interface{} if len(item.Value) == 0 { From 2034d1b10118feb633615ab4cd594a161bea263d Mon Sep 17 00:00:00 2001 From: zhl11b Date: Sat, 29 Dec 2018 17:41:59 +0800 Subject: [PATCH 009/112] =?UTF-8?q?=E8=81=94=E9=80=9A171=EF=BC=8C175=20?= =?UTF-8?q?=E7=94=B5=E4=BF=A1173?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- validation/validators.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation/validators.go b/validation/validators.go index 4dff9c0b..dc18b11e 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -632,7 +632,7 @@ func (b Base64) GetLimitValue() interface{} { } // just for chinese mobile phone number -var mobilePattern = regexp.MustCompile(`^((\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][06789]|[4][579]))\d{8}$`) +var mobilePattern = regexp.MustCompile(`^((\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][01356789]|[4][579]))\d{8}$`) // Mobile check struct type Mobile struct { From d02699a189c1874442752ada8d3bd232e672063b Mon Sep 17 00:00:00 2001 From: zhl11b Date: Sun, 30 Dec 2018 20:51:21 +0800 Subject: [PATCH 010/112] add new test case for china mobile phone --- validation/validation_test.go | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/validation/validation_test.go b/validation/validation_test.go index f97105fd..3146766b 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -268,6 +268,18 @@ func TestMobile(t *testing.T) { if !valid.Mobile("+8614700008888", "mobile").Ok { t.Error("\"+8614700008888\" is a valid mobile phone number should be true") } + if !valid.Mobile("17300008888", "mobile").Ok { + t.Error("\"17300008888\" is a valid mobile phone number should be true") + } + if !valid.Mobile("+8617100008888", "mobile").Ok { + t.Error("\"+8617100008888\" is a valid mobile phone number should be true") + } + if !valid.Mobile("8617500008888", "mobile").Ok { + t.Error("\"8617500008888\" is a valid mobile phone number should be true") + } + if valid.Mobile("8617400008888", "mobile").Ok { + t.Error("\"8617400008888\" is a valid mobile phone number should be false") + } } func TestTel(t *testing.T) { @@ -453,7 +465,7 @@ func TestPointer(t *testing.T) { u := User{ ReqEmail: nil, - Email: nil, + Email: nil, } valid := Validation{} @@ -468,7 +480,7 @@ func TestPointer(t *testing.T) { validEmail := "a@a.com" u = User{ ReqEmail: &validEmail, - Email: nil, + Email: nil, } valid = Validation{RequiredFirst: true} @@ -482,7 +494,7 @@ func TestPointer(t *testing.T) { u = User{ ReqEmail: &validEmail, - Email: nil, + Email: nil, } valid = Validation{} @@ -497,7 +509,7 @@ func TestPointer(t *testing.T) { invalidEmail := "a@a" u = User{ ReqEmail: &validEmail, - Email: &invalidEmail, + Email: &invalidEmail, } valid = Validation{RequiredFirst: true} @@ -511,7 +523,7 @@ func TestPointer(t *testing.T) { u = User{ ReqEmail: &validEmail, - Email: &invalidEmail, + Email: &invalidEmail, } valid = Validation{} @@ -524,19 +536,18 @@ func TestPointer(t *testing.T) { } } - func TestCanSkipAlso(t *testing.T) { type User struct { ID int - Email string `valid:"Email"` - ReqEmail string `valid:"Required;Email"` - MatchRange int `valid:"Range(10, 20)"` + Email string `valid:"Email"` + ReqEmail string `valid:"Required;Email"` + MatchRange int `valid:"Range(10, 20)"` } u := User{ - ReqEmail: "a@a.com", - Email: "", + ReqEmail: "a@a.com", + Email: "", MatchRange: 0, } @@ -560,4 +571,3 @@ func TestCanSkipAlso(t *testing.T) { } } - From 24215fb3eb134a4abf88d9b6fd2cc893bf550712 Mon Sep 17 00:00:00 2001 From: DennisMao Date: Wed, 2 Jan 2019 15:37:41 +0800 Subject: [PATCH 011/112] update dependency --- go.mod | 2 +- logs/es/es.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 9b3eb08e..a7e1194b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ require ( github.com/Knetic/govaluate v3.0.0+incompatible // indirect github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542 - github.com/belogik/goes v0.0.0-20151229125003-e54d722c3aff + github.com/OwnLocal/goes v1.0.0 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 github.com/casbin/casbin v1.7.0 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 diff --git a/logs/es/es.go b/logs/es/es.go index 22f4f650..9c0b830d 100644 --- a/logs/es/es.go +++ b/logs/es/es.go @@ -9,7 +9,7 @@ import ( "time" "github.com/astaxie/beego/logs" - "github.com/belogik/goes" + "github.com/OwnLocal/goes" ) // NewES return a LoggerInterface From 6e16b8cdcfec27bca8e7b62211381953e9a4bfde Mon Sep 17 00:00:00 2001 From: DennisMao Date: Wed, 2 Jan 2019 16:46:27 +0800 Subject: [PATCH 012/112] fix ci losing dependency --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ed04c9d1..97fc317b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ install: - go get github.com/Knetic/govaluate - go get github.com/casbin/casbin - go get github.com/elazarl/go-bindata-assetfs + - go get github.com/OwnLocal/goes - go get -u honnef.co/go/tools/cmd/gosimple - go get -u github.com/mdempsky/unconvert - go get -u github.com/gordonklaus/ineffassign From edb1c52dee08d36a1ab7031647d94068f2c93533 Mon Sep 17 00:00:00 2001 From: DennisMao Date: Wed, 2 Jan 2019 17:01:46 +0800 Subject: [PATCH 013/112] fix function changes --- logs/es/es.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/logs/es/es.go b/logs/es/es.go index 9c0b830d..9d6a615c 100644 --- a/logs/es/es.go +++ b/logs/es/es.go @@ -8,8 +8,8 @@ import ( "net/url" "time" - "github.com/astaxie/beego/logs" "github.com/OwnLocal/goes" + "github.com/astaxie/beego/logs" ) // NewES return a LoggerInterface @@ -21,7 +21,7 @@ func NewES() logs.Logger { } type esLogger struct { - *goes.Connection + *goes.Client DSN string `json:"dsn"` Level int `json:"level"` } @@ -41,8 +41,8 @@ func (el *esLogger) Init(jsonconfig string) error { } else if host, port, err := net.SplitHostPort(u.Host); err != nil { return err } else { - conn := goes.NewConnection(host, port) - el.Connection = conn + conn := goes.NewClient(host, port) + el.Client = conn } return nil } @@ -78,3 +78,4 @@ func (el *esLogger) Flush() { func init() { logs.Register(logs.AdapterEs, NewES) } + From bf15535a5bf5783b53e6764268dd1554cde3608e Mon Sep 17 00:00:00 2001 From: sanghee Date: Thu, 3 Jan 2019 22:44:32 +0900 Subject: [PATCH 014/112] fix panic: sync: negative WaitGroup counter --- grace/conn.go | 3 +-- grace/server.go | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/grace/conn.go b/grace/conn.go index e020f850..32623650 100644 --- a/grace/conn.go +++ b/grace/conn.go @@ -28,12 +28,11 @@ func (c *graceConn) Close() (err error) { }() c.m.Lock() + defer c.m.Unlock() if c.closed { - c.m.Unlock() return } c.server.wg.Done() c.closed = true - c.m.Unlock() return c.Conn.Close() } diff --git a/grace/server.go b/grace/server.go index 513a52a9..ef5cbe7e 100644 --- a/grace/server.go +++ b/grace/server.go @@ -34,6 +34,11 @@ type Server struct { // creating a new service goroutine for each. // The service goroutines read requests and then call srv.Handler to reply to them. func (srv *Server) Serve() (err error) { + defer func() { + if r := recover(); r != nil { + log.Println("wait group counter is negative", r) + } + }() srv.state = StateRunning err = srv.Server.Serve(srv.GraceListener) log.Println(syscall.Getpid(), "Waiting for connections to finish...") From d792536c23a25f98fb6e5c54de3e6cc111c466ed Mon Sep 17 00:00:00 2001 From: duyazhe Date: Mon, 14 Jan 2019 15:14:11 +0800 Subject: [PATCH 015/112] Update orm_log.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit orm log支持用户自定义函数处理 --- orm/orm_log.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/orm/orm_log.go b/orm/orm_log.go index 2a879c13..f107bb59 100644 --- a/orm/orm_log.go +++ b/orm/orm_log.go @@ -29,6 +29,9 @@ type Log struct { *log.Logger } +//costomer log func +var LogFunc func(query map[string]interface{}) + // NewLog set io.Writer to create a Logger. func NewLog(out io.Writer) *Log { d := new(Log) @@ -37,12 +40,15 @@ func NewLog(out io.Writer) *Log { } func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error, args ...interface{}) { + var logMap = make(map[string]interface{}) sub := time.Now().Sub(t) / 1e5 elsp := float64(int(sub)) / 10.0 + logMap["cost_time"] = elsp flag := " OK" if err != nil { flag = "FAIL" } + logMap["flag"] = flag con := fmt.Sprintf(" -[Queries/%s] - [%s / %11s / %7.1fms] - [%s]", alias.Name, flag, operaton, elsp, query) cons := make([]string, 0, len(args)) for _, arg := range args { @@ -54,6 +60,10 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error if err != nil { con += " - " + err.Error() } + logMap["sql"] = fmt.Sprintf("%s-`%s`", query, strings.Join(cons, "`, `")) + if LogFunc != nil{ + LogFunc(logMap) + } DebugLog.Println(con) } From 7173fd7490841746aa0ed254b81692117f892e54 Mon Sep 17 00:00:00 2001 From: nuczzz Date: Thu, 17 Jan 2019 20:17:57 +0800 Subject: [PATCH 016/112] modify http graceful --- grace/conn.go | 38 ------------------ grace/grace.go | 22 +++++------ grace/listener.go | 62 ------------------------------ grace/server.go | 98 ++++++++++++++++------------------------------- 4 files changed, 43 insertions(+), 177 deletions(-) delete mode 100644 grace/conn.go delete mode 100644 grace/listener.go diff --git a/grace/conn.go b/grace/conn.go deleted file mode 100644 index 32623650..00000000 --- a/grace/conn.go +++ /dev/null @@ -1,38 +0,0 @@ -package grace - -import ( - "errors" - "net" - "sync" -) - -type graceConn struct { - net.Conn - server *Server - m sync.Mutex - closed bool -} - -func (c *graceConn) Close() (err error) { - defer func() { - if r := recover(); r != nil { - switch x := r.(type) { - case string: - err = errors.New(x) - case error: - err = x - default: - err = errors.New("Unknown panic") - } - } - }() - - c.m.Lock() - defer c.m.Unlock() - if c.closed { - return - } - c.server.wg.Done() - c.closed = true - return c.Conn.Close() -} diff --git a/grace/grace.go b/grace/grace.go index 6ebf8455..5a8bc3b8 100644 --- a/grace/grace.go +++ b/grace/grace.go @@ -122,7 +122,6 @@ func NewServer(addr string, handler http.Handler) (srv *Server) { } srv = &Server{ - wg: sync.WaitGroup{}, sigChan: make(chan os.Signal), isChild: isChild, SignalHooks: map[int]map[os.Signal][]func(){ @@ -137,20 +136,21 @@ func NewServer(addr string, handler http.Handler) (srv *Server) { syscall.SIGTERM: {}, }, }, - state: StateInit, - Network: "tcp", + state: StateInit, + Network: "tcp", + terminalChan: make(chan error), //no cache channel + } + srv.Server = &http.Server{ + Addr: addr, + ReadTimeout: DefaultReadTimeOut, + WriteTimeout: DefaultWriteTimeOut, + MaxHeaderBytes: DefaultMaxHeaderBytes, + Handler: handler, } - srv.Server = &http.Server{} - srv.Server.Addr = addr - srv.Server.ReadTimeout = DefaultReadTimeOut - srv.Server.WriteTimeout = DefaultWriteTimeOut - srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes - srv.Server.Handler = handler runningServersOrder = append(runningServersOrder, addr) runningServers[addr] = srv - - return + return srv } // ListenAndServe refer http.ListenAndServe diff --git a/grace/listener.go b/grace/listener.go deleted file mode 100644 index 7ede63a3..00000000 --- a/grace/listener.go +++ /dev/null @@ -1,62 +0,0 @@ -package grace - -import ( - "net" - "os" - "syscall" - "time" -) - -type graceListener struct { - net.Listener - stop chan error - stopped bool - server *Server -} - -func newGraceListener(l net.Listener, srv *Server) (el *graceListener) { - el = &graceListener{ - Listener: l, - stop: make(chan error), - server: srv, - } - go func() { - <-el.stop - el.stopped = true - el.stop <- el.Listener.Close() - }() - return -} - -func (gl *graceListener) Accept() (c net.Conn, err error) { - tc, err := gl.Listener.(*net.TCPListener).AcceptTCP() - if err != nil { - return - } - - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - - c = &graceConn{ - Conn: tc, - server: gl.server, - } - - gl.server.wg.Add(1) - return -} - -func (gl *graceListener) Close() error { - if gl.stopped { - return syscall.EINVAL - } - gl.stop <- nil - return <-gl.stop -} - -func (gl *graceListener) File() *os.File { - // returns a dup(2) - FD_CLOEXEC flag *not* set - tl := gl.Listener.(*net.TCPListener) - fl, _ := tl.File() - return fl -} diff --git a/grace/server.go b/grace/server.go index ef5cbe7e..ade05ef7 100644 --- a/grace/server.go +++ b/grace/server.go @@ -1,6 +1,7 @@ package grace import ( + "context" "crypto/tls" "crypto/x509" "fmt" @@ -12,39 +13,37 @@ import ( "os/exec" "os/signal" "strings" - "sync" "syscall" - "time" ) // Server embedded http.Server type Server struct { *http.Server - GraceListener net.Listener - SignalHooks map[int]map[os.Signal][]func() - tlsInnerListener *graceListener - wg sync.WaitGroup - sigChan chan os.Signal - isChild bool - state uint8 - Network string + ln net.Listener + SignalHooks map[int]map[os.Signal][]func() + sigChan chan os.Signal + isChild bool + state uint8 + Network string + terminalChan chan error } // Serve accepts incoming connections on the Listener l, // creating a new service goroutine for each. // The service goroutines read requests and then call srv.Handler to reply to them. func (srv *Server) Serve() (err error) { - defer func() { - if r := recover(); r != nil { - log.Println("wait group counter is negative", r) - } - }() srv.state = StateRunning - err = srv.Server.Serve(srv.GraceListener) - log.Println(syscall.Getpid(), "Waiting for connections to finish...") - srv.wg.Wait() - srv.state = StateTerminate - return + defer func() { srv.state = StateTerminate }() + + // When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS + // immediately return ErrServerClosed. Make sure the program doesn't exit + // and waits instead for Shutdown to return. + if err = srv.Server.Serve(srv.ln); err != nil && err != http.ErrServerClosed { + return err + } + + // wait for Shutdown to return + return <-srv.terminalChan } // ListenAndServe listens on the TCP network address srv.Addr and then calls Serve @@ -58,14 +57,12 @@ func (srv *Server) ListenAndServe() (err error) { go srv.handleSignals() - l, err := srv.getListener(addr) + srv.ln, err = srv.getListener(addr) if err != nil { log.Println(err) return err } - srv.GraceListener = newGraceListener(l, srv) - if srv.isChild { process, err := os.FindProcess(os.Getppid()) if err != nil { @@ -112,14 +109,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) { go srv.handleSignals() - l, err := srv.getListener(addr) + ln, err := srv.getListener(addr) if err != nil { log.Println(err) return err } - - srv.tlsInnerListener = newGraceListener(l, srv) - srv.GraceListener = tls.NewListener(srv.tlsInnerListener, srv.TLSConfig) + srv.ln = tls.NewListener(ln, srv.TLSConfig) if srv.isChild { process, err := os.FindProcess(os.Getppid()) @@ -132,6 +127,7 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) { return err } } + log.Println(os.Getpid(), srv.Addr) return srv.Serve() } @@ -168,14 +164,12 @@ func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) log.Println("Mutual HTTPS") go srv.handleSignals() - l, err := srv.getListener(addr) + ln, err := srv.getListener(addr) if err != nil { log.Println(err) return err } - - srv.tlsInnerListener = newGraceListener(l, srv) - srv.GraceListener = tls.NewListener(srv.tlsInnerListener, srv.TLSConfig) + srv.ln = tls.NewListener(ln, srv.TLSConfig) if srv.isChild { process, err := os.FindProcess(os.Getppid()) @@ -188,6 +182,7 @@ func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) return err } } + log.Println(os.Getpid(), srv.Addr) return srv.Serve() } @@ -270,37 +265,12 @@ func (srv *Server) shutdown() { } srv.state = StateShuttingDown + log.Println(syscall.Getpid(), "Waiting for connections to finish...") + ctx := context.Background() if DefaultTimeout >= 0 { - go srv.serverTimeout(DefaultTimeout) - } - err := srv.GraceListener.Close() - if err != nil { - log.Println(syscall.Getpid(), "Listener.Close() error:", err) - } else { - log.Println(syscall.Getpid(), srv.GraceListener.Addr(), "Listener closed.") - } -} - -// serverTimeout forces the server to shutdown in a given timeout - whether it -// finished outstanding requests or not. if Read/WriteTimeout are not set or the -// max header size is very big a connection could hang -func (srv *Server) serverTimeout(d time.Duration) { - defer func() { - if r := recover(); r != nil { - log.Println("WaitGroup at 0", r) - } - }() - if srv.state != StateShuttingDown { - return - } - time.Sleep(d) - log.Println("[STOP - Hammer Time] Forcefully shutting down parent") - for { - if srv.state == StateTerminate { - break - } - srv.wg.Done() + ctx, _ = context.WithTimeout(context.Background(), DefaultTimeout) } + srv.terminalChan <- srv.Server.Shutdown(ctx) } func (srv *Server) fork() (err error) { @@ -314,12 +284,8 @@ func (srv *Server) fork() (err error) { var files = make([]*os.File, len(runningServers)) var orderArgs = make([]string, len(runningServers)) for _, srvPtr := range runningServers { - switch srvPtr.GraceListener.(type) { - case *graceListener: - files[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.GraceListener.(*graceListener).File() - default: - files[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.tlsInnerListener.File() - } + f, _ := srvPtr.ln.(*net.TCPListener).File() + files[socketPtrOffsetMap[srvPtr.Server.Addr]] = f orderArgs[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.Server.Addr } From 2ae480556dc660ac3e9b9a5078568e7af7a5847a Mon Sep 17 00:00:00 2001 From: Bharat Patel Date: Thu, 17 Jan 2019 09:56:42 -0800 Subject: [PATCH 017/112] Add DBStats method wrapper to provide sql.DBStats when using ormer --- orm/orm.go | 5 +++++ orm/types.go | 1 + 2 files changed, 6 insertions(+) diff --git a/orm/orm.go b/orm/orm.go index bcf6e4be..b7296ab9 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -522,6 +522,11 @@ func (o *orm) Driver() Driver { return driver(o.alias.Name) } +// return sql.DBStats for current database +func (o *orm) DBStats() sql.DBStats { + return o.alias.DB.Stats() +} + // NewOrm create new orm func NewOrm() Ormer { BootStrap() // execute only once diff --git a/orm/types.go b/orm/types.go index ddf39a2b..4c67c7a6 100644 --- a/orm/types.go +++ b/orm/types.go @@ -128,6 +128,7 @@ type Ormer interface { // // update user testing's name to slene Raw(query string, args ...interface{}) RawSeter Driver() Driver + DBStats() sql.DBStats } // Inserter insert prepared statement From 313be996cd9ed3c4bc2647b6303d651c4b487fd3 Mon Sep 17 00:00:00 2001 From: nuczzz Date: Fri, 18 Jan 2019 19:33:45 +0800 Subject: [PATCH 018/112] call cancel after shutdown --- grace/server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grace/server.go b/grace/server.go index ade05ef7..ac3eefa7 100644 --- a/grace/server.go +++ b/grace/server.go @@ -268,7 +268,9 @@ func (srv *Server) shutdown() { log.Println(syscall.Getpid(), "Waiting for connections to finish...") ctx := context.Background() if DefaultTimeout >= 0 { - ctx, _ = context.WithTimeout(context.Background(), DefaultTimeout) + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout) + defer cancel() } srv.terminalChan <- srv.Server.Shutdown(ctx) } From e295c3c7c3f0bec6ed782d77cc55a49b5c31b4ec Mon Sep 17 00:00:00 2001 From: nuczzz Date: Fri, 18 Jan 2019 19:50:22 +0800 Subject: [PATCH 019/112] add shutdown log --- grace/server.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grace/server.go b/grace/server.go index ac3eefa7..e5302baa 100644 --- a/grace/server.go +++ b/grace/server.go @@ -39,9 +39,11 @@ func (srv *Server) Serve() (err error) { // immediately return ErrServerClosed. Make sure the program doesn't exit // and waits instead for Shutdown to return. if err = srv.Server.Serve(srv.ln); err != nil && err != http.ErrServerClosed { + log.Println(syscall.Getpid(), "Server.Serve() error:", err) return err } + log.Println(syscall.Getpid(), srv.ln.Addr(), "Listener closed.") // wait for Shutdown to return return <-srv.terminalChan } From f508f8d959258ecfab3314f0183fc02be755f246 Mon Sep 17 00:00:00 2001 From: Bharat Patel Date: Fri, 18 Jan 2019 16:51:40 -0800 Subject: [PATCH 020/112] Nil check --- orm/orm.go | 9 +++++++-- orm/types.go | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/orm/orm.go b/orm/orm.go index b7296ab9..fc3cd400 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -523,8 +523,13 @@ func (o *orm) Driver() Driver { } // return sql.DBStats for current database -func (o *orm) DBStats() sql.DBStats { - return o.alias.DB.Stats() +func (o *orm) DBStats() *sql.DBStats { + if o.alias != nil && o.alias.DB != nil { + stats := o.alias.DB.Stats() + return &stats + } + + return nil } // NewOrm create new orm diff --git a/orm/types.go b/orm/types.go index 4c67c7a6..6c6443c7 100644 --- a/orm/types.go +++ b/orm/types.go @@ -128,7 +128,7 @@ type Ormer interface { // // update user testing's name to slene Raw(query string, args ...interface{}) RawSeter Driver() Driver - DBStats() sql.DBStats + DBStats() *sql.DBStats } // Inserter insert prepared statement From fe519bd2a054cd1da746d2d9b82843379c2067df Mon Sep 17 00:00:00 2001 From: nuczzz Date: Sun, 20 Jan 2019 11:17:10 +0800 Subject: [PATCH 021/112] update tls KeepAlive setting --- grace/server.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/grace/server.go b/grace/server.go index e5302baa..1ce8bc78 100644 --- a/grace/server.go +++ b/grace/server.go @@ -14,6 +14,7 @@ import ( "os/signal" "strings" "syscall" + "time" ) // Server embedded http.Server @@ -116,7 +117,7 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) { log.Println(err) return err } - srv.ln = tls.NewListener(ln, srv.TLSConfig) + srv.ln = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig) if srv.isChild { process, err := os.FindProcess(os.Getppid()) @@ -171,7 +172,7 @@ func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) log.Println(err) return err } - srv.ln = tls.NewListener(ln, srv.TLSConfig) + srv.ln = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig) if srv.isChild { process, err := os.FindProcess(os.Getppid()) @@ -215,6 +216,20 @@ func (srv *Server) getListener(laddr string) (l net.Listener, err error) { return } +type tcpKeepAliveListener struct { + *net.TCPListener +} + +func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { + tc, err := ln.AcceptTCP() + if err != nil { + return + } + tc.SetKeepAlive(true) + tc.SetKeepAlivePeriod(3 * time.Minute) + return tc, nil +} + // handleSignals listens for os Signals and calls any hooked in function that the // user had registered with the signal. func (srv *Server) handleSignals() { From 30b80cba9219bc007e7898ea5af4fac88859b27d Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 16:23:10 +0800 Subject: [PATCH 022/112] errors is better style --- router.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router.go b/router.go index 997b6854..0ccc1568 100644 --- a/router.go +++ b/router.go @@ -15,6 +15,7 @@ package beego import ( + "errors" "fmt" "net/http" "path" @@ -479,8 +480,7 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter // add Filter into func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) { if pos < BeforeStatic || pos > FinishRouter { - err = fmt.Errorf("can not find your filter position") - return + return errors.New("can not find your filter position") } p.enableFilter = true p.filters[pos] = append(p.filters[pos], mr) From 475feb7e241e96da85e26d02bafa9ab9cd295318 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 16:25:17 +0800 Subject: [PATCH 023/112] camel name style --- router.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/router.go b/router.go index 0ccc1568..9004819c 100644 --- a/router.go +++ b/router.go @@ -510,10 +510,10 @@ func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) stri } } } - controllName := strings.Join(paths[:len(paths)-1], "/") + controllerName := strings.Join(paths[:len(paths)-1], "/") methodName := paths[len(paths)-1] for m, t := range p.routers { - ok, url := p.geturl(t, "/", controllName, methodName, params, m) + ok, url := p.getUrl(t, "/", controllerName, methodName, params, m) if ok { return url } @@ -521,17 +521,17 @@ func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) stri return "" } -func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName string, params map[string]string, httpMethod string) (bool, string) { +func (p *ControllerRegister) getUrl(t *Tree, url, controllerName, methodName string, params map[string]string, httpMethod string) (bool, string) { for _, subtree := range t.fixrouters { u := path.Join(url, subtree.prefix) - ok, u := p.geturl(subtree, u, controllName, methodName, params, httpMethod) + ok, u := p.getUrl(subtree, u, controllerName, methodName, params, httpMethod) if ok { return ok, u } } if t.wildcard != nil { u := path.Join(url, urlPlaceholder) - ok, u := p.geturl(t.wildcard, u, controllName, methodName, params, httpMethod) + ok, u := p.getUrl(t.wildcard, u, controllerName, methodName, params, httpMethod) if ok { return ok, u } @@ -539,7 +539,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin for _, l := range t.leaves { if c, ok := l.runObject.(*ControllerInfo); ok { if c.routerType == routerTypeBeego && - strings.HasSuffix(path.Join(c.controllerType.PkgPath(), c.controllerType.Name()), controllName) { + strings.HasSuffix(path.Join(c.controllerType.PkgPath(), c.controllerType.Name()), controllerName) { find := false if HTTPMETHOD[strings.ToUpper(methodName)] { if len(c.methods) == 0 { @@ -578,18 +578,18 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin } } } - canskip := false + canSkip := false for _, v := range l.wildcards { if v == ":" { - canskip = true + canSkip = true continue } if u, ok := params[v]; ok { delete(params, v) url = strings.Replace(url, urlPlaceholder, u, 1) } else { - if canskip { - canskip = false + if canSkip { + canSkip = false continue } return false, "" @@ -598,27 +598,27 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin return true, url + toURL(params) } var i int - var startreg bool - regurl := "" + var startReg bool + regUrl := "" for _, v := range strings.Trim(l.regexps.String(), "^$") { if v == '(' { - startreg = true + startReg = true continue } else if v == ')' { - startreg = false + startReg = false if v, ok := params[l.wildcards[i]]; ok { delete(params, l.wildcards[i]) - regurl = regurl + v + regUrl = regUrl + v i++ } else { break } - } else if !startreg { - regurl = string(append([]rune(regurl), v)) + } else if !startReg { + regUrl = string(append([]rune(regUrl), v)) } } - if l.regexps.MatchString(regurl) { - ps := strings.Split(regurl, "/") + if l.regexps.MatchString(regUrl) { + ps := strings.Split(regUrl, "/") for _, p := range ps { url = strings.Replace(url, urlPlaceholder, p, 1) } From 3ed82c088208119ab6a021f42657441003fc2634 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 17:43:55 +0800 Subject: [PATCH 024/112] Gosimple has been deprecated. Please use staticcheck instead. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97fc317b..343041bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ install: - go get github.com/casbin/casbin - go get github.com/elazarl/go-bindata-assetfs - go get github.com/OwnLocal/goes - - go get -u honnef.co/go/tools/cmd/gosimple + - go get -u honnef.co/go/tools/cmd/staticcheck - go get -u github.com/mdempsky/unconvert - go get -u github.com/gordonklaus/ineffassign - go get -u github.com/golang/lint/golint @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - gosimple -ignore "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) + - staticcheck -show-ignore "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s From e65a9cbc0092d935e5ca848e6054f06bc230c2dc Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 18:01:14 +0800 Subject: [PATCH 025/112] Gosimple has been deprecated. Please use staticcheck instead. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 343041bf..6755cac3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignore "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) + - staticcheck -show-ignored "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s From 0d54bbff0238f6d22c983db07f97c02efd1617da Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 19:09:57 +0800 Subject: [PATCH 026/112] make staticcheck happy --- controller.go | 17 ++++++++--------- fs.go | 2 +- namespace.go | 8 ++++---- parser.go | 14 +++++++------- router.go | 2 +- router_test.go | 15 +-------------- template.go | 4 ++-- templatefunc.go | 2 +- templatefunc_test.go | 1 - 9 files changed, 25 insertions(+), 40 deletions(-) diff --git a/controller.go b/controller.go index 4b8f9807..7859681f 100644 --- a/controller.go +++ b/controller.go @@ -34,7 +34,7 @@ import ( var ( // ErrAbort custom error when user stop request handler manually. - ErrAbort = errors.New("User stop run") + ErrAbort = errors.New("user stop run") // GlobalControllerRouter store comments with controller. pkgpath+controller:comments GlobalControllerRouter = make(map[string][]ControllerComments) ) @@ -93,7 +93,6 @@ type Controller struct { controllerName string actionName string methodMapping map[string]func() //method:routertree - gotofunc string AppController interface{} // template data @@ -156,37 +155,37 @@ func (c *Controller) Finish() {} // Get adds a request function to handle GET request. func (c *Controller) Get() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Post adds a request function to handle POST request. func (c *Controller) Post() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Delete adds a request function to handle DELETE request. func (c *Controller) Delete() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Put adds a request function to handle PUT request. func (c *Controller) Put() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Head adds a request function to handle HEAD request. func (c *Controller) Head() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Patch adds a request function to handle PATCH request. func (c *Controller) Patch() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // Options adds a request function to handle OPTIONS request. func (c *Controller) Options() { - http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405) + http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } // HandlerFunc call function with the name diff --git a/fs.go b/fs.go index bf7002ad..41cc6f6e 100644 --- a/fs.go +++ b/fs.go @@ -42,13 +42,13 @@ func walk(fs http.FileSystem, path string, info os.FileInfo, walkFn filepath.Wal } dir, err := fs.Open(path) - defer dir.Close() if err != nil { if err1 := walkFn(path, info, err); err1 != nil { return err1 } return err } + defer dir.Close() dirs, err := dir.Readdir(-1) err1 := walkFn(path, info, err) // If err != nil, walk can't walk into this directory. diff --git a/namespace.go b/namespace.go index 72f22a72..4952c9d5 100644 --- a/namespace.go +++ b/namespace.go @@ -207,11 +207,11 @@ func (n *Namespace) Include(cList ...ControllerInterface) *Namespace { func (n *Namespace) Namespace(ns ...*Namespace) *Namespace { for _, ni := range ns { for k, v := range ni.handlers.routers { - if t, ok := n.handlers.routers[k]; ok { + if _, ok := n.handlers.routers[k]; ok { addPrefix(v, ni.prefix) n.handlers.routers[k].AddTree(ni.prefix, v) } else { - t = NewTree() + t := NewTree() t.AddTree(ni.prefix, v) addPrefix(t, ni.prefix) n.handlers.routers[k] = t @@ -236,11 +236,11 @@ func (n *Namespace) Namespace(ns ...*Namespace) *Namespace { func AddNamespace(nl ...*Namespace) { for _, n := range nl { for k, v := range n.handlers.routers { - if t, ok := BeeApp.Handlers.routers[k]; ok { + if _, ok := BeeApp.Handlers.routers[k]; ok { addPrefix(v, n.prefix) BeeApp.Handlers.routers[k].AddTree(n.prefix, v) } else { - t = NewTree() + t := NewTree() t.AddTree(n.prefix, v) addPrefix(t, n.prefix) BeeApp.Handlers.routers[k] = t diff --git a/parser.go b/parser.go index a8690274..9c509075 100644 --- a/parser.go +++ b/parser.go @@ -259,9 +259,9 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { imports := []parsedImport{} for _, c := range lines { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + t := strings.TrimSpace(strings.TrimPrefix(c.Text, "//")) if strings.HasPrefix(t, "@Param") { - pv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Param"))) + pv := getparams(strings.TrimSpace(strings.TrimPrefix(t, "@Param"))) if len(pv) < 4 { logs.Error("Invalid @Param format. Needs at least 4 parameters") } @@ -286,7 +286,7 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { } for _, c := range lines { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + t := strings.TrimSpace(strings.TrimPrefix(c.Text, "//")) if strings.HasPrefix(t, "@Import") { iv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Import"))) if len(iv) == 0 || len(iv) > 2 { @@ -307,9 +307,9 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { filterLoop: for _, c := range lines { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) if strings.HasPrefix(t, "@Filter") { - fv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Filter"))) + fv := getparams(strings.TrimSpace(strings.TrimPrefix(t, "@Filter"))) if len(fv) < 3 { logs.Error("Invalid @Filter format. Needs at least 3 parameters") continue filterLoop @@ -349,9 +349,9 @@ filterLoop: pc.filters = filters pc.imports = imports - t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) if strings.HasPrefix(t, "@router") { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) matches := routeRegex.FindStringSubmatch(t) if len(matches) == 3 { pc.routerPath = matches[1] diff --git a/router.go b/router.go index 9004819c..c5b618c3 100644 --- a/router.go +++ b/router.go @@ -690,7 +690,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) // filter wrong http method if !HTTPMETHOD[r.Method] { - http.Error(rw, "Method Not Allowed", 405) + http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) goto Admin } diff --git a/router_test.go b/router_test.go index 90104427..2797b33a 100644 --- a/router_test.go +++ b/router_test.go @@ -71,10 +71,6 @@ func (tc *TestController) GetEmptyBody() { tc.Ctx.Output.Body(res) } -type ResStatus struct { - Code int - Msg string -} type JSONController struct { Controller @@ -475,7 +471,7 @@ func TestParamResetFilter(t *testing.T) { // a response header of `Splat`. The expectation here is that that Header // value should match what the _request's_ router set, not the filter's. - headers := rw.HeaderMap + headers := rw.Result().Header if len(headers["Splat"]) != 1 { t.Errorf( "%s: There was an error in the test. Splat param not set in Header", @@ -660,25 +656,16 @@ func beegoBeforeRouter1(ctx *context.Context) { ctx.WriteString("|BeforeRouter1") } -func beegoBeforeRouter2(ctx *context.Context) { - ctx.WriteString("|BeforeRouter2") -} func beegoBeforeExec1(ctx *context.Context) { ctx.WriteString("|BeforeExec1") } -func beegoBeforeExec2(ctx *context.Context) { - ctx.WriteString("|BeforeExec2") -} func beegoAfterExec1(ctx *context.Context) { ctx.WriteString("|AfterExec1") } -func beegoAfterExec2(ctx *context.Context) { - ctx.WriteString("|AfterExec2") -} func beegoFinishRouter1(ctx *context.Context) { ctx.WriteString("|FinishRouter1") diff --git a/template.go b/template.go index cf41cb9b..264ce931 100644 --- a/template.go +++ b/template.go @@ -240,7 +240,7 @@ func getTplDeep(root string, fs http.FileSystem, file string, parent string, t * var fileAbsPath string var rParent string var err error - if filepath.HasPrefix(file, "../") { + if strings.HasPrefix(file, "../") { rParent = filepath.Join(filepath.Dir(parent), file) fileAbsPath = filepath.Join(root, filepath.Dir(parent), file) } else { @@ -248,10 +248,10 @@ func getTplDeep(root string, fs http.FileSystem, file string, parent string, t * fileAbsPath = filepath.Join(root, file) } f, err := fs.Open(fileAbsPath) - defer f.Close() if err != nil { panic("can't find template file:" + file) } + defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { return nil, [][]string{}, err diff --git a/templatefunc.go b/templatefunc.go index 8c1504aa..9ec2a9e8 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -172,7 +172,7 @@ func GetConfig(returnType, key string, defaultVal interface{}) (value interface{ case "DIY": value, err = AppConfig.DIY(key) default: - err = errors.New("Config keys must be of type String, Bool, Int, Int64, Float, or DIY") + err = errors.New("config keys must be of type String, Bool, Int, Int64, Float, or DIY") } if err != nil { diff --git a/templatefunc_test.go b/templatefunc_test.go index c7b8fbd3..e99ff880 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -197,7 +197,6 @@ func TestParseForm(t *testing.T) { func TestRenderForm(t *testing.T) { type user struct { ID int `form:"-"` - tag string `form:"tag"` Name interface{} `form:"username"` Age int `form:"age,text,年龄:"` Sex string From c3eca637fba319665b794a50b3197c76e90bfbae Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 19:10:23 +0800 Subject: [PATCH 027/112] no need gosimple --- .gosimpleignore | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .gosimpleignore diff --git a/.gosimpleignore b/.gosimpleignore deleted file mode 100644 index 84df9b95..00000000 --- a/.gosimpleignore +++ /dev/null @@ -1,4 +0,0 @@ -github.com/astaxie/beego/*/*:S1012 -github.com/astaxie/beego/*:S1012 -github.com/astaxie/beego/*/*:S1007 -github.com/astaxie/beego/*:S1007 \ No newline at end of file From 2956d33bab1dd95d80ccab213f604c8737d716a3 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 19:12:25 +0800 Subject: [PATCH 028/112] no need gosimple --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6755cac3..8c3252b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/) + - staticcheck -show-ignored $(go list ./... | grep -v /vendor/) - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s From 00264650b5c87fd2a287b4f4085a2519eb2d829f Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 19:29:53 +0800 Subject: [PATCH 029/112] modify travis and redis_sentinel test --- .travis.yml | 2 +- session/redis_sentinel/sess_redis_sentinel_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c3252b5..1bc896af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored $(go list ./... | grep -v /vendor/) + - staticcheck -show-ignored - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s diff --git a/session/redis_sentinel/sess_redis_sentinel_test.go b/session/redis_sentinel/sess_redis_sentinel_test.go index 851fe804..f4e2be5f 100644 --- a/session/redis_sentinel/sess_redis_sentinel_test.go +++ b/session/redis_sentinel/sess_redis_sentinel_test.go @@ -15,7 +15,7 @@ func TestRedisSentinel(t *testing.T) { Maxlifetime: 3600, Secure: false, CookieLifeTime: 3600, - ProviderConfig: "119.23.132.234:26379,100,,0,master", + ProviderConfig: "127.0.0.1:26379,100,,0,master", } globalSessions, _ := session.NewManager("redis_sentinel", sessionConfig) go globalSessions.GC() From f237ff049ab2410572df46b4dbcf83912a8ae9e6 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 19:45:32 +0800 Subject: [PATCH 030/112] redis_sentinel test ignore --- session/redis_sentinel/sess_redis_sentinel_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/session/redis_sentinel/sess_redis_sentinel_test.go b/session/redis_sentinel/sess_redis_sentinel_test.go index f4e2be5f..d5abc051 100644 --- a/session/redis_sentinel/sess_redis_sentinel_test.go +++ b/session/redis_sentinel/sess_redis_sentinel_test.go @@ -1,10 +1,11 @@ package redis_sentinel import ( - "github.com/astaxie/beego/session" "net/http" "net/http/httptest" "testing" + + "github.com/astaxie/beego/session" ) func TestRedisSentinel(t *testing.T) { @@ -15,9 +16,13 @@ func TestRedisSentinel(t *testing.T) { Maxlifetime: 3600, Secure: false, CookieLifeTime: 3600, - ProviderConfig: "127.0.0.1:26379,100,,0,master", + ProviderConfig: "127.0.0.1:6379,100,,0,master", + } + globalSessions, e := session.NewManager("redis_sentinel", sessionConfig) + if e != nil { + t.Log(e) + return } - globalSessions, _ := session.NewManager("redis_sentinel", sessionConfig) go globalSessions.GC() r, _ := http.NewRequest("GET", "/", nil) From abc9c38224293c51c1273f4516d12e1c560e01ed Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 20:04:30 +0800 Subject: [PATCH 031/112] ignore some staticcheck checks --- staticcheck.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 staticcheck.conf diff --git a/staticcheck.conf b/staticcheck.conf new file mode 100644 index 00000000..7803887f --- /dev/null +++ b/staticcheck.conf @@ -0,0 +1 @@ +checks = ["all", "-ST1017", "-U1000", "-ST1005","-S1034","-S1012","-SA4006","-ST1005","-SA6005","-SA1019"] \ No newline at end of file From 97713849a17674bfcc7e6ab2ca7581388836306a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 20:21:00 +0800 Subject: [PATCH 032/112] delete stackcheck config file and ignore some staticcheck checks --- .travis.yml | 2 +- session/redis_sentinel/sess_redis_sentinel_test.go | 1 + staticcheck.conf | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 staticcheck.conf diff --git a/.travis.yml b/.travis.yml index 1bc896af..d77f8048 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored + - staticcheck -show-ignored -checks "-ST1017", "-U1000", "-ST1005","-S1034","-S1012","-SA4006","-ST1003","-SA6005","-SA1019" - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s diff --git a/session/redis_sentinel/sess_redis_sentinel_test.go b/session/redis_sentinel/sess_redis_sentinel_test.go index d5abc051..fd4155c6 100644 --- a/session/redis_sentinel/sess_redis_sentinel_test.go +++ b/session/redis_sentinel/sess_redis_sentinel_test.go @@ -23,6 +23,7 @@ func TestRedisSentinel(t *testing.T) { t.Log(e) return } + //todo test if e==nil go globalSessions.GC() r, _ := http.NewRequest("GET", "/", nil) diff --git a/staticcheck.conf b/staticcheck.conf deleted file mode 100644 index 7803887f..00000000 --- a/staticcheck.conf +++ /dev/null @@ -1 +0,0 @@ -checks = ["all", "-ST1017", "-U1000", "-ST1005","-S1034","-S1012","-SA4006","-ST1005","-SA6005","-SA1019"] \ No newline at end of file From 5b42afa32480baeb17d932299f7951ab01f35bf3 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 20:30:05 +0800 Subject: [PATCH 033/112] modiyf staticcheck checks --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d77f8048..7465ceca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored -checks "-ST1017", "-U1000", "-ST1005","-S1034","-S1012","-SA4006","-ST1003","-SA6005","-SA1019" + - staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-ST1003,-SA6005,-SA1019" - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s From 2a579eb27c3a9a9ec06d402256bf06bc10413dde Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 20:41:07 +0800 Subject: [PATCH 034/112] staticcheck checks -ST1003 remove --- .travis.yml | 2 +- router.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7465ceca..8f44b5ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-ST1003,-SA6005,-SA1019" + - staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-SA6005,-SA1019" - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s diff --git a/router.go b/router.go index c5b618c3..851934a8 100644 --- a/router.go +++ b/router.go @@ -513,7 +513,7 @@ func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) stri controllerName := strings.Join(paths[:len(paths)-1], "/") methodName := paths[len(paths)-1] for m, t := range p.routers { - ok, url := p.getUrl(t, "/", controllerName, methodName, params, m) + ok, url := p.getURL(t, "/", controllerName, methodName, params, m) if ok { return url } @@ -521,17 +521,17 @@ func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) stri return "" } -func (p *ControllerRegister) getUrl(t *Tree, url, controllerName, methodName string, params map[string]string, httpMethod string) (bool, string) { +func (p *ControllerRegister) getURL(t *Tree, url, controllerName, methodName string, params map[string]string, httpMethod string) (bool, string) { for _, subtree := range t.fixrouters { u := path.Join(url, subtree.prefix) - ok, u := p.getUrl(subtree, u, controllerName, methodName, params, httpMethod) + ok, u := p.getURL(subtree, u, controllerName, methodName, params, httpMethod) if ok { return ok, u } } if t.wildcard != nil { u := path.Join(url, urlPlaceholder) - ok, u := p.getUrl(t.wildcard, u, controllerName, methodName, params, httpMethod) + ok, u := p.getURL(t.wildcard, u, controllerName, methodName, params, httpMethod) if ok { return ok, u } @@ -599,7 +599,7 @@ func (p *ControllerRegister) getUrl(t *Tree, url, controllerName, methodName str } var i int var startReg bool - regUrl := "" + regURL := "" for _, v := range strings.Trim(l.regexps.String(), "^$") { if v == '(' { startReg = true @@ -608,17 +608,17 @@ func (p *ControllerRegister) getUrl(t *Tree, url, controllerName, methodName str startReg = false if v, ok := params[l.wildcards[i]]; ok { delete(params, l.wildcards[i]) - regUrl = regUrl + v + regURL = regURL + v i++ } else { break } } else if !startReg { - regUrl = string(append([]rune(regUrl), v)) + regURL = string(append([]rune(regURL), v)) } } - if l.regexps.MatchString(regUrl) { - ps := strings.Split(regUrl, "/") + if l.regexps.MatchString(regURL) { + ps := strings.Split(regURL, "/") for _, p := range ps { url = strings.Replace(url, urlPlaceholder, p, 1) } From 0145fe348669e85057d75a0a3d32e151ff35d1cb Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 22 Jan 2019 20:52:06 +0800 Subject: [PATCH 035/112] remove SA1024 staticchek --- .travis.yml | 2 +- parser.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f44b5ea..3a3a6f66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ after_script: - rm -rf ./res/var/* script: - go test -v ./... - - staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-SA6005,-SA1019" + - staticcheck -show-ignored -checks "-ST1017,-U1000,-ST1005,-S1034,-S1012,-SA4006,-SA6005,-SA1019,-SA1024" - unconvert $(go list ./... | grep -v /vendor/) - ineffassign . - find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s diff --git a/parser.go b/parser.go index 9c509075..a8690274 100644 --- a/parser.go +++ b/parser.go @@ -259,9 +259,9 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { imports := []parsedImport{} for _, c := range lines { - t := strings.TrimSpace(strings.TrimPrefix(c.Text, "//")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) if strings.HasPrefix(t, "@Param") { - pv := getparams(strings.TrimSpace(strings.TrimPrefix(t, "@Param"))) + pv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Param"))) if len(pv) < 4 { logs.Error("Invalid @Param format. Needs at least 4 parameters") } @@ -286,7 +286,7 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { } for _, c := range lines { - t := strings.TrimSpace(strings.TrimPrefix(c.Text, "//")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) if strings.HasPrefix(t, "@Import") { iv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Import"))) if len(iv) == 0 || len(iv) > 2 { @@ -307,9 +307,9 @@ func parseComment(lines []*ast.Comment) (pcs []*parsedComment, err error) { filterLoop: for _, c := range lines { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) if strings.HasPrefix(t, "@Filter") { - fv := getparams(strings.TrimSpace(strings.TrimPrefix(t, "@Filter"))) + fv := getparams(strings.TrimSpace(strings.TrimLeft(t, "@Filter"))) if len(fv) < 3 { logs.Error("Invalid @Filter format. Needs at least 3 parameters") continue filterLoop @@ -349,9 +349,9 @@ filterLoop: pc.filters = filters pc.imports = imports - t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) if strings.HasPrefix(t, "@router") { - t := strings.TrimSpace(strings.TrimLeft(c.Text, "/")) + t := strings.TrimSpace(strings.TrimLeft(c.Text, "//")) matches := routeRegex.FindStringSubmatch(t) if len(matches) == 3 { pc.routerPath = matches[1] From a9ffc2a0783b6f8838028073c781a4b5fa56e04a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 23 Jan 2019 12:30:57 +0800 Subject: [PATCH 036/112] https://github.com/astaxie/beego/issues/3446 Use UTF-8 as the encoding of the "filename*" parameter, when present, because at least one existing implementation only implements that encoding. --- context/output.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/context/output.go b/context/output.go index 3e277ab2..8a1a1628 100644 --- a/context/output.go +++ b/context/output.go @@ -30,7 +30,8 @@ import ( "strconv" "strings" "time" - "gopkg.in/yaml.v2" + + yaml "gopkg.in/yaml.v2" ) // BeegoOutput does work for sending response header. @@ -203,7 +204,6 @@ func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, encoding bool) return output.Body(content) } - // YAML writes yaml to response body. func (output *BeegoOutput) YAML(data interface{}) error { output.Header("Content-Type", "application/x-yaml; charset=utf-8") @@ -288,7 +288,19 @@ func (output *BeegoOutput) Download(file string, filename ...string) { } else { fName = filepath.Base(file) } - output.Header("Content-Disposition", "attachment; filename="+url.PathEscape(fName)) + //https://tools.ietf.org/html/rfc6266#section-4.3 + fn := url.PathEscape(fName) + if fName == fn { + output.Header("Content-Disposition", "attachment; filename="+fn) + } else { + /** + The parameters "filename" and "filename*" differ only in that + "filename*" uses the encoding defined in [RFC5987], allowing the use + of characters not present in the ISO-8859-1 character set + ([ISO-8859-1]). + */ + output.Header("Content-Disposition", "attachment; filename*=utf-8''"+fn) + } output.Header("Content-Description", "File Transfer") output.Header("Content-Type", "application/octet-stream") output.Header("Content-Transfer-Encoding", "binary") From 1c893996c0af969d529274ecacaf0eb21fef424b Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 23 Jan 2019 12:36:14 +0800 Subject: [PATCH 037/112] improve the download func code --- context/output.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/context/output.go b/context/output.go index 8a1a1628..238dcf45 100644 --- a/context/output.go +++ b/context/output.go @@ -291,7 +291,7 @@ func (output *BeegoOutput) Download(file string, filename ...string) { //https://tools.ietf.org/html/rfc6266#section-4.3 fn := url.PathEscape(fName) if fName == fn { - output.Header("Content-Disposition", "attachment; filename="+fn) + fn = "filename=" + fn } else { /** The parameters "filename" and "filename*" differ only in that @@ -299,8 +299,9 @@ func (output *BeegoOutput) Download(file string, filename ...string) { of characters not present in the ISO-8859-1 character set ([ISO-8859-1]). */ - output.Header("Content-Disposition", "attachment; filename*=utf-8''"+fn) + fn = "filename=" + fName + "; filename*=utf-8''" + fn } + output.Header("Content-Disposition", "attachment; "+fn) output.Header("Content-Description", "File Transfer") output.Header("Content-Type", "application/octet-stream") output.Header("Content-Transfer-Encoding", "binary") From dc07fa70851f7784f1c9f88c8dc0c39694dc32aa Mon Sep 17 00:00:00 2001 From: "Iskander (Alex) Sharipov" Date: Thu, 24 Jan 2019 08:52:30 +0300 Subject: [PATCH 038/112] cache: remove excessive type assertions Assign type switch variable to get properly-typed value inside case clauses. Signed-off-by: Iskander Sharipov --- cache/memory.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cache/memory.go b/cache/memory.go index cb9802ab..e5b562f0 100644 --- a/cache/memory.go +++ b/cache/memory.go @@ -116,19 +116,19 @@ func (bc *MemoryCache) Incr(key string) error { if !ok { return errors.New("key not exist") } - switch itm.val.(type) { + switch val := itm.val.(type) { case int: - itm.val = itm.val.(int) + 1 + itm.val = val + 1 case int32: - itm.val = itm.val.(int32) + 1 + itm.val = val + 1 case int64: - itm.val = itm.val.(int64) + 1 + itm.val = val + 1 case uint: - itm.val = itm.val.(uint) + 1 + itm.val = val + 1 case uint32: - itm.val = itm.val.(uint32) + 1 + itm.val = val + 1 case uint64: - itm.val = itm.val.(uint64) + 1 + itm.val = val + 1 default: return errors.New("item val is not (u)int (u)int32 (u)int64") } @@ -143,28 +143,28 @@ func (bc *MemoryCache) Decr(key string) error { if !ok { return errors.New("key not exist") } - switch itm.val.(type) { + switch val := itm.val.(type) { case int: - itm.val = itm.val.(int) - 1 + itm.val = val - 1 case int64: - itm.val = itm.val.(int64) - 1 + itm.val = val - 1 case int32: - itm.val = itm.val.(int32) - 1 + itm.val = val - 1 case uint: - if itm.val.(uint) > 0 { - itm.val = itm.val.(uint) - 1 + if val > 0 { + itm.val = val - 1 } else { return errors.New("item val is less than 0") } case uint32: - if itm.val.(uint32) > 0 { - itm.val = itm.val.(uint32) - 1 + if val > 0 { + itm.val = val - 1 } else { return errors.New("item val is less than 0") } case uint64: - if itm.val.(uint64) > 0 { - itm.val = itm.val.(uint64) - 1 + if val > 0 { + itm.val = val - 1 } else { return errors.New("item val is less than 0") } From 12fdc04f1b2c9e9ea1c9c2a636ef71141f342818 Mon Sep 17 00:00:00 2001 From: Witaya Tospitakkul Date: Fri, 25 Jan 2019 00:15:40 +0700 Subject: [PATCH 039/112] fix: when parse post form it didnt parse fields which have same name but the first index is empty but another is not --- go.mod | 2 +- go.sum | 1 + templatefunc.go | 29 +++++++++++++++++++++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index a7e1194b..fbdec124 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,9 @@ module github.com/astaxie/beego require ( github.com/Knetic/govaluate v3.0.0+incompatible // indirect + github.com/OwnLocal/goes v1.0.0 github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542 - github.com/OwnLocal/goes v1.0.0 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 github.com/casbin/casbin v1.7.0 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 diff --git a/go.sum b/go.sum index fbe3a8c3..ab233162 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd h1:jZtX5jh5IOMu0fpOTC3ayh6QGSPJ/KWOv1lgPvbRw1M= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542 h1:nYXb+3jF6Oq/j8R/y90XrKpreCxIalBWfeyeKymgOPk= diff --git a/templatefunc.go b/templatefunc.go index 9ec2a9e8..eeb34cc6 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -85,24 +85,24 @@ func DateFormat(t time.Time, layout string) (datestring string) { var datePatterns = []string{ // year "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 - "y", "06", //A two digit representation of a year Examples: 99 or 03 + "y", "06", //A two digit representation of a year Examples: 99 or 03 // month - "m", "01", // Numeric representation of a month, with leading zeros 01 through 12 - "n", "1", // Numeric representation of a month, without leading zeros 1 through 12 - "M", "Jan", // A short textual representation of a month, three letters Jan through Dec + "m", "01", // Numeric representation of a month, with leading zeros 01 through 12 + "n", "1", // Numeric representation of a month, without leading zeros 1 through 12 + "M", "Jan", // A short textual representation of a month, three letters Jan through Dec "F", "January", // A full textual representation of a month, such as January or March January through December // day "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31 - "j", "2", // Day of the month without leading zeros 1 to 31 + "j", "2", // Day of the month without leading zeros 1 to 31 // week - "D", "Mon", // A textual representation of a day, three letters Mon through Sun + "D", "Mon", // A textual representation of a day, three letters Mon through Sun "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday // time - "g", "3", // 12-hour format of an hour without leading zeros 1 through 12 + "g", "3", // 12-hour format of an hour without leading zeros 1 through 12 "G", "15", // 24-hour format of an hour without leading zeros 0 through 23 "h", "03", // 12-hour format of an hour with leading zeros 01 through 12 "H", "15", // 24-hour format of an hour with leading zeros 00 through 23 @@ -297,8 +297,21 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e tag = tags[0] } + if fieldT.Type.Kind() == reflect.Slice { + found := false + for _, v := range form[tag] { + if len(v) != 0 { + found = true + break + } + } + if !found { + continue + } + } + value := form.Get(tag) - if len(value) == 0 { + if (fieldT.Type.Kind() != reflect.Slice) && len(value) == 0 { continue } From 920207f72c20161bbb45e0fb8d509d2165601df7 Mon Sep 17 00:00:00 2001 From: Witaya Tospitakkul Date: Fri, 25 Jan 2019 00:38:14 +0700 Subject: [PATCH 040/112] add testing for ParseForm when form post has a slice in body --- templatefunc_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/templatefunc_test.go b/templatefunc_test.go index e99ff880..6c1d9d72 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -111,7 +111,7 @@ func TestHtmlunquote(t *testing.T) { func TestParseForm(t *testing.T) { type ExtendInfo struct { - Hobby string `form:"hobby"` + Hobby []string `form:"hobby"` Memo string } @@ -146,7 +146,7 @@ func TestParseForm(t *testing.T) { "date": []string{"2014-11-12"}, "organization": []string{"beego"}, "title": []string{"CXO"}, - "hobby": []string{"Basketball"}, + "hobby": []string{"Basketball", "Football"}, "memo": []string{"nothing"}, } if err := ParseForm(form, u); err == nil { @@ -186,8 +186,11 @@ func TestParseForm(t *testing.T) { if u.Title != "CXO" { t.Errorf("Title should equal `CXO`, but got `%v`", u.Title) } - if u.Hobby != "Basketball" { - t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby) + if u.Hobby[0] != "Basketball" { + t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby[0]) + } + if u.Hobby[1] != "Football" { + t.Errorf("Hobby should equal `Football`, but got `%v`", u.Hobby[1]) } if len(u.Memo) != 0 { t.Errorf("Memo's length should equal 0 but got %v", len(u.Memo)) From bd1b421491d1d79f92b55344fc45341a264be624 Mon Sep 17 00:00:00 2001 From: Witaya Tospitakkul Date: Fri, 25 Jan 2019 09:04:01 +0700 Subject: [PATCH 041/112] fix: adding test for issue due to testing is not reflect changed --- templatefunc_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/templatefunc_test.go b/templatefunc_test.go index 6c1d9d72..b4c19c2e 100644 --- a/templatefunc_test.go +++ b/templatefunc_test.go @@ -146,7 +146,7 @@ func TestParseForm(t *testing.T) { "date": []string{"2014-11-12"}, "organization": []string{"beego"}, "title": []string{"CXO"}, - "hobby": []string{"Basketball", "Football"}, + "hobby": []string{"", "Basketball", "Football"}, "memo": []string{"nothing"}, } if err := ParseForm(form, u); err == nil { @@ -186,11 +186,14 @@ func TestParseForm(t *testing.T) { if u.Title != "CXO" { t.Errorf("Title should equal `CXO`, but got `%v`", u.Title) } - if u.Hobby[0] != "Basketball" { - t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby[0]) + if u.Hobby[0] != "" { + t.Errorf("Hobby should equal ``, but got `%v`", u.Hobby[0]) } - if u.Hobby[1] != "Football" { - t.Errorf("Hobby should equal `Football`, but got `%v`", u.Hobby[1]) + if u.Hobby[1] != "Basketball" { + t.Errorf("Hobby should equal `Basketball`, but got `%v`", u.Hobby[1]) + } + if u.Hobby[2] != "Football" { + t.Errorf("Hobby should equal `Football`, but got `%v`", u.Hobby[2]) } if len(u.Memo) != 0 { t.Errorf("Memo's length should equal 0 but got %v", len(u.Memo)) From 3bd7614ade4f0b9d5cd9d7f2da972a4c370805b8 Mon Sep 17 00:00:00 2001 From: Witaya Tospitakkul Date: Fri, 25 Jan 2019 11:00:24 +0700 Subject: [PATCH 042/112] refactoring code after discussion --- templatefunc.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/templatefunc.go b/templatefunc.go index eeb34cc6..d302cb64 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -297,24 +297,18 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e tag = tags[0] } - if fieldT.Type.Kind() == reflect.Slice { - found := false - for _, v := range form[tag] { - if len(v) != 0 { - found = true - break - } - } - if !found { + formValues := form[tag] + var value string + if len(formValues) == 0 { + continue + } + if len(formValues) == 1 { + value = formValues[0] + if value == "" { continue } } - value := form.Get(tag) - if (fieldT.Type.Kind() != reflect.Slice) && len(value) == 0 { - continue - } - switch fieldT.Type.Kind() { case reflect.Bool: if strings.ToLower(value) == "on" || strings.ToLower(value) == "1" || strings.ToLower(value) == "yes" { From 8506194d2c887bb1b56fb639cb6c2da7a5c9d8df Mon Sep 17 00:00:00 2001 From: DennisMao Date: Fri, 25 Jan 2019 19:08:39 +0800 Subject: [PATCH 043/112] fix panic cause by the map --- cache/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/file.go b/cache/file.go index 691ce7cd..1926268a 100644 --- a/cache/file.go +++ b/cache/file.go @@ -65,7 +65,7 @@ func NewFileCache() Cache { // the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0} func (fc *FileCache) StartAndGC(config string) error { - var cfg map[string]string + cfg := make(map[string]string) json.Unmarshal([]byte(config), &cfg) if _, ok := cfg["CachePath"]; !ok { cfg["CachePath"] = FileCachePath From 6ca0978777bd8e796376162520fc3ea561b644c8 Mon Sep 17 00:00:00 2001 From: "Iskander (Alex) Sharipov" Date: Sat, 26 Jan 2019 14:13:53 +0300 Subject: [PATCH 044/112] replace unchecked Compile calls with MustCompile For constant patterns and especially when errors are ignored, `regexp.MustCompile` is a better choice than `regexp.Compile`. Signed-off-by: Iskander Sharipov --- templatefunc.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templatefunc.go b/templatefunc.go index 9ec2a9e8..7a8d5588 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -55,21 +55,21 @@ func Substr(s string, start, length int) string { // HTML2str returns escaping text convert from html. func HTML2str(html string) string { - re, _ := regexp.Compile(`\<[\S\s]+?\>`) + re := regexp.MustCompile(`\<[\S\s]+?\>`) html = re.ReplaceAllStringFunc(html, strings.ToLower) //remove STYLE - re, _ = regexp.Compile(`\`) + re = regexp.MustCompile(`\`) html = re.ReplaceAllString(html, "") //remove SCRIPT - re, _ = regexp.Compile(`\`) + re = regexp.MustCompile(`\`) html = re.ReplaceAllString(html, "") - re, _ = regexp.Compile(`\<[\S\s]+?\>`) + re = regexp.MustCompile(`\<[\S\s]+?\>`) html = re.ReplaceAllString(html, "\n") - re, _ = regexp.Compile(`\s{2,}`) + re = regexp.MustCompile(`\s{2,}`) html = re.ReplaceAllString(html, "\n") return strings.TrimSpace(html) From af4464ce585434015ab51bcf21ab9da8a7a448f4 Mon Sep 17 00:00:00 2001 From: zav8 Date: Fri, 1 Feb 2019 15:27:10 +0800 Subject: [PATCH 045/112] add support for pointer fields of structs to method QueryRows() --- orm/orm_raw.go | 8 ++++++++ orm/orm_test.go | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/orm/orm_raw.go b/orm/orm_raw.go index 27651fe4..3325a7ea 100644 --- a/orm/orm_raw.go +++ b/orm/orm_raw.go @@ -191,6 +191,14 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { ind.Set(reflect.Indirect(reflect.ValueOf(sc))) } } + + case reflect.Ptr: + if value == nil { + ind.Set(reflect.Zero(ind.Type())) + break + } + ind.Set(reflect.New(ind.Type().Elem())) + o.setFieldValue(reflect.Indirect(ind), value) } } diff --git a/orm/orm_test.go b/orm/orm_test.go index 4f499a7c..0e2bf732 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -458,6 +458,14 @@ func TestNullDataTypes(t *testing.T) { throwFail(t, AssertIs((*d.TimePtr).UTC().Format(testTime), timePtr.UTC().Format(testTime))) throwFail(t, AssertIs((*d.DatePtr).UTC().Format(testDate), datePtr.UTC().Format(testDate))) throwFail(t, AssertIs((*d.DateTimePtr).UTC().Format(testDateTime), dateTimePtr.UTC().Format(testDateTime))) + + // test support for pointer fields using RawSeter.QueryRows() + var dnList []*DataNull + Q := dDbBaser.TableQuote() + num, err = dORM.Raw(fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q), 3).QueryRows(&dnList) + throwFailNow(t, err) + equal := reflect.DeepEqual(*dnList[0], d) + throwFailNow(t, AssertIs(equal, true)) } func TestDataCustomTypes(t *testing.T) { From 7abdb05f913424ee0ce21e736eec3e3dc20d42d8 Mon Sep 17 00:00:00 2001 From: zav8 Date: Fri, 1 Feb 2019 15:39:40 +0800 Subject: [PATCH 046/112] little fix --- orm/orm_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/orm/orm_test.go b/orm/orm_test.go index 0e2bf732..bdb430b6 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -464,6 +464,7 @@ func TestNullDataTypes(t *testing.T) { Q := dDbBaser.TableQuote() num, err = dORM.Raw(fmt.Sprintf("SELECT * FROM %sdata_null%s where id=?", Q, Q), 3).QueryRows(&dnList) throwFailNow(t, err) + throwFailNow(t, AssertIs(num, 1)) equal := reflect.DeepEqual(*dnList[0], d) throwFailNow(t, AssertIs(equal, true)) } From d7430eb92171f6066745705090cf617b3eea3870 Mon Sep 17 00:00:00 2001 From: Sergey Date: Mon, 4 Feb 2019 11:03:27 +0500 Subject: [PATCH 047/112] SessionRead: check of the length for input sid variable --- session/sess_file.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/session/sess_file.go b/session/sess_file.go index c089dade..db143522 100644 --- a/session/sess_file.go +++ b/session/sess_file.go @@ -19,6 +19,7 @@ import ( "io/ioutil" "net/http" "os" + "errors" "path" "path/filepath" "strings" @@ -131,6 +132,9 @@ func (fp *FileProvider) SessionRead(sid string) (Store, error) { if strings.ContainsAny(sid, "./") { return nil, nil } + if len(sid) < 2 { + return nil, errors.New("length of the sid is less than 2") + } filepder.lock.Lock() defer filepder.lock.Unlock() From 67666dbe0f982a8edd1bb9a03234a2a4297ac614 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Sat, 9 Feb 2019 17:18:59 +0300 Subject: [PATCH 048/112] all: simplify boolean expressions - !(a == b) => a != b - !(a != b) => a == b Signed-off-by: Iskander Sharipov --- cache/memcache/memcache.go | 2 +- session/ledis/ledis_session.go | 2 +- session/mysql/sess_mysql.go | 2 +- session/postgres/sess_postgresql.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cache/memcache/memcache.go b/cache/memcache/memcache.go index 0624f5fa..19116bfa 100644 --- a/cache/memcache/memcache.go +++ b/cache/memcache/memcache.go @@ -146,7 +146,7 @@ func (rc *Cache) IsExist(key string) bool { } } _, err := rc.conn.Get(key) - return !(err != nil) + return err == nil } // ClearAll clear all cached in memcache. diff --git a/session/ledis/ledis_session.go b/session/ledis/ledis_session.go index 77685d1e..c0d4bf82 100644 --- a/session/ledis/ledis_session.go +++ b/session/ledis/ledis_session.go @@ -133,7 +133,7 @@ func (lp *Provider) SessionRead(sid string) (session.Store, error) { // SessionExist check ledis session exist by sid func (lp *Provider) SessionExist(sid string) bool { count, _ := c.Exists([]byte(sid)) - return !(count == 0) + return count != 0 } // SessionRegenerate generate new sid for ledis session diff --git a/session/mysql/sess_mysql.go b/session/mysql/sess_mysql.go index 4c9251e7..301353ab 100644 --- a/session/mysql/sess_mysql.go +++ b/session/mysql/sess_mysql.go @@ -170,7 +170,7 @@ func (mp *Provider) SessionExist(sid string) bool { row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid) var sessiondata []byte err := row.Scan(&sessiondata) - return !(err == sql.ErrNoRows) + return err != sql.ErrNoRows } // SessionRegenerate generate new sid for mysql session diff --git a/session/postgres/sess_postgresql.go b/session/postgres/sess_postgresql.go index ffc27def..0b8b9645 100644 --- a/session/postgres/sess_postgresql.go +++ b/session/postgres/sess_postgresql.go @@ -184,7 +184,7 @@ func (mp *Provider) SessionExist(sid string) bool { row := c.QueryRow("select session_data from session where session_key=$1", sid) var sessiondata []byte err := row.Scan(&sessiondata) - return !(err == sql.ErrNoRows) + return err != sql.ErrNoRows } // SessionRegenerate generate new sid for postgresql session From c998e52cc03dc244b4d6f6fdf60b5a886d9598a9 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Sun, 10 Feb 2019 20:37:43 +0300 Subject: [PATCH 049/112] config/yaml: s/bytes.NewBuffer/bytes.NewReader/ When io.Reader is required out of []byte, it's better to use bytes.NewReader than bytes.NewBuffer. Signed-off-by: Iskander Sharipov --- config/yaml/yaml.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index 7bf1335c..5def2da3 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -97,7 +97,7 @@ func parseYML(buf []byte) (cnf map[string]interface{}, err error) { } } - data, err := goyaml2.Read(bytes.NewBuffer(buf)) + data, err := goyaml2.Read(bytes.NewReader(buf)) if err != nil { log.Println("Goyaml2 ERR>", string(buf), err) return From ba17bdd3669b359f291abb880a8e2a2fdc329f11 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Tue, 12 Feb 2019 18:05:29 +0800 Subject: [PATCH 050/112] add ignore auto_now_add field when update --- orm/db.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/orm/db.go b/orm/db.go index dfaa5f1d..e488a5ab 100644 --- a/orm/db.go +++ b/orm/db.go @@ -621,6 +621,25 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. return 0, err } + var find bool + var index int + for i, col := range setNames { + if mi.fields.GetByColumn(col).autoNowAdd { + index = i + find = true + } + } + + if find { + newSetNames := make([]string, 0, 0) + newSetNames = append(setNames[0:index], setNames[index+1:]...) + setNames = newSetNames + newSetValues := make([]interface{}, 0, 0) + newSetValues = append(setValues[0:index], setValues[index+1:]...) + setValues = newSetValues + + } + setValues = append(setValues, pkValue) Q := d.ins.TableQuote() From 2fefd8cbbfd2141361f4d74bad24c19b724d8fbd Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Tue, 12 Feb 2019 18:53:34 +0800 Subject: [PATCH 051/112] update len --- orm/db.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orm/db.go b/orm/db.go index e488a5ab..8e7e93bb 100644 --- a/orm/db.go +++ b/orm/db.go @@ -631,10 +631,10 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. } if find { - newSetNames := make([]string, 0, 0) + newSetNames := make([]string, 0, len(setNames)-1) newSetNames = append(setNames[0:index], setNames[index+1:]...) setNames = newSetNames - newSetValues := make([]interface{}, 0, 0) + newSetValues := make([]interface{}, 0, len(setNames)-1) newSetValues = append(setValues[0:index], setValues[index+1:]...) setValues = newSetValues From 65f587d5e96f34f91e7b576e7890b98bc56d3553 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Tue, 12 Feb 2019 19:05:22 +0800 Subject: [PATCH 052/112] fix ineffectual assignment --- orm/db.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/orm/db.go b/orm/db.go index 8e7e93bb..2719dff7 100644 --- a/orm/db.go +++ b/orm/db.go @@ -632,10 +632,12 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. if find { newSetNames := make([]string, 0, len(setNames)-1) - newSetNames = append(setNames[0:index], setNames[index+1:]...) + newSetNames = append(newSetNames, setNames[0:index]...) + newSetNames = append(newSetNames, setNames[index+1:]...) setNames = newSetNames newSetValues := make([]interface{}, 0, len(setNames)-1) - newSetValues = append(setValues[0:index], setValues[index+1:]...) + newSetValues = append(newSetValues, setValues[0:index]...) + newSetValues = append(newSetValues, setValues[index+1:]...) setValues = newSetValues } From ddcd28e67f23da83eb8e64fa3e45b16451c82291 Mon Sep 17 00:00:00 2001 From: Joseph Edwards Van Riper III Date: Tue, 12 Feb 2019 13:00:11 -0500 Subject: [PATCH 053/112] APIBaiscAuth is misspelling of APIBasicAuth Corrected APIBaiscAuth to APIBasicAuth. Maintained old name (forwarding to new one) for those still using the previous API function name. --- plugins/apiauth/apiauth.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/apiauth/apiauth.go b/plugins/apiauth/apiauth.go index f816029c..aa8c1960 100644 --- a/plugins/apiauth/apiauth.go +++ b/plugins/apiauth/apiauth.go @@ -72,8 +72,8 @@ import ( // AppIDToAppSecret is used to get appsecret throw appid type AppIDToAppSecret func(string) string -// APIBaiscAuth use the basic appid/appkey as the AppIdToAppSecret -func APIBaiscAuth(appid, appkey string) beego.FilterFunc { +// APIBasicAuth use the basic appid/appkey as the AppIdToAppSecret +func APIBasicAuth(appid, appkey string) beego.FilterFunc { ft := func(aid string) string { if aid == appid { return appkey @@ -83,6 +83,11 @@ func APIBaiscAuth(appid, appkey string) beego.FilterFunc { return APISecretAuth(ft, 300) } +// APIBaiscAuth calls APIBasicAuth for previous callers +func APIBaiscAuth(appid, appkey string) beego.FilterFunc { + return APIBaiscAuth(appid, appkey) +} + // APISecretAuth use AppIdToAppSecret verify and func APISecretAuth(f AppIDToAppSecret, timeout int) beego.FilterFunc { return func(ctx *context.Context) { From 8995b291a9ca44029f590f79525cfeeee29ff126 Mon Sep 17 00:00:00 2001 From: Waleed Gadelkareem Date: Thu, 14 Feb 2019 16:29:26 +0100 Subject: [PATCH 054/112] Make LogAccess public --- controller.go | 2 +- error.go | 2 +- router.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controller.go b/controller.go index 7859681f..9c605760 100644 --- a/controller.go +++ b/controller.go @@ -291,7 +291,7 @@ func (c *Controller) viewPath() string { // Redirect sends the redirection response to url with status code. func (c *Controller) Redirect(url string, code int) { - logAccess(c.Ctx, nil, code) + LogAccess(c.Ctx, nil, code) c.Ctx.Redirect(code, url) } diff --git a/error.go b/error.go index 727830df..e5e9fd47 100644 --- a/error.go +++ b/error.go @@ -435,7 +435,7 @@ func exception(errCode string, ctx *context.Context) { func executeError(err *errorInfo, ctx *context.Context, code int) { //make sure to log the error in the access log - logAccess(ctx, nil, code) + LogAccess(ctx, nil, code) if err.errorType == errorTypeHandler { ctx.ResponseWriter.WriteHeader(code) diff --git a/router.go b/router.go index 851934a8..c5d0cda4 100644 --- a/router.go +++ b/router.go @@ -889,7 +889,7 @@ Admin: statusCode = 200 } - logAccess(context, &startTime, statusCode) + LogAccess(context, &startTime, statusCode) timeDur := time.Since(startTime) context.ResponseWriter.Elapsed = timeDur @@ -980,7 +980,7 @@ func toURL(params map[string]string) string { return strings.TrimRight(u, "&") } -func logAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) { +func LogAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) { //Skip logging if AccessLogs config is false if !BConfig.Log.AccessLogs { return From 94ed35e781d54833b27c13c2e4ba0f48932f604f Mon Sep 17 00:00:00 2001 From: Nedzad Smajic Date: Sat, 23 Feb 2019 22:49:32 +0100 Subject: [PATCH 055/112] Register .gohtml extension Goland as of 2018.3 seems to support only '.tpl.gohtml" and ".gohtml" templates. The regular ".tpl" templates will be rendered as plain text files which is not acceptable. --- template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template.go b/template.go index 264ce931..59875be7 100644 --- a/template.go +++ b/template.go @@ -38,7 +38,7 @@ var ( beeViewPathTemplates = make(map[string]map[string]*template.Template) templatesLock sync.RWMutex // beeTemplateExt stores the template extension which will build - beeTemplateExt = []string{"tpl", "html"} + beeTemplateExt = []string{"tpl", "html", "gohtml"} // beeTemplatePreprocessors stores associations of extension -> preprocessor handler beeTemplateEngines = map[string]templatePreProcessor{} beeTemplateFS = defaultFSFunc From 8454e8417e63125417a80f349f6528d4d234b885 Mon Sep 17 00:00:00 2001 From: grahamjamesaddis Date: Fri, 1 Mar 2019 11:27:32 +0000 Subject: [PATCH 056/112] Allow forked beego project to pass travis ci builds --- .travis.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a3a6f66..2bd0f004 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,19 @@ services: - postgresql - memcached env: - - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - - ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" + global: + - GO_REPO_FULLNAME="github.com/astaxie/beego" + matrix: + - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db + - ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" before_install: + # link the local repo with ${GOPATH}/src// + - GO_REPO_NAMESPACE=${GO_REPO_FULLNAME%/*} + # relies on GOPATH to contain only one directory... + - mkdir -p ${GOPATH}/src/${GO_REPO_NAMESPACE} + - ln -sv ${TRAVIS_BUILD_DIR} ${GOPATH}/src/${GO_REPO_FULLNAME} + - cd ${GOPATH}/src/${GO_REPO_FULLNAME} + # get and build ssdb - git clone git://github.com/ideawu/ssdb.git - cd ssdb - make From aba51d99a18eede16aba81def3de68d1a6c4c5db Mon Sep 17 00:00:00 2001 From: hellomrlee Date: Mon, 4 Mar 2019 11:05:29 +0800 Subject: [PATCH 057/112] spelling mistake of word "Header" --- grace/grace.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grace/grace.go b/grace/grace.go index 5a8bc3b8..fb0cb7bb 100644 --- a/grace/grace.go +++ b/grace/grace.go @@ -78,7 +78,7 @@ var ( DefaultReadTimeOut time.Duration // DefaultWriteTimeOut is the HTTP Write timeout DefaultWriteTimeOut time.Duration - // DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit + // DefaultMaxHeaderBytes is the Max HTTP Header size, default is 0, no limit DefaultMaxHeaderBytes int // DefaultTimeout is the shutdown server's timeout. default is 60s DefaultTimeout = 60 * time.Second From 52f8ccd06c034d61fb2038997211ce8d6d4fa609 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Thu, 7 Mar 2019 17:15:30 +0800 Subject: [PATCH 058/112] TestToJson bug fixed --- httplib/httplib_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/httplib/httplib_test.go b/httplib/httplib_test.go index 8970b764..7314ae01 100644 --- a/httplib/httplib_test.go +++ b/httplib/httplib_test.go @@ -206,10 +206,16 @@ func TestToJson(t *testing.T) { t.Fatal(err) } t.Log(ip.Origin) - - if n := strings.Count(ip.Origin, "."); n != 3 { + ips := strings.Split(ip.Origin, ",") + if len(ips) == 0 { t.Fatal("response is not valid ip") } + for i := range ips { + if net.ParseIP(strings.TrimSpace(ips[i])).To4() == nil { + t.Fatal("response is not valid ip") + } + } + } func TestToFile(t *testing.T) { From 6dd5171fdfd9fd2e002cb4ce1372d75cfaf6032a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 8 Mar 2019 11:08:39 +0800 Subject: [PATCH 059/112] logger color function refactor,easy to read and run more quickly --- logs/logger.go | 61 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/logs/logger.go b/logs/logger.go index 428d3aa0..b6f0c86b 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "os" + "runtime" "sync" "time" ) @@ -33,7 +34,7 @@ func newLogWriter(wr io.Writer) *logWriter { func (lg *logWriter) println(when time.Time, msg string) { lg.Lock() - h, _, _:= formatTimeHeader(when) + h, _, _ := formatTimeHeader(when) lg.writer.Write(append(append(h, msg...), '\n')) lg.Unlock() } @@ -146,21 +147,50 @@ var ( reset = string([]byte{27, 91, 48, 109}) ) +var once sync.Once +var colorMap map[string]string + +func initColor() { + if runtime.GOOS == "windows" { + green = w32Green + white = w32White + yellow = w32Yellow + red = w32Red + blue = w32Blue + magenta = w32Magenta + cyan = w32Cyan + } + colorMap = map[string]string{ + "green": green, + "white": white, + "yellow": yellow, + "red": red, + "GET": blue, + "POST": cyan, + "PUT": yellow, + "DELETE": red, + "PATCH": green, + "HEAD": magenta, + "OPTIONS": white, + } +} + // ColorByStatus return color by http code // 2xx return Green // 3xx return White // 4xx return Yellow // 5xx return Red func ColorByStatus(cond bool, code int) string { + once.Do(initColor) switch { case code >= 200 && code < 300: - return map[bool]string{true: green, false: w32Green}[cond] + return colorMap["green"] case code >= 300 && code < 400: - return map[bool]string{true: white, false: w32White}[cond] + return colorMap["white"] case code >= 400 && code < 500: - return map[bool]string{true: yellow, false: w32Yellow}[cond] + return colorMap["yellow"] default: - return map[bool]string{true: red, false: w32Red}[cond] + return colorMap["red"] } } @@ -173,24 +203,11 @@ func ColorByStatus(cond bool, code int) string { // HEAD return Magenta // OPTIONS return WHITE func ColorByMethod(cond bool, method string) string { - switch method { - case "GET": - return map[bool]string{true: blue, false: w32Blue}[cond] - case "POST": - return map[bool]string{true: cyan, false: w32Cyan}[cond] - case "PUT": - return map[bool]string{true: yellow, false: w32Yellow}[cond] - case "DELETE": - return map[bool]string{true: red, false: w32Red}[cond] - case "PATCH": - return map[bool]string{true: green, false: w32Green}[cond] - case "HEAD": - return map[bool]string{true: magenta, false: w32Magenta}[cond] - case "OPTIONS": - return map[bool]string{true: white, false: w32White}[cond] - default: - return reset + once.Do(initColor) + if c := colorMap[method]; c != "" { + return c } + return reset } // Guard Mutex to guarantee atomic of W32Debug(string) function From 4a5e10852775164ae03a8cfffe5b86a1f11f018a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 8 Mar 2019 11:50:30 +0800 Subject: [PATCH 060/112] logger color function refactor,easy to read and run more quickly --- logs/logger.go | 8 ++++++-- router.go | 37 ++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/logs/logger.go b/logs/logger.go index b6f0c86b..c744d45c 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -180,7 +180,7 @@ func initColor() { // 3xx return White // 4xx return Yellow // 5xx return Red -func ColorByStatus(cond bool, code int) string { +func ColorByStatus(code int) string { once.Do(initColor) switch { case code >= 200 && code < 300: @@ -202,7 +202,7 @@ func ColorByStatus(cond bool, code int) string { // PATCH return Green // HEAD return Magenta // OPTIONS return WHITE -func ColorByMethod(cond bool, method string) string { +func ColorByMethod(method string) string { once.Do(initColor) if c := colorMap[method]; c != "" { return c @@ -210,6 +210,10 @@ func ColorByMethod(cond bool, method string) string { return reset } +func ResetColor() string { + return reset +} + // Guard Mutex to guarantee atomic of W32Debug(string) function var mu sync.Mutex diff --git a/router.go b/router.go index c5d0cda4..946635d9 100644 --- a/router.go +++ b/router.go @@ -900,34 +900,29 @@ Admin: } if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, pattern, statusCode) { + routerName := "" if runRouter != nil { - go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur) - } else { - go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, "", timeDur) + routerName = runRouter.Name() } + go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, routerName, timeDur) } } if BConfig.RunMode == DEV && !BConfig.Log.AccessLogs { - var devInfo string - iswin := (runtime.GOOS == "windows") - statusColor := logs.ColorByStatus(iswin, statusCode) - methodColor := logs.ColorByMethod(iswin, r.Method) - resetColor := logs.ColorByMethod(iswin, "") - if findRouter { - if routerInfo != nil { - devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s r:%s", context.Input.IP(), statusColor, statusCode, - resetColor, timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path, - routerInfo.pattern) - } else { - devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor, - timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path) - } - } else { - devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor, - timeDur.String(), "nomatch", methodColor, r.Method, resetColor, r.URL.Path) + match := map[bool]string{true: "match", false: "nomatch"} + devInfo := fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", + context.Input.IP(), + logs.ColorByStatus(statusCode), statusCode, logs.ResetColor(), + timeDur.String(), + match[findRouter], + logs.ColorByMethod(r.Method), r.Method, logs.ResetColor(), + r.URL.Path) + if routerInfo != nil { + devInfo += fmt.Sprintf(" r:%s", routerInfo.pattern) } - if iswin { + + //todo one logger enough,in fact no need to separate logger into windows and others + if runtime.GOOS == "windows" { logs.W32Debug(devInfo) } else { logs.Debug(devInfo) From 8432a1c758eef59cfd1f3ebda8209a5e9bf3a377 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 8 Mar 2019 12:10:57 +0800 Subject: [PATCH 061/112] better comment for color map --- logs/logger.go | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/logs/logger.go b/logs/logger.go index c744d45c..cf793cc0 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -161,10 +161,12 @@ func initColor() { cyan = w32Cyan } colorMap = map[string]string{ - "green": green, - "white": white, - "yellow": yellow, - "red": red, + //by color + "green": green, + "white": white, + "yellow": yellow, + "red": red, + //by method "GET": blue, "POST": cyan, "PUT": yellow, @@ -195,13 +197,6 @@ func ColorByStatus(code int) string { } // ColorByMethod return color by http code -// GET return Blue -// POST return Cyan -// PUT return Yellow -// DELETE return Red -// PATCH return Green -// HEAD return Magenta -// OPTIONS return WHITE func ColorByMethod(method string) string { once.Do(initColor) if c := colorMap[method]; c != "" { From 121fab61f1afc3434544dba303027d48abf2b092 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 8 Mar 2019 12:18:45 +0800 Subject: [PATCH 062/112] ResetColor function --- logs/logger.go | 1 + 1 file changed, 1 insertion(+) diff --git a/logs/logger.go b/logs/logger.go index cf793cc0..cdcd63e9 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -205,6 +205,7 @@ func ColorByMethod(method string) string { return reset } +// ResetColor return reset color func ResetColor() string { return reset } From 93485df3d2e193d42d411349c998598bd2155734 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 8 Mar 2019 14:42:06 +0800 Subject: [PATCH 063/112] color should be false by default otherwise the http logger's color would be wrong --- logs/console.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logs/console.go b/logs/console.go index e75f2a1b..43ff417a 100644 --- a/logs/console.go +++ b/logs/console.go @@ -56,7 +56,7 @@ func NewConsole() Logger { cw := &consoleWriter{ lg: newLogWriter(os.Stdout), Level: LevelDebug, - Colorful: runtime.GOOS != "windows", + Colorful: false, } return cw } From 578440a18de7990e37a47e9b13349387952f9b9c Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 12:09:41 +0800 Subject: [PATCH 064/112] add ansicolor to beego --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3a3a6f66..92e53577 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ install: - go get github.com/casbin/casbin - go get github.com/elazarl/go-bindata-assetfs - go get github.com/OwnLocal/goes + - go get github.com/shiena/ansicolor - go get -u honnef.co/go/tools/cmd/staticcheck - go get -u github.com/mdempsky/unconvert - go get -u github.com/gordonklaus/ineffassign From 661dcbb6cafeeb9e7451f23da1fae227ba3260e7 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 12:11:25 +0800 Subject: [PATCH 065/112] router logger modify --- router.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/router.go b/router.go index 946635d9..7fae248e 100644 --- a/router.go +++ b/router.go @@ -21,7 +21,6 @@ import ( "path" "path/filepath" "reflect" - "runtime" "strconv" "strings" "sync" @@ -921,12 +920,7 @@ Admin: devInfo += fmt.Sprintf(" r:%s", routerInfo.pattern) } - //todo one logger enough,in fact no need to separate logger into windows and others - if runtime.GOOS == "windows" { - logs.W32Debug(devInfo) - } else { - logs.Debug(devInfo) - } + logs.Debug(devInfo) } // Call WriteHeader if status code has been set changed if context.Output.Status != 0 { From 0ba77a0d8725d62980b25e7acd4ec40f0c9945cd Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 12:12:59 +0800 Subject: [PATCH 066/112] colorful is the switch to level label --- logs/console.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/logs/console.go b/logs/console.go index 43ff417a..73c623f5 100644 --- a/logs/console.go +++ b/logs/console.go @@ -17,8 +17,10 @@ package logs import ( "encoding/json" "os" - "runtime" + "strings" "time" + + "github.com/shiena/ansicolor" ) // brush is a color join function @@ -54,9 +56,9 @@ type consoleWriter struct { // NewConsole create ConsoleWriter returning as LoggerInterface. func NewConsole() Logger { cw := &consoleWriter{ - lg: newLogWriter(os.Stdout), + lg: newLogWriter(ansicolor.NewAnsiColorWriter(os.Stdout)), Level: LevelDebug, - Colorful: false, + Colorful: true, } return cw } @@ -67,11 +69,7 @@ func (c *consoleWriter) Init(jsonConfig string) error { if len(jsonConfig) == 0 { return nil } - err := json.Unmarshal([]byte(jsonConfig), c) - if runtime.GOOS == "windows" { - c.Colorful = false - } - return err + return json.Unmarshal([]byte(jsonConfig), c) } // WriteMsg write message in console. @@ -80,7 +78,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { return nil } if c.Colorful { - msg = colors[level](msg) + msg = strings.Replace(msg, levelPrefix[level], colors[level](levelPrefix[level]), 1) } c.lg.println(when, msg) return nil From c0fae547e9f204c9b5e191ad8ff99a58de17cc21 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 12:14:09 +0800 Subject: [PATCH 067/112] remove ansicolor code,import ansicolor package --- logs/color.go | 28 --- logs/color_windows.go | 428 ------------------------------------- logs/color_windows_test.go | 294 ------------------------- logs/log.go | 8 +- logs/logger.go | 50 ----- 5 files changed, 4 insertions(+), 804 deletions(-) delete mode 100644 logs/color.go delete mode 100644 logs/color_windows.go delete mode 100644 logs/color_windows_test.go diff --git a/logs/color.go b/logs/color.go deleted file mode 100644 index 41d23638..00000000 --- a/logs/color.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -// +build !windows - -package logs - -import "io" - -type ansiColorWriter struct { - w io.Writer - mode outputMode -} - -func (cw *ansiColorWriter) Write(p []byte) (int, error) { - return cw.w.Write(p) -} diff --git a/logs/color_windows.go b/logs/color_windows.go deleted file mode 100644 index 4e28f188..00000000 --- a/logs/color_windows.go +++ /dev/null @@ -1,428 +0,0 @@ -// 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. - -// +build windows - -package logs - -import ( - "bytes" - "io" - "strings" - "syscall" - "unsafe" -) - -type ( - csiState int - parseResult int -) - -const ( - outsideCsiCode csiState = iota - firstCsiCode - secondCsiCode -) - -const ( - noConsole parseResult = iota - changedColor - unknown -) - -type ansiColorWriter struct { - w io.Writer - mode outputMode - state csiState - paramStartBuf bytes.Buffer - paramBuf bytes.Buffer -} - -const ( - firstCsiChar byte = '\x1b' - secondeCsiChar byte = '[' - separatorChar byte = ';' - sgrCode byte = 'm' -) - -const ( - foregroundBlue = uint16(0x0001) - foregroundGreen = uint16(0x0002) - foregroundRed = uint16(0x0004) - foregroundIntensity = uint16(0x0008) - backgroundBlue = uint16(0x0010) - backgroundGreen = uint16(0x0020) - backgroundRed = uint16(0x0040) - backgroundIntensity = uint16(0x0080) - underscore = uint16(0x8000) - - foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity - backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity -) - -const ( - ansiReset = "0" - ansiIntensityOn = "1" - ansiIntensityOff = "21" - ansiUnderlineOn = "4" - ansiUnderlineOff = "24" - ansiBlinkOn = "5" - ansiBlinkOff = "25" - - ansiForegroundBlack = "30" - ansiForegroundRed = "31" - ansiForegroundGreen = "32" - ansiForegroundYellow = "33" - ansiForegroundBlue = "34" - ansiForegroundMagenta = "35" - ansiForegroundCyan = "36" - ansiForegroundWhite = "37" - ansiForegroundDefault = "39" - - ansiBackgroundBlack = "40" - ansiBackgroundRed = "41" - ansiBackgroundGreen = "42" - ansiBackgroundYellow = "43" - ansiBackgroundBlue = "44" - ansiBackgroundMagenta = "45" - ansiBackgroundCyan = "46" - ansiBackgroundWhite = "47" - ansiBackgroundDefault = "49" - - ansiLightForegroundGray = "90" - ansiLightForegroundRed = "91" - ansiLightForegroundGreen = "92" - ansiLightForegroundYellow = "93" - ansiLightForegroundBlue = "94" - ansiLightForegroundMagenta = "95" - ansiLightForegroundCyan = "96" - ansiLightForegroundWhite = "97" - - ansiLightBackgroundGray = "100" - ansiLightBackgroundRed = "101" - ansiLightBackgroundGreen = "102" - ansiLightBackgroundYellow = "103" - ansiLightBackgroundBlue = "104" - ansiLightBackgroundMagenta = "105" - ansiLightBackgroundCyan = "106" - ansiLightBackgroundWhite = "107" -) - -type drawType int - -const ( - foreground drawType = iota - background -) - -type winColor struct { - code uint16 - drawType drawType -} - -var colorMap = map[string]winColor{ - ansiForegroundBlack: {0, foreground}, - ansiForegroundRed: {foregroundRed, foreground}, - ansiForegroundGreen: {foregroundGreen, foreground}, - ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground}, - ansiForegroundBlue: {foregroundBlue, foreground}, - ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground}, - ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground}, - ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, - ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, - - ansiBackgroundBlack: {0, background}, - ansiBackgroundRed: {backgroundRed, background}, - ansiBackgroundGreen: {backgroundGreen, background}, - ansiBackgroundYellow: {backgroundRed | backgroundGreen, background}, - ansiBackgroundBlue: {backgroundBlue, background}, - ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background}, - ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background}, - ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background}, - ansiBackgroundDefault: {0, background}, - - ansiLightForegroundGray: {foregroundIntensity, foreground}, - ansiLightForegroundRed: {foregroundIntensity | foregroundRed, foreground}, - ansiLightForegroundGreen: {foregroundIntensity | foregroundGreen, foreground}, - ansiLightForegroundYellow: {foregroundIntensity | foregroundRed | foregroundGreen, foreground}, - ansiLightForegroundBlue: {foregroundIntensity | foregroundBlue, foreground}, - ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground}, - ansiLightForegroundCyan: {foregroundIntensity | foregroundGreen | foregroundBlue, foreground}, - ansiLightForegroundWhite: {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground}, - - ansiLightBackgroundGray: {backgroundIntensity, background}, - ansiLightBackgroundRed: {backgroundIntensity | backgroundRed, background}, - ansiLightBackgroundGreen: {backgroundIntensity | backgroundGreen, background}, - ansiLightBackgroundYellow: {backgroundIntensity | backgroundRed | backgroundGreen, background}, - ansiLightBackgroundBlue: {backgroundIntensity | backgroundBlue, background}, - ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background}, - ansiLightBackgroundCyan: {backgroundIntensity | backgroundGreen | backgroundBlue, background}, - ansiLightBackgroundWhite: {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background}, -} - -var ( - kernel32 = syscall.NewLazyDLL("kernel32.dll") - procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") - defaultAttr *textAttributes -) - -func init() { - screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) - if screenInfo != nil { - colorMap[ansiForegroundDefault] = winColor{ - screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue), - foreground, - } - colorMap[ansiBackgroundDefault] = winColor{ - screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue), - background, - } - defaultAttr = convertTextAttr(screenInfo.WAttributes) - } -} - -type coord struct { - X, Y int16 -} - -type smallRect struct { - Left, Top, Right, Bottom int16 -} - -type consoleScreenBufferInfo struct { - DwSize coord - DwCursorPosition coord - WAttributes uint16 - SrWindow smallRect - DwMaximumWindowSize coord -} - -func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo { - var csbi consoleScreenBufferInfo - ret, _, _ := procGetConsoleScreenBufferInfo.Call( - hConsoleOutput, - uintptr(unsafe.Pointer(&csbi))) - if ret == 0 { - return nil - } - return &csbi -} - -func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool { - ret, _, _ := procSetConsoleTextAttribute.Call( - hConsoleOutput, - uintptr(wAttributes)) - return ret != 0 -} - -type textAttributes struct { - foregroundColor uint16 - backgroundColor uint16 - foregroundIntensity uint16 - backgroundIntensity uint16 - underscore uint16 - otherAttributes uint16 -} - -func convertTextAttr(winAttr uint16) *textAttributes { - fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue) - bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue) - fgIntensity := winAttr & foregroundIntensity - bgIntensity := winAttr & backgroundIntensity - underline := winAttr & underscore - otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore) - return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes} -} - -func convertWinAttr(textAttr *textAttributes) uint16 { - var winAttr uint16 - winAttr |= textAttr.foregroundColor - winAttr |= textAttr.backgroundColor - winAttr |= textAttr.foregroundIntensity - winAttr |= textAttr.backgroundIntensity - winAttr |= textAttr.underscore - winAttr |= textAttr.otherAttributes - return winAttr -} - -func changeColor(param []byte) parseResult { - screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) - if screenInfo == nil { - return noConsole - } - - winAttr := convertTextAttr(screenInfo.WAttributes) - strParam := string(param) - if len(strParam) <= 0 { - strParam = "0" - } - csiParam := strings.Split(strParam, string(separatorChar)) - for _, p := range csiParam { - c, ok := colorMap[p] - switch { - case !ok: - switch p { - case ansiReset: - winAttr.foregroundColor = defaultAttr.foregroundColor - winAttr.backgroundColor = defaultAttr.backgroundColor - winAttr.foregroundIntensity = defaultAttr.foregroundIntensity - winAttr.backgroundIntensity = defaultAttr.backgroundIntensity - winAttr.underscore = 0 - winAttr.otherAttributes = 0 - case ansiIntensityOn: - winAttr.foregroundIntensity = foregroundIntensity - case ansiIntensityOff: - winAttr.foregroundIntensity = 0 - case ansiUnderlineOn: - winAttr.underscore = underscore - case ansiUnderlineOff: - winAttr.underscore = 0 - case ansiBlinkOn: - winAttr.backgroundIntensity = backgroundIntensity - case ansiBlinkOff: - winAttr.backgroundIntensity = 0 - default: - // unknown code - } - case c.drawType == foreground: - winAttr.foregroundColor = c.code - case c.drawType == background: - winAttr.backgroundColor = c.code - } - } - winTextAttribute := convertWinAttr(winAttr) - setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute) - - return changedColor -} - -func parseEscapeSequence(command byte, param []byte) parseResult { - if defaultAttr == nil { - return noConsole - } - - switch command { - case sgrCode: - return changeColor(param) - default: - return unknown - } -} - -func (cw *ansiColorWriter) flushBuffer() (int, error) { - return cw.flushTo(cw.w) -} - -func (cw *ansiColorWriter) resetBuffer() (int, error) { - return cw.flushTo(nil) -} - -func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) { - var n1, n2 int - var err error - - startBytes := cw.paramStartBuf.Bytes() - cw.paramStartBuf.Reset() - if w != nil { - n1, err = cw.w.Write(startBytes) - if err != nil { - return n1, err - } - } else { - n1 = len(startBytes) - } - paramBytes := cw.paramBuf.Bytes() - cw.paramBuf.Reset() - if w != nil { - n2, err = cw.w.Write(paramBytes) - if err != nil { - return n1 + n2, err - } - } else { - n2 = len(paramBytes) - } - return n1 + n2, nil -} - -func isParameterChar(b byte) bool { - return ('0' <= b && b <= '9') || b == separatorChar -} - -func (cw *ansiColorWriter) Write(p []byte) (int, error) { - var r, nw, first, last int - if cw.mode != DiscardNonColorEscSeq { - cw.state = outsideCsiCode - cw.resetBuffer() - } - - var err error - for i, ch := range p { - switch cw.state { - case outsideCsiCode: - if ch == firstCsiChar { - cw.paramStartBuf.WriteByte(ch) - cw.state = firstCsiCode - } - case firstCsiCode: - switch ch { - case firstCsiChar: - cw.paramStartBuf.WriteByte(ch) - break - case secondeCsiChar: - cw.paramStartBuf.WriteByte(ch) - cw.state = secondCsiCode - last = i - 1 - default: - cw.resetBuffer() - cw.state = outsideCsiCode - } - case secondCsiCode: - if isParameterChar(ch) { - cw.paramBuf.WriteByte(ch) - } else { - nw, err = cw.w.Write(p[first:last]) - r += nw - if err != nil { - return r, err - } - first = i + 1 - result := parseEscapeSequence(ch, cw.paramBuf.Bytes()) - if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) { - cw.paramBuf.WriteByte(ch) - nw, err := cw.flushBuffer() - if err != nil { - return r, err - } - r += nw - } else { - n, _ := cw.resetBuffer() - // Add one more to the size of the buffer for the last ch - r += n + 1 - } - - cw.state = outsideCsiCode - } - default: - cw.state = outsideCsiCode - } - } - - if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode { - nw, err = cw.w.Write(p[first:]) - r += nw - } - - return r, err -} diff --git a/logs/color_windows_test.go b/logs/color_windows_test.go deleted file mode 100644 index 5074841a..00000000 --- a/logs/color_windows_test.go +++ /dev/null @@ -1,294 +0,0 @@ -// 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. - -// +build windows - -package logs - -import ( - "bytes" - "fmt" - "syscall" - "testing" -) - -var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo - -func ChangeColor(color uint16) { - setConsoleTextAttribute(uintptr(syscall.Stdout), color) -} - -func ResetColor() { - ChangeColor(uint16(0x0007)) -} - -func TestWritePlanText(t *testing.T) { - inner := bytes.NewBufferString("") - w := NewAnsiColorWriter(inner) - expected := "plain text" - fmt.Fprintf(w, expected) - actual := inner.String() - if actual != expected { - t.Errorf("Get %q, want %q", actual, expected) - } -} - -func TestWriteParseText(t *testing.T) { - inner := bytes.NewBufferString("") - w := NewAnsiColorWriter(inner) - - inputTail := "\x1b[0mtail text" - expectedTail := "tail text" - fmt.Fprintf(w, inputTail) - actualTail := inner.String() - inner.Reset() - if actualTail != expectedTail { - t.Errorf("Get %q, want %q", actualTail, expectedTail) - } - - inputHead := "head text\x1b[0m" - expectedHead := "head text" - fmt.Fprintf(w, inputHead) - actualHead := inner.String() - inner.Reset() - if actualHead != expectedHead { - t.Errorf("Get %q, want %q", actualHead, expectedHead) - } - - inputBothEnds := "both ends \x1b[0m text" - expectedBothEnds := "both ends text" - fmt.Fprintf(w, inputBothEnds) - actualBothEnds := inner.String() - inner.Reset() - if actualBothEnds != expectedBothEnds { - t.Errorf("Get %q, want %q", actualBothEnds, expectedBothEnds) - } - - inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc" - expectedManyEsc := "\x1b\x1b\x1b many esc" - fmt.Fprintf(w, inputManyEsc) - actualManyEsc := inner.String() - inner.Reset() - if actualManyEsc != expectedManyEsc { - t.Errorf("Get %q, want %q", actualManyEsc, expectedManyEsc) - } - - expectedSplit := "split text" - for _, ch := range "split \x1b[0m text" { - fmt.Fprintf(w, string(ch)) - } - actualSplit := inner.String() - inner.Reset() - if actualSplit != expectedSplit { - t.Errorf("Get %q, want %q", actualSplit, expectedSplit) - } -} - -type screenNotFoundError struct { - error -} - -func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) { - inner := bytes.NewBufferString("") - w := NewAnsiColorWriter(inner) - fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText) - - actualText = inner.String() - screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout)) - if screenInfo != nil { - actualAttributes = screenInfo.WAttributes - } else { - err = &screenNotFoundError{} - } - return -} - -type testParam struct { - text string - attributes uint16 - ansiColor string -} - -func TestWriteAnsiColorText(t *testing.T) { - screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout)) - if screenInfo == nil { - t.Fatal("Could not get ConsoleScreenBufferInfo") - } - defer ChangeColor(screenInfo.WAttributes) - defaultFgColor := screenInfo.WAttributes & uint16(0x0007) - defaultBgColor := screenInfo.WAttributes & uint16(0x0070) - defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008) - defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080) - - fgParam := []testParam{ - {"foreground black ", uint16(0x0000 | 0x0000), "30"}, - {"foreground red ", uint16(0x0004 | 0x0000), "31"}, - {"foreground green ", uint16(0x0002 | 0x0000), "32"}, - {"foreground yellow ", uint16(0x0006 | 0x0000), "33"}, - {"foreground blue ", uint16(0x0001 | 0x0000), "34"}, - {"foreground magenta", uint16(0x0005 | 0x0000), "35"}, - {"foreground cyan ", uint16(0x0003 | 0x0000), "36"}, - {"foreground white ", uint16(0x0007 | 0x0000), "37"}, - {"foreground default", defaultFgColor | 0x0000, "39"}, - {"foreground light gray ", uint16(0x0000 | 0x0008 | 0x0000), "90"}, - {"foreground light red ", uint16(0x0004 | 0x0008 | 0x0000), "91"}, - {"foreground light green ", uint16(0x0002 | 0x0008 | 0x0000), "92"}, - {"foreground light yellow ", uint16(0x0006 | 0x0008 | 0x0000), "93"}, - {"foreground light blue ", uint16(0x0001 | 0x0008 | 0x0000), "94"}, - {"foreground light magenta", uint16(0x0005 | 0x0008 | 0x0000), "95"}, - {"foreground light cyan ", uint16(0x0003 | 0x0008 | 0x0000), "96"}, - {"foreground light white ", uint16(0x0007 | 0x0008 | 0x0000), "97"}, - } - - bgParam := []testParam{ - {"background black ", uint16(0x0007 | 0x0000), "40"}, - {"background red ", uint16(0x0007 | 0x0040), "41"}, - {"background green ", uint16(0x0007 | 0x0020), "42"}, - {"background yellow ", uint16(0x0007 | 0x0060), "43"}, - {"background blue ", uint16(0x0007 | 0x0010), "44"}, - {"background magenta", uint16(0x0007 | 0x0050), "45"}, - {"background cyan ", uint16(0x0007 | 0x0030), "46"}, - {"background white ", uint16(0x0007 | 0x0070), "47"}, - {"background default", uint16(0x0007) | defaultBgColor, "49"}, - {"background light gray ", uint16(0x0007 | 0x0000 | 0x0080), "100"}, - {"background light red ", uint16(0x0007 | 0x0040 | 0x0080), "101"}, - {"background light green ", uint16(0x0007 | 0x0020 | 0x0080), "102"}, - {"background light yellow ", uint16(0x0007 | 0x0060 | 0x0080), "103"}, - {"background light blue ", uint16(0x0007 | 0x0010 | 0x0080), "104"}, - {"background light magenta", uint16(0x0007 | 0x0050 | 0x0080), "105"}, - {"background light cyan ", uint16(0x0007 | 0x0030 | 0x0080), "106"}, - {"background light white ", uint16(0x0007 | 0x0070 | 0x0080), "107"}, - } - - resetParam := []testParam{ - {"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"}, - {"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""}, - } - - boldParam := []testParam{ - {"bold on", uint16(0x0007 | 0x0008), "1"}, - {"bold off", uint16(0x0007), "21"}, - } - - underscoreParam := []testParam{ - {"underscore on", uint16(0x0007 | 0x8000), "4"}, - {"underscore off", uint16(0x0007), "24"}, - } - - blinkParam := []testParam{ - {"blink on", uint16(0x0007 | 0x0080), "5"}, - {"blink off", uint16(0x0007), "25"}, - } - - mixedParam := []testParam{ - {"both black, bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"}, - {"both red, bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"}, - {"both green, bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"}, - {"both yellow, bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"}, - {"both blue, bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"}, - {"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"}, - {"both cyan, bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"}, - {"both white, bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"}, - {"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"}, - } - - assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) { - actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor) - if actualText != expectedText { - t.Errorf("Get %q, want %q", actualText, expectedText) - } - if err != nil { - t.Fatal("Could not get ConsoleScreenBufferInfo") - } - if actualAttributes != expectedAttributes { - t.Errorf("Text: %q, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes) - } - } - - for _, v := range fgParam { - ResetColor() - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - for _, v := range bgParam { - ChangeColor(uint16(0x0070 | 0x0007)) - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - for _, v := range resetParam { - ChangeColor(uint16(0x0000 | 0x0070 | 0x0008)) - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - ResetColor() - for _, v := range boldParam { - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - ResetColor() - for _, v := range underscoreParam { - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - ResetColor() - for _, v := range blinkParam { - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } - - for _, v := range mixedParam { - ResetColor() - assertTextAttribute(v.text, v.attributes, v.ansiColor) - } -} - -func TestIgnoreUnknownSequences(t *testing.T) { - inner := bytes.NewBufferString("") - w := NewModeAnsiColorWriter(inner, OutputNonColorEscSeq) - - inputText := "\x1b[=decpath mode" - expectedTail := inputText - fmt.Fprintf(w, inputText) - actualTail := inner.String() - inner.Reset() - if actualTail != expectedTail { - t.Errorf("Get %q, want %q", actualTail, expectedTail) - } - - inputText = "\x1b[=tailing esc and bracket\x1b[" - expectedTail = inputText - fmt.Fprintf(w, inputText) - actualTail = inner.String() - inner.Reset() - if actualTail != expectedTail { - t.Errorf("Get %q, want %q", actualTail, expectedTail) - } - - inputText = "\x1b[?tailing esc\x1b" - expectedTail = inputText - fmt.Fprintf(w, inputText) - actualTail = inner.String() - inner.Reset() - if actualTail != expectedTail { - t.Errorf("Get %q, want %q", actualTail, expectedTail) - } - - inputText = "\x1b[1h;3punended color code invalid\x1b3" - expectedTail = inputText - fmt.Fprintf(w, inputText) - actualTail = inner.String() - inner.Reset() - if actualTail != expectedTail { - t.Errorf("Get %q, want %q", actualTail, expectedTail) - } -} diff --git a/logs/log.go b/logs/log.go index a3614165..3bf9c5f4 100644 --- a/logs/log.go +++ b/logs/log.go @@ -47,7 +47,7 @@ import ( // RFC5424 log message levels. const ( - LevelEmergency = iota + LevelEmergency = iota LevelAlert LevelCritical LevelError @@ -92,7 +92,7 @@ type Logger interface { } var adapters = make(map[string]newLoggerFunc) -var levelPrefix = [LevelDebug + 1]string{"[M] ", "[A] ", "[C] ", "[E] ", "[W] ", "[N] ", "[I] ", "[D] "} +var levelPrefix = [LevelDebug + 1]string{"[M]", "[A]", "[C]", "[E]", "[W]", "[N]", "[I]", "[D]"} // Register makes a log provide available by the provided name. // If Register is called twice with the same name or if driver is nil, @@ -248,7 +248,7 @@ func (bl *BeeLogger) Write(p []byte) (n int, err error) { } // writeMsg will always add a '\n' character if p[len(p)-1] == '\n' { - p = p[0: len(p)-1] + p = p[0 : len(p)-1] } // set levelLoggerImpl to ensure all log message will be write out err = bl.writeMsg(levelLoggerImpl, string(p)) @@ -287,7 +287,7 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error // set to emergency to ensure all log will be print out correctly logLevel = LevelEmergency } else { - msg = levelPrefix[logLevel] + msg + msg = levelPrefix[logLevel] + " " + msg } if bl.asynchronous { diff --git a/logs/logger.go b/logs/logger.go index cdcd63e9..06bf0f69 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -15,9 +15,7 @@ package logs import ( - "fmt" "io" - "os" "runtime" "sync" "time" @@ -39,40 +37,6 @@ func (lg *logWriter) println(when time.Time, msg string) { lg.Unlock() } -type outputMode int - -// DiscardNonColorEscSeq supports the divided color escape sequence. -// But non-color escape sequence is not output. -// Please use the OutputNonColorEscSeq If you want to output a non-color -// escape sequences such as ncurses. However, it does not support the divided -// color escape sequence. -const ( - _ outputMode = iota - DiscardNonColorEscSeq - OutputNonColorEscSeq -) - -// NewAnsiColorWriter creates and initializes a new ansiColorWriter -// using io.Writer w as its initial contents. -// In the console of Windows, which change the foreground and background -// colors of the text by the escape sequence. -// In the console of other systems, which writes to w all text. -func NewAnsiColorWriter(w io.Writer) io.Writer { - return NewModeAnsiColorWriter(w, DiscardNonColorEscSeq) -} - -// NewModeAnsiColorWriter create and initializes a new ansiColorWriter -// by specifying the outputMode. -func NewModeAnsiColorWriter(w io.Writer, mode outputMode) io.Writer { - if _, ok := w.(*ansiColorWriter); !ok { - return &ansiColorWriter{ - w: w, - mode: mode, - } - } - return w -} - const ( y1 = `0123456789` y2 = `0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789` @@ -209,17 +173,3 @@ func ColorByMethod(method string) string { func ResetColor() string { return reset } - -// Guard Mutex to guarantee atomic of W32Debug(string) function -var mu sync.Mutex - -// W32Debug Helper method to output colored logs in Windows terminals -func W32Debug(msg string) { - mu.Lock() - defer mu.Unlock() - - current := time.Now() - w := NewAnsiColorWriter(os.Stdout) - - fmt.Fprintf(w, "[beego] %v %s\n", current.Format("2006/01/02 - 15:04:05"), msg) -} From 7693502aaa65b2a62e4aea005d2ee21250fa3dc4 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 13:20:13 +0800 Subject: [PATCH 068/112] logAdapter is more readable --- logs/log.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/logs/log.go b/logs/log.go index 3bf9c5f4..49f3794f 100644 --- a/logs/log.go +++ b/logs/log.go @@ -187,12 +187,12 @@ func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error { } } - log, ok := adapters[adapterName] + logAdapter, ok := adapters[adapterName] if !ok { return fmt.Errorf("logs: unknown adaptername %q (forgotten Register?)", adapterName) } - lg := log() + lg := logAdapter() err := lg.Init(config) if err != nil { fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error()) From 9cecb221703a4b845b50b47abaecf3bd1ecd41cc Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 15:13:54 +0800 Subject: [PATCH 069/112] NewAnsiColorWriter remove --- logs/logger_test.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/logs/logger_test.go b/logs/logger_test.go index 78c67737..debe2e90 100644 --- a/logs/logger_test.go +++ b/logs/logger_test.go @@ -57,19 +57,3 @@ func TestFormatHeader_1(t *testing.T) { } } -func TestNewAnsiColor1(t *testing.T) { - inner := bytes.NewBufferString("") - w := NewAnsiColorWriter(inner) - if w == inner { - t.Errorf("Get %#v, want %#v", w, inner) - } -} - -func TestNewAnsiColor2(t *testing.T) { - inner := bytes.NewBufferString("") - w1 := NewAnsiColorWriter(inner) - w2 := NewAnsiColorWriter(w1) - if w1 != w2 { - t.Errorf("Get %#v, want %#v", w1, w2) - } -} From 44a1a8f6bef9008e15be4810a031b495a0b08542 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 15:51:43 +0800 Subject: [PATCH 070/112] println is builtin function --- logs/conn.go | 2 +- logs/console.go | 2 +- logs/logger.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/logs/conn.go b/logs/conn.go index 6d5bf6bf..afe0cbb7 100644 --- a/logs/conn.go +++ b/logs/conn.go @@ -63,7 +63,7 @@ func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { defer c.innerWriter.Close() } - c.lg.println(when, msg) + c.lg.writeln(when, msg) return nil } diff --git a/logs/console.go b/logs/console.go index 73c623f5..3dcaee1d 100644 --- a/logs/console.go +++ b/logs/console.go @@ -80,7 +80,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { if c.Colorful { msg = strings.Replace(msg, levelPrefix[level], colors[level](levelPrefix[level]), 1) } - c.lg.println(when, msg) + c.lg.writeln(when, msg) return nil } diff --git a/logs/logger.go b/logs/logger.go index 06bf0f69..c7cf8a56 100644 --- a/logs/logger.go +++ b/logs/logger.go @@ -30,7 +30,7 @@ func newLogWriter(wr io.Writer) *logWriter { return &logWriter{writer: wr} } -func (lg *logWriter) println(when time.Time, msg string) { +func (lg *logWriter) writeln(when time.Time, msg string) { lg.Lock() h, _, _ := formatTimeHeader(when) lg.writer.Write(append(append(h, msg...), '\n')) From 4564e9810c487ea6c19e8072f0847294442b43f4 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 16:36:00 +0800 Subject: [PATCH 071/112] logger_test imported and not used: "bytes" --- logs/logger_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/logs/logger_test.go b/logs/logger_test.go index debe2e90..15be500d 100644 --- a/logs/logger_test.go +++ b/logs/logger_test.go @@ -15,7 +15,6 @@ package logs import ( - "bytes" "testing" "time" ) @@ -56,4 +55,3 @@ func TestFormatHeader_1(t *testing.T) { tm = tm.Add(dur) } } - From ea91e7638c39ae38cdda9e11918dacc21ff899a0 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 12 Mar 2019 17:01:23 +0800 Subject: [PATCH 072/112] move log function to log package --- app.go | 4 +-- log.go | 111 --------------------------------------------------------- 2 files changed, 2 insertions(+), 113 deletions(-) delete mode 100644 log.go diff --git a/app.go b/app.go index 32ff159d..d9e85e9b 100644 --- a/app.go +++ b/app.go @@ -176,7 +176,7 @@ func (app *App) Run(mws ...MiddleWare) { if BConfig.Listen.HTTPSPort != 0 { app.Server.Addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort) } else if BConfig.Listen.EnableHTTP { - BeeLogger.Info("Start https server error, conflict with http. Please reset https port") + logs.Info("Start https server error, conflict with http. Please reset https port") return } logs.Info("https server Running on https://%s", app.Server.Addr) @@ -192,7 +192,7 @@ func (app *App) Run(mws ...MiddleWare) { pool := x509.NewCertPool() data, err := ioutil.ReadFile(BConfig.Listen.TrustCaFile) if err != nil { - BeeLogger.Info("MutualHTTPS should provide TrustCaFile") + logs.Info("MutualHTTPS should provide TrustCaFile") return } pool.AppendCertsFromPEM(data) diff --git a/log.go b/log.go deleted file mode 100644 index e9412f92..00000000 --- a/log.go +++ /dev/null @@ -1,111 +0,0 @@ -// 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 beego - -import ( - "strings" - - "github.com/astaxie/beego/logs" -) - -// Log levels to control the logging output. -const ( - LevelEmergency = iota - LevelAlert - LevelCritical - LevelError - LevelWarning - LevelNotice - LevelInformational - LevelDebug -) - -// BeeLogger references the used application logger. -var BeeLogger = logs.GetBeeLogger() - -// SetLevel sets the global log level used by the simple logger. -func SetLevel(l int) { - logs.SetLevel(l) -} - -// SetLogFuncCall set the CallDepth, default is 3 -func SetLogFuncCall(b bool) { - logs.SetLogFuncCall(b) -} - -// SetLogger sets a new logger. -func SetLogger(adaptername string, config string) error { - return logs.SetLogger(adaptername, config) -} - -// Emergency logs a message at emergency level. -func Emergency(v ...interface{}) { - logs.Emergency(generateFmtStr(len(v)), v...) -} - -// Alert logs a message at alert level. -func Alert(v ...interface{}) { - logs.Alert(generateFmtStr(len(v)), v...) -} - -// Critical logs a message at critical level. -func Critical(v ...interface{}) { - logs.Critical(generateFmtStr(len(v)), v...) -} - -// Error logs a message at error level. -func Error(v ...interface{}) { - logs.Error(generateFmtStr(len(v)), v...) -} - -// Warning logs a message at warning level. -func Warning(v ...interface{}) { - logs.Warning(generateFmtStr(len(v)), v...) -} - -// Warn compatibility alias for Warning() -func Warn(v ...interface{}) { - logs.Warn(generateFmtStr(len(v)), v...) -} - -// Notice logs a message at notice level. -func Notice(v ...interface{}) { - logs.Notice(generateFmtStr(len(v)), v...) -} - -// Informational logs a message at info level. -func Informational(v ...interface{}) { - logs.Informational(generateFmtStr(len(v)), v...) -} - -// Info compatibility alias for Warning() -func Info(v ...interface{}) { - logs.Info(generateFmtStr(len(v)), v...) -} - -// Debug logs a message at debug level. -func Debug(v ...interface{}) { - logs.Debug(generateFmtStr(len(v)), v...) -} - -// Trace logs a message at trace level. -// compatibility alias for Warning() -func Trace(v ...interface{}) { - logs.Trace(generateFmtStr(len(v)), v...) -} - -func generateFmtStr(n int) string { - return strings.Repeat("%v ", n) -} From 95ff8170192aa249d97dea1db695a96d2c631466 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 13 Mar 2019 09:41:13 +0800 Subject: [PATCH 073/112] undefined: beego.BeeLogger fixed --- migration/ddl.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index 9313acf8..cd2c1c49 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -17,7 +17,7 @@ package migration import ( "fmt" - "github.com/astaxie/beego" + "github.com/astaxie/beego/logs" ) // Index struct defines the structure of Index Columns @@ -316,7 +316,7 @@ func (m *Migration) GetSQL() (sql string) { sql += fmt.Sprintf("ALTER TABLE `%s` ", m.TableName) for index, column := range m.Columns { if !column.remove { - beego.BeeLogger.Info("col") + logs.Info("col") sql += fmt.Sprintf("\n ADD `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) } else { sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) From be31bd2bbd3c6642a46f6b282b79ceeca4b1dcf1 Mon Sep 17 00:00:00 2001 From: Yanhui Shen Date: Wed, 13 Mar 2019 16:24:04 +0800 Subject: [PATCH 074/112] Ensure custom error handler is called --- router.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router.go b/router.go index c5d0cda4..52c56632 100644 --- a/router.go +++ b/router.go @@ -690,7 +690,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) // filter wrong http method if !HTTPMETHOD[r.Method] { - http.Error(rw, "Method Not Allowed", http.StatusMethodNotAllowed) + exception("405", context) goto Admin } From 914bbfd7105eda78199b3620b3d935495348725d Mon Sep 17 00:00:00 2001 From: Daniel Ramirez Grave de Peralta Date: Thu, 14 Mar 2019 09:14:12 -0400 Subject: [PATCH 075/112] Update apiauth.go fixed infinite recursive call --- plugins/apiauth/apiauth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/apiauth/apiauth.go b/plugins/apiauth/apiauth.go index aa8c1960..10e25f3f 100644 --- a/plugins/apiauth/apiauth.go +++ b/plugins/apiauth/apiauth.go @@ -85,7 +85,7 @@ func APIBasicAuth(appid, appkey string) beego.FilterFunc { // APIBaiscAuth calls APIBasicAuth for previous callers func APIBaiscAuth(appid, appkey string) beego.FilterFunc { - return APIBaiscAuth(appid, appkey) + return APIBasicAuth(appid, appkey) } // APISecretAuth use AppIdToAppSecret verify and From 005391be81e129fe41477a78a416b690f81f4b75 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Sat, 23 Mar 2019 00:33:26 +0800 Subject: [PATCH 076/112] update --- orm/db.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/orm/db.go b/orm/db.go index 2719dff7..df69eec3 100644 --- a/orm/db.go +++ b/orm/db.go @@ -631,14 +631,8 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. } if find { - newSetNames := make([]string, 0, len(setNames)-1) - newSetNames = append(newSetNames, setNames[0:index]...) - newSetNames = append(newSetNames, setNames[index+1:]...) - setNames = newSetNames - newSetValues := make([]interface{}, 0, len(setNames)-1) - newSetValues = append(newSetValues, setValues[0:index]...) - newSetValues = append(newSetValues, setValues[index+1:]...) - setValues = newSetValues + setNames = append(setNames[0:index], setNames[index+1:]...) + setValues = append(setValues[0:index], setValues[index+1:]...) } From 3b00cfccec18dac833c3afddcf1fc7839fc59fd1 Mon Sep 17 00:00:00 2001 From: "Yang, Gao" Date: Sun, 24 Mar 2019 14:41:28 +0800 Subject: [PATCH 077/112] [Fix] Fix the issue that genRouterCode incorrect logic results in @Import annotations getting overwritten --- parser.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/parser.go b/parser.go index a8690274..81990a4a 100644 --- a/parser.go +++ b/parser.go @@ -459,13 +459,17 @@ func genRouterCode(pkgRealpath string) { imports := "" if len(c.ImportComments) > 0 { for _, i := range c.ImportComments { + var s string if i.ImportAlias != "" { - imports += fmt.Sprintf(` + s = fmt.Sprintf(` %s "%s"`, i.ImportAlias, i.ImportPath) } else { - imports += fmt.Sprintf(` + s = fmt.Sprintf(` "%s"`, i.ImportPath) } + if !strings.Contains(globalimport, s) { + imports += s + } } } @@ -490,7 +494,7 @@ func genRouterCode(pkgRealpath string) { }`, filters) } - globalimport = imports + globalimport += imports globalinfo = globalinfo + ` beego.GlobalControllerRouter["` + k + `"] = append(beego.GlobalControllerRouter["` + k + `"], From 0b8ebaf38755bcbfa51443fb6ba55eef3c268a51 Mon Sep 17 00:00:00 2001 From: GeorgeXc Date: Tue, 26 Mar 2019 01:00:04 +0800 Subject: [PATCH 078/112] Update db.go --- orm/db.go | 1 - 1 file changed, 1 deletion(-) diff --git a/orm/db.go b/orm/db.go index df69eec3..20d9c4cd 100644 --- a/orm/db.go +++ b/orm/db.go @@ -633,7 +633,6 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. if find { setNames = append(setNames[0:index], setNames[index+1:]...) setValues = append(setValues[0:index], setValues[index+1:]...) - } setValues = append(setValues, pkValue) From e8b29c9fd18e97a56821e7f80464f80965dc6e71 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:34:46 +0800 Subject: [PATCH 079/112] handle trace request --- controller.go | 63 +++++++++++++++++++++++++++++++++++++-------------- router.go | 2 ++ 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/controller.go b/controller.go index 9c605760..e6ecd12e 100644 --- a/controller.go +++ b/controller.go @@ -27,6 +27,8 @@ import ( "strconv" "strings" + "fmt" + "github.com/astaxie/beego/context" "github.com/astaxie/beego/context/param" "github.com/astaxie/beego/session" @@ -78,24 +80,30 @@ type ControllerComments struct { // ControllerCommentsSlice implements the sort interface type ControllerCommentsSlice []ControllerComments -func (p ControllerCommentsSlice) Len() int { return len(p) } -func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router } -func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p ControllerCommentsSlice) Len() int { + return len(p) +} +func (p ControllerCommentsSlice) Less(i, j int) bool { + return p[i].Router < p[j].Router +} +func (p ControllerCommentsSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. type Controller struct { - // context data - Ctx *context.Context - Data map[interface{}]interface{} + // context data + Ctx *context.Context + Data map[interface{}]interface{} - // route controller info + // route controller info controllerName string actionName string methodMapping map[string]func() //method:routertree AppController interface{} - // template data + // template data TplName string ViewPath string Layout string @@ -104,13 +112,13 @@ type Controller struct { TplExt string EnableRender bool - // xsrf data - _xsrfToken string - XSRFExpire int - EnableXSRF bool + // xsrf data + _xsrfToken string + XSRFExpire int + EnableXSRF bool - // session - CruSession session.Store + // session + CruSession session.Store } // ControllerInterface is an interface to uniform all controller handler. @@ -124,6 +132,7 @@ type ControllerInterface interface { Head() Patch() Options() + Trace() Finish() Render() error XSRFToken() string @@ -188,6 +197,26 @@ func (c *Controller) Options() { http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } +// Trace adds a request function to handle Trace request. +// https://tools.ietf.org/html/rfc7231#section-4.3.8 +// The TRACE method requests a remote, application-level loop-back of +// the request message. The final recipient of the request SHOULD +// reflect the message received, excluding some fields described below, +// back to the client as the message body of a 200 (OK) response with a +// Content-Type of "message/http" (Section 8.3.1 of [RFC7230]). +func (c *Controller) Trace() { + ts := func(h http.Header) (hs string) { + for k, v := range h { + hs += fmt.Sprintf("\r\n%s: %s", k, v) + } + return + } + hs := fmt.Sprintf("\r\nTRACE %s %s%s\r\n", c.Ctx.Request.RequestURI, c.Ctx.Request.Proto, ts(c.Ctx.Request.Header)) + c.Ctx.Output.Header("Content-Type", "message/http") + c.Ctx.Output.Header("Content-Length", fmt.Sprint(len(hs))) + c.Ctx.WriteString(hs) +} + // HandlerFunc call function with the name func (c *Controller) HandlerFunc(fnname string) bool { if v, ok := c.methodMapping[fnname]; ok { @@ -342,7 +371,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { return "" } if endpoint[0] == '.' { - return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...) + return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name() + endpoint, values...) } return URLFor(endpoint, values...) } @@ -350,7 +379,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { // ServeJSON sends a json response with encoding charset. func (c *Controller) ServeJSON(encoding ...bool) { var ( - hasIndent = BConfig.RunMode != PROD + hasIndent = BConfig.RunMode != PROD hasEncoding = len(encoding) > 0 && encoding[0] ) @@ -575,7 +604,7 @@ func (c *Controller) SaveToFile(fromfile, tofile string) error { return err } defer file.Close() - f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + f, err := os.OpenFile(tofile, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0666) if err != nil { return err } diff --git a/router.go b/router.go index a9b6f078..c7abe38c 100644 --- a/router.go +++ b/router.go @@ -843,6 +843,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) execController.Patch() case http.MethodOptions: execController.Options() + case http.MethodTrace: + execController.Trace() default: if !execController.HandlerFunc(runMethod) { vc := reflect.ValueOf(execController) From 02bead509778356b010c8ef08f1fdee139e44d6f Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:40:34 +0800 Subject: [PATCH 080/112] handle trace request must NOT CACHE https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control --- controller.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/controller.go b/controller.go index e6ecd12e..c1bbb857 100644 --- a/controller.go +++ b/controller.go @@ -93,17 +93,17 @@ func (p ControllerCommentsSlice) Swap(i, j int) { // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. type Controller struct { - // context data - Ctx *context.Context - Data map[interface{}]interface{} + // context data + Ctx *context.Context + Data map[interface{}]interface{} - // route controller info + // route controller info controllerName string actionName string methodMapping map[string]func() //method:routertree AppController interface{} - // template data + // template data TplName string ViewPath string Layout string @@ -112,13 +112,13 @@ type Controller struct { TplExt string EnableRender bool - // xsrf data - _xsrfToken string - XSRFExpire int - EnableXSRF bool + // xsrf data + _xsrfToken string + XSRFExpire int + EnableXSRF bool - // session - CruSession session.Store + // session + CruSession session.Store } // ControllerInterface is an interface to uniform all controller handler. @@ -214,6 +214,7 @@ func (c *Controller) Trace() { hs := fmt.Sprintf("\r\nTRACE %s %s%s\r\n", c.Ctx.Request.RequestURI, c.Ctx.Request.Proto, ts(c.Ctx.Request.Header)) c.Ctx.Output.Header("Content-Type", "message/http") c.Ctx.Output.Header("Content-Length", fmt.Sprint(len(hs))) + c.Ctx.Output.Header("Cache-Control", "no-cache, no-store, must-revalidate") c.Ctx.WriteString(hs) } @@ -371,7 +372,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { return "" } if endpoint[0] == '.' { - return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name() + endpoint, values...) + return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...) } return URLFor(endpoint, values...) } @@ -379,7 +380,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { // ServeJSON sends a json response with encoding charset. func (c *Controller) ServeJSON(encoding ...bool) { var ( - hasIndent = BConfig.RunMode != PROD + hasIndent = BConfig.RunMode != PROD hasEncoding = len(encoding) > 0 && encoding[0] ) @@ -604,7 +605,7 @@ func (c *Controller) SaveToFile(fromfile, tofile string) error { return err } defer file.Close() - f, err := os.OpenFile(tofile, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0666) + f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return err } From 3155f07ccdcdd7d3fc0e5ebcf022e834b7e24688 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:43:27 +0800 Subject: [PATCH 081/112] no need to override Trace method. --- controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controller.go b/controller.go index c1bbb857..38328c17 100644 --- a/controller.go +++ b/controller.go @@ -198,6 +198,7 @@ func (c *Controller) Options() { } // Trace adds a request function to handle Trace request. +// this method SHOULD NOT be overridden. // https://tools.ietf.org/html/rfc7231#section-4.3.8 // The TRACE method requests a remote, application-level loop-back of // the request message. The final recipient of the request SHOULD From c0ecf32d177f2bdf251392f9c1c8890bb88ee90f Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 2 Apr 2019 21:53:01 +0800 Subject: [PATCH 082/112] update travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6ddcfcf5..1bb121a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: go go: - - "1.10.x" - "1.11.x" services: - redis-server From 75b4bc58965a6b3d8172df7b4b5f34904d04b9a9 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 3 Apr 2019 10:19:09 +0800 Subject: [PATCH 083/112] it's no need to override Trace method. --- controller.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/controller.go b/controller.go index 38328c17..0e8853b3 100644 --- a/controller.go +++ b/controller.go @@ -17,6 +17,7 @@ package beego import ( "bytes" "errors" + "fmt" "html/template" "io" "mime/multipart" @@ -27,8 +28,6 @@ import ( "strconv" "strings" - "fmt" - "github.com/astaxie/beego/context" "github.com/astaxie/beego/context/param" "github.com/astaxie/beego/session" @@ -80,15 +79,9 @@ type ControllerComments struct { // ControllerCommentsSlice implements the sort interface type ControllerCommentsSlice []ControllerComments -func (p ControllerCommentsSlice) Len() int { - return len(p) -} -func (p ControllerCommentsSlice) Less(i, j int) bool { - return p[i].Router < p[j].Router -} -func (p ControllerCommentsSlice) Swap(i, j int) { - p[i], p[j] = p[j], p[i] -} +func (p ControllerCommentsSlice) Len() int { return len(p) } +func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router } +func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. From e3d668f4504b04a8bd78ea36d95cdf7d09df164a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 3 Apr 2019 14:08:42 +0800 Subject: [PATCH 084/112] revet to log.go https://github.com/astaxie/beego/issues/3591 https://github.com/astaxie/beego/issues/3588 --- log.go | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 log.go diff --git a/log.go b/log.go new file mode 100644 index 00000000..e9412f92 --- /dev/null +++ b/log.go @@ -0,0 +1,111 @@ +// 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 beego + +import ( + "strings" + + "github.com/astaxie/beego/logs" +) + +// Log levels to control the logging output. +const ( + LevelEmergency = iota + LevelAlert + LevelCritical + LevelError + LevelWarning + LevelNotice + LevelInformational + LevelDebug +) + +// BeeLogger references the used application logger. +var BeeLogger = logs.GetBeeLogger() + +// SetLevel sets the global log level used by the simple logger. +func SetLevel(l int) { + logs.SetLevel(l) +} + +// SetLogFuncCall set the CallDepth, default is 3 +func SetLogFuncCall(b bool) { + logs.SetLogFuncCall(b) +} + +// SetLogger sets a new logger. +func SetLogger(adaptername string, config string) error { + return logs.SetLogger(adaptername, config) +} + +// Emergency logs a message at emergency level. +func Emergency(v ...interface{}) { + logs.Emergency(generateFmtStr(len(v)), v...) +} + +// Alert logs a message at alert level. +func Alert(v ...interface{}) { + logs.Alert(generateFmtStr(len(v)), v...) +} + +// Critical logs a message at critical level. +func Critical(v ...interface{}) { + logs.Critical(generateFmtStr(len(v)), v...) +} + +// Error logs a message at error level. +func Error(v ...interface{}) { + logs.Error(generateFmtStr(len(v)), v...) +} + +// Warning logs a message at warning level. +func Warning(v ...interface{}) { + logs.Warning(generateFmtStr(len(v)), v...) +} + +// Warn compatibility alias for Warning() +func Warn(v ...interface{}) { + logs.Warn(generateFmtStr(len(v)), v...) +} + +// Notice logs a message at notice level. +func Notice(v ...interface{}) { + logs.Notice(generateFmtStr(len(v)), v...) +} + +// Informational logs a message at info level. +func Informational(v ...interface{}) { + logs.Informational(generateFmtStr(len(v)), v...) +} + +// Info compatibility alias for Warning() +func Info(v ...interface{}) { + logs.Info(generateFmtStr(len(v)), v...) +} + +// Debug logs a message at debug level. +func Debug(v ...interface{}) { + logs.Debug(generateFmtStr(len(v)), v...) +} + +// Trace logs a message at trace level. +// compatibility alias for Warning() +func Trace(v ...interface{}) { + logs.Trace(generateFmtStr(len(v)), v...) +} + +func generateFmtStr(n int) string { + return strings.Repeat("%v ", n) +} From ce3800e3efcb40f219d27e5ff4a2a4800aa6f229 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 3 Apr 2019 14:13:38 +0800 Subject: [PATCH 085/112] // Deprecated: use github.com/astaxie/beego/logs instead. --- log.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/log.go b/log.go index e9412f92..cc4c0f81 100644 --- a/log.go +++ b/log.go @@ -21,6 +21,7 @@ import ( ) // Log levels to control the logging output. +// Deprecated: use github.com/astaxie/beego/logs instead. const ( LevelEmergency = iota LevelAlert @@ -33,75 +34,90 @@ const ( ) // BeeLogger references the used application logger. +// Deprecated: use github.com/astaxie/beego/logs instead. var BeeLogger = logs.GetBeeLogger() // SetLevel sets the global log level used by the simple logger. +// Deprecated: use github.com/astaxie/beego/logs instead. func SetLevel(l int) { logs.SetLevel(l) } // SetLogFuncCall set the CallDepth, default is 3 +// Deprecated: use github.com/astaxie/beego/logs instead. func SetLogFuncCall(b bool) { logs.SetLogFuncCall(b) } // SetLogger sets a new logger. +// Deprecated: use github.com/astaxie/beego/logs instead. func SetLogger(adaptername string, config string) error { return logs.SetLogger(adaptername, config) } // Emergency logs a message at emergency level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Emergency(v ...interface{}) { logs.Emergency(generateFmtStr(len(v)), v...) } // Alert logs a message at alert level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Alert(v ...interface{}) { logs.Alert(generateFmtStr(len(v)), v...) } // Critical logs a message at critical level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Critical(v ...interface{}) { logs.Critical(generateFmtStr(len(v)), v...) } // Error logs a message at error level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Error(v ...interface{}) { logs.Error(generateFmtStr(len(v)), v...) } // Warning logs a message at warning level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Warning(v ...interface{}) { logs.Warning(generateFmtStr(len(v)), v...) } // Warn compatibility alias for Warning() +// Deprecated: use github.com/astaxie/beego/logs instead. func Warn(v ...interface{}) { logs.Warn(generateFmtStr(len(v)), v...) } // Notice logs a message at notice level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Notice(v ...interface{}) { logs.Notice(generateFmtStr(len(v)), v...) } // Informational logs a message at info level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Informational(v ...interface{}) { logs.Informational(generateFmtStr(len(v)), v...) } // Info compatibility alias for Warning() +// Deprecated: use github.com/astaxie/beego/logs instead. func Info(v ...interface{}) { logs.Info(generateFmtStr(len(v)), v...) } // Debug logs a message at debug level. +// Deprecated: use github.com/astaxie/beego/logs instead. func Debug(v ...interface{}) { logs.Debug(generateFmtStr(len(v)), v...) } // Trace logs a message at trace level. // compatibility alias for Warning() +// Deprecated: use github.com/astaxie/beego/logs instead. func Trace(v ...interface{}) { logs.Trace(generateFmtStr(len(v)), v...) } From e980f92c6382e1d05aea4520b3486c5975f590b8 Mon Sep 17 00:00:00 2001 From: Wusuluren <1634636348@qq.com> Date: Fri, 5 Apr 2019 20:28:24 +0800 Subject: [PATCH 086/112] fix race problem on toolbox/task --- toolbox/task.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/toolbox/task.go b/toolbox/task.go index 7e841e89..d1343023 100644 --- a/toolbox/task.go +++ b/toolbox/task.go @@ -20,6 +20,7 @@ import ( "sort" "strconv" "strings" + "sync" "time" ) @@ -32,6 +33,7 @@ type bounds struct { // The bounds for each field. var ( AdminTaskList map[string]Tasker + taskLock sync.Mutex stop chan bool changed chan bool isstart bool @@ -389,6 +391,8 @@ func dayMatches(s *Schedule, t time.Time) bool { // StartTask start all tasks func StartTask() { + taskLock.Lock() + defer taskLock.Unlock() if isstart { //If already started, no need to start another goroutine. return @@ -440,6 +444,8 @@ func run() { // StopTask stop all tasks func StopTask() { + taskLock.Lock() + defer taskLock.Unlock() if isstart { isstart = false stop <- true @@ -449,6 +455,8 @@ func StopTask() { // AddTask add task with name func AddTask(taskname string, t Tasker) { + taskLock.Lock() + defer taskLock.Unlock() t.SetNext(time.Now().Local()) AdminTaskList[taskname] = t if isstart { @@ -458,6 +466,8 @@ func AddTask(taskname string, t Tasker) { // DeleteTask delete task with name func DeleteTask(taskname string) { + taskLock.Lock() + defer taskLock.Unlock() delete(AdminTaskList, taskname) if isstart { changed <- true From 190024605408b1a9964da201a022f7a1bc04cf36 Mon Sep 17 00:00:00 2001 From: Wusuluren <1634636348@qq.com> Date: Fri, 5 Apr 2019 22:15:53 +0800 Subject: [PATCH 087/112] fix bug on cache/file --- cache/file.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cache/file.go b/cache/file.go index 1926268a..6f12d3ee 100644 --- a/cache/file.go +++ b/cache/file.go @@ -62,11 +62,14 @@ func NewFileCache() Cache { } // StartAndGC will start and begin gc for file cache. -// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0} +// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"} func (fc *FileCache) StartAndGC(config string) error { cfg := make(map[string]string) - json.Unmarshal([]byte(config), &cfg) + err := json.Unmarshal([]byte(config), &cfg) + if err != nil { + return err + } if _, ok := cfg["CachePath"]; !ok { cfg["CachePath"] = FileCachePath } @@ -142,12 +145,12 @@ func (fc *FileCache) GetMulti(keys []string) []interface{} { // Put value into file cache. // timeout means how long to keep this file, unit of ms. -// if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever. +// if timeout equals fc.EmbedExpiry(default is 0), cache this item forever. func (fc *FileCache) Put(key string, val interface{}, timeout time.Duration) error { gob.Register(val) item := FileCacheItem{Data: val} - if timeout == FileCacheEmbedExpiry { + if timeout == time.Duration(fc.EmbedExpiry) { item.Expired = time.Now().Add((86400 * 365 * 10) * time.Second) // ten years } else { item.Expired = time.Now().Add(timeout) @@ -179,7 +182,7 @@ func (fc *FileCache) Incr(key string) error { } else { incr = data.(int) + 1 } - fc.Put(key, incr, FileCacheEmbedExpiry) + fc.Put(key, incr, time.Duration(fc.EmbedExpiry)) return nil } @@ -192,7 +195,7 @@ func (fc *FileCache) Decr(key string) error { } else { decr = data.(int) - 1 } - fc.Put(key, decr, FileCacheEmbedExpiry) + fc.Put(key, decr, time.Duration(fc.EmbedExpiry)) return nil } From dfab44c24ab4573adccbf0dcc998f4cde5fca919 Mon Sep 17 00:00:00 2001 From: Wusuluren <1634636348@qq.com> Date: Fri, 5 Apr 2019 22:32:28 +0800 Subject: [PATCH 088/112] fix bug on cache/file --- cache/cache_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/cache_test.go b/cache/cache_test.go index 9ceb606a..1e71d075 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -98,7 +98,7 @@ func TestCache(t *testing.T) { } func TestFileCache(t *testing.T) { - bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}`) + bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`) if err != nil { t.Error("init err") } From 3086081ec02803c7cb73fc7c40b7c656698b36dc Mon Sep 17 00:00:00 2001 From: astaxie Date: Sat, 6 Apr 2019 13:50:14 +0800 Subject: [PATCH 089/112] v1.11.2 --- beego.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beego.go b/beego.go index ff89f2f5..7ebea8a2 100644 --- a/beego.go +++ b/beego.go @@ -23,7 +23,7 @@ import ( const ( // VERSION represent beego web framework version. - VERSION = "1.11.1" + VERSION = "1.11.2" // DEV is for develop DEV = "dev" From fa97488bdc130ae71abb09a0f769f76ad78586ed Mon Sep 17 00:00:00 2001 From: guanle <270464839@qq.com> Date: Sun, 21 Apr 2019 10:27:35 +0800 Subject: [PATCH 090/112] Update templatefunc.go --- templatefunc.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/templatefunc.go b/templatefunc.go index 5ef9a041..d62442ae 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -300,7 +300,12 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e formValues := form[tag] var value string if len(formValues) == 0 { - continue + defaultValue := fieldT.Tag.Get("default") + if defaultValue != "" { + value = defaultValue + } else { + continue + } } if len(formValues) == 1 { value = formValues[0] From 0b165b78a1a00631eaf881f634c8aa8b15969f36 Mon Sep 17 00:00:00 2001 From: hetingyao Date: Mon, 22 Apr 2019 22:18:37 +0800 Subject: [PATCH 091/112] make routers configurable for beego multi-instance in the same repo --- parser.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 81990a4a..5e6b9111 100644 --- a/parser.go +++ b/parser.go @@ -35,7 +35,7 @@ import ( "github.com/astaxie/beego/utils" ) -var globalRouterTemplate = `package routers +var globalRouterTemplate = `package {{.routersDir}} import ( "github.com/astaxie/beego" @@ -516,7 +516,9 @@ func genRouterCode(pkgRealpath string) { } defer f.Close() + routersDir := AppConfig.DefaultString("routersdir", "routers") content := strings.Replace(globalRouterTemplate, "{{.globalinfo}}", globalinfo, -1) + content = strings.Replace(content, "{{.routersDir}}", routersDir, -1) content = strings.Replace(content, "{{.globalimport}}", globalimport, -1) f.WriteString(content) } @@ -574,7 +576,8 @@ func getpathTime(pkgRealpath string) (lastupdate int64, err error) { func getRouterDir(pkgRealpath string) string { dir := filepath.Dir(pkgRealpath) for { - d := filepath.Join(dir, "routers") + routersDir := AppConfig.DefaultString("routersdir", "routers") + d := filepath.Join(dir, routersDir) if utils.FileExists(d) { return d } From afb787d49db39d37047b48fbfa139bc7651dd973 Mon Sep 17 00:00:00 2001 From: Yang Luo Date: Sat, 27 Apr 2019 16:55:42 +0800 Subject: [PATCH 092/112] remove the 1000-row limit for ORM result set --- orm/orm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orm/orm.go b/orm/orm.go index fc3cd400..d322881b 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -72,7 +72,7 @@ const ( var ( Debug = false DebugLog = NewLog(os.Stdout) - DefaultRowsLimit = 1000 + DefaultRowsLimit = -1 DefaultRelsDepth = 2 DefaultTimeLoc = time.Local ErrTxHasBegan = errors.New(" transaction already begin") From a9629f707e37883b491e058e03dfb870543dda75 Mon Sep 17 00:00:00 2001 From: haley Date: Sun, 28 Apr 2019 08:50:30 +0800 Subject: [PATCH 093/112] route request put amendment --- router.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/router.go b/router.go index 997b6854..e00c1b36 100644 --- a/router.go +++ b/router.go @@ -779,7 +779,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) runRouter = routerInfo.controllerType methodParams = routerInfo.methodParams method := r.Method - if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodPost { + if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodPut { method = http.MethodPut } if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodDelete { From 0939e8e4933b487c857faf2ab9709e81c37a50f4 Mon Sep 17 00:00:00 2001 From: Wusuluren <1634636348@qq.com> Date: Tue, 30 Apr 2019 00:15:24 +0800 Subject: [PATCH 094/112] fix concurrent map access problem on BeegoInput.data --- context/input.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/context/input.go b/context/input.go index 81952158..0cf80924 100644 --- a/context/input.go +++ b/context/input.go @@ -27,6 +27,7 @@ import ( "regexp" "strconv" "strings" + "sync" "github.com/astaxie/beego/session" ) @@ -49,6 +50,7 @@ type BeegoInput struct { pnames []string pvalues []string data map[interface{}]interface{} // store some values in this context when calling context in filter or controller. + dataLock sync.RWMutex RequestBody []byte RunMethod string RunController reflect.Type @@ -204,6 +206,7 @@ func (input *BeegoInput) AcceptsXML() bool { func (input *BeegoInput) AcceptsJSON() bool { return acceptsJSONRegex.MatchString(input.Header("Accept")) } + // AcceptsYAML Checks if request accepts json response func (input *BeegoInput) AcceptsYAML() bool { return acceptsYAMLRegex.MatchString(input.Header("Accept")) @@ -385,6 +388,8 @@ func (input *BeegoInput) Data() map[interface{}]interface{} { // GetData returns the stored data in this context. func (input *BeegoInput) GetData(key interface{}) interface{} { + input.dataLock.Lock() + defer input.dataLock.Unlock() if v, ok := input.data[key]; ok { return v } @@ -394,6 +399,8 @@ func (input *BeegoInput) GetData(key interface{}) interface{} { // SetData stores data with given key in this context. // This data are only available in this context. func (input *BeegoInput) SetData(key, val interface{}) { + input.dataLock.Lock() + defer input.dataLock.Unlock() if input.data == nil { input.data = make(map[interface{}]interface{}) } From 8748de95c73ebf215c19b61d00115e21ac4d4504 Mon Sep 17 00:00:00 2001 From: Guo Date: Tue, 30 Apr 2019 06:43:25 +0800 Subject: [PATCH 095/112] fix:utils.GetGOPATHs() when go version equal or after go1.10 func does not return defaultGoPATH() --- utils/utils.go | 61 ++++++++++++++++++++++++++++++++++++++++++++- utils/utils_test.go | 36 ++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 utils/utils_test.go diff --git a/utils/utils.go b/utils/utils.go index ed885787..3874b803 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -3,19 +3,78 @@ package utils import ( "os" "path/filepath" + "regexp" "runtime" + "strconv" "strings" ) // GetGOPATHs returns all paths in GOPATH variable. func GetGOPATHs() []string { gopath := os.Getenv("GOPATH") - if gopath == "" && strings.Compare(runtime.Version(), "go1.8") >= 0 { + if gopath == "" && compareGoVersion(runtime.Version(), "go1.8") >= 0 { gopath = defaultGOPATH() } return filepath.SplitList(gopath) } +func compareGoVersion(a, b string) int { + reg := regexp.MustCompile("^\\d*") + + a = strings.TrimPrefix(a, "go") + b = strings.TrimPrefix(b, "go") + + versionsA := strings.Split(a, ".") + versionsB := strings.Split(b, ".") + + for i := 0; i < len(versionsA) && i < len(versionsB); i++ { + versionA := versionsA[i] + versionB := versionsB[i] + + vA, err := strconv.Atoi(versionA) + if err != nil { + str := reg.FindString(versionA) + if str != "" { + vA, _ = strconv.Atoi(str) + } else { + vA = -1 + } + } + + vB, err := strconv.Atoi(versionB) + if err != nil { + str := reg.FindString(versionB) + if str != "" { + vB, _ = strconv.Atoi(str) + } else { + vB = -1 + } + } + + if vA > vB { + // vA = 12, vB = 8 + return 1 + } else if vA < vB { + // vA = 6, vB = 8 + return -1 + } else if vA == -1 { + // vA = rc1, vB = rc3 + return strings.Compare(versionA, versionB) + } + + // vA = vB = 8 + continue + } + + if len(versionsA) > len(versionsB) { + return 1 + } else if len(versionsA) == len(versionsB) { + return 0 + } + + return -1 +} + func defaultGOPATH() string { env := "HOME" if runtime.GOOS == "windows" { diff --git a/utils/utils_test.go b/utils/utils_test.go new file mode 100644 index 00000000..ced6f63f --- /dev/null +++ b/utils/utils_test.go @@ -0,0 +1,36 @@ +package utils + +import ( + "testing" +) + +func TestCompareGoVersion(t *testing.T) { + targetVersion := "go1.8" + if compareGoVersion("go1.12.4", targetVersion) != 1 { + t.Error("should be 1") + } + + if compareGoVersion("go1.8.7", targetVersion) != 1 { + t.Error("should be 1") + } + + if compareGoVersion("go1.8", targetVersion) != 0 { + t.Error("should be 0") + } + + if compareGoVersion("go1.7.6", targetVersion) != -1 { + t.Error("should be -1") + } + + if compareGoVersion("go1.12.1rc1", targetVersion) != 1 { + t.Error("should be 1") + } + + if compareGoVersion("go1.8rc1", targetVersion) != 0 { + t.Error("should be 0") + } + + if compareGoVersion("go1.7rc1", targetVersion) != -1 { + t.Error("should be -1") + } +} From 39bd40e512fad75af4739b93c6ed13734d7fc899 Mon Sep 17 00:00:00 2001 From: "Edward.Yang" Date: Wed, 1 May 2019 13:10:21 +0800 Subject: [PATCH 096/112] =?UTF-8?q?Incr=E5=92=8CDecr=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E6=94=B9=E6=88=90=E6=8E=92=E5=AE=83=E9=94=81=EF=BC=8C=E5=90=A6?= =?UTF-8?q?=E5=88=99=E5=9C=A8=E5=B9=B6=E5=8F=91=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=E4=BC=9A=E5=87=BA=E7=8E=B0=E9=9D=9E=E6=9C=9F=E6=9C=9B=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cache/cache_test.go | 23 +++++++++++++++++++++++ cache/memory.go | 8 ++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cache/cache_test.go b/cache/cache_test.go index 1e71d075..470c0a43 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -16,10 +16,33 @@ package cache import ( "os" + "sync" "testing" "time" ) +func TestCacheIncr(t *testing.T) { + bm, err := NewCache("memory", `{"interval":20}`) + if err != nil { + t.Error("init err") + } + //timeoutDuration := 10 * time.Second + + bm.Put("edwardhey", 0, time.Second*20) + wg := sync.WaitGroup{} + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + defer wg.Done() + bm.Incr("edwardhey") + }() + } + wg.Wait() + if bm.Get("edwardhey").(int) != 10 { + t.Error("Incr err") + } +} + func TestCache(t *testing.T) { bm, err := NewCache("memory", `{"interval":20}`) if err != nil { diff --git a/cache/memory.go b/cache/memory.go index e5b562f0..1fec2eff 100644 --- a/cache/memory.go +++ b/cache/memory.go @@ -110,8 +110,8 @@ func (bc *MemoryCache) Delete(name string) error { // Incr increase cache counter in memory. // it supports int,int32,int64,uint,uint32,uint64. func (bc *MemoryCache) Incr(key string) error { - bc.RLock() - defer bc.RUnlock() + bc.Lock() + defer bc.Unlock() itm, ok := bc.items[key] if !ok { return errors.New("key not exist") @@ -137,8 +137,8 @@ func (bc *MemoryCache) Incr(key string) error { // Decr decrease counter in memory. func (bc *MemoryCache) Decr(key string) error { - bc.RLock() - defer bc.RUnlock() + bc.Lock() + defer bc.Unlock() itm, ok := bc.items[key] if !ok { return errors.New("key not exist") From a0ca3d61d6ab36f960b31a969081ead439701ffc Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Wed, 8 May 2019 23:11:57 +0800 Subject: [PATCH 097/112] update --- orm/db.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/orm/db.go b/orm/db.go index 20d9c4cd..2148daaa 100644 --- a/orm/db.go +++ b/orm/db.go @@ -621,20 +621,31 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. return 0, err } - var find bool + var findAutoNowAdd, findAutoNow bool var index int for i, col := range setNames { if mi.fields.GetByColumn(col).autoNowAdd { index = i - find = true + findAutoNowAdd = true + } + if mi.fields.GetByColumn(col).autoNow { + findAutoNow = true } } - - if find { + if findAutoNowAdd { setNames = append(setNames[0:index], setNames[index+1:]...) setValues = append(setValues[0:index], setValues[index+1:]...) } + if !findAutoNow { + for col, info := range mi.fields.columns { + if info.autoNow { + setNames = append(setNames, col) + setValues = append(setValues, time.Now()) + } + } + } + setValues = append(setValues, pkValue) Q := d.ins.TableQuote() From fcacfc08e3c8d8da9cb307d77e3a60bb34d1b415 Mon Sep 17 00:00:00 2001 From: Priyesh <43954392+priyesh-lb@users.noreply.github.com> Date: Fri, 17 May 2019 16:19:26 +0530 Subject: [PATCH 098/112] Beego skipping some migrations Beego skipping some migrations #3657 --- migration/migration.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/migration/migration.go b/migration/migration.go index 97e10c2e..5ddfd972 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -176,8 +176,9 @@ func Register(name string, m Migrationer) error { func Upgrade(lasttime int64) error { sm := sortMap(migrationMap) i := 0 + migs, _ := getAllMigrations() for _, v := range sm { - if v.created > lasttime { + if _, ok := migs[v.name]; !ok { logs.Info("start upgrade", v.name) v.m.Reset() v.m.Up() @@ -310,3 +311,20 @@ func isRollBack(name string) bool { } return false } +func getAllMigrations() (map[string]string, error) { + o := orm.NewOrm() + var maps []orm.Params + migs := make(map[string]string) + num, err := o.Raw("select * from migrations order by id_migration desc").Values(&maps) + if err != nil { + logs.Info("get name has error", err) + return migs, err + } + if num > 0 { + for _, v := range maps { + name := v["name"].(string) + migs[name] = v["status"].(string) + } + } + return migs, nil +} From 3c046a4dbfb1a40e5bb1118e368eca11d3cc23a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=8B=87?= Date: Mon, 27 May 2019 16:38:30 +0800 Subject: [PATCH 099/112] fix two typos --- orm/models_utils.go | 2 +- orm/types.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/orm/models_utils.go b/orm/models_utils.go index 13a22aca..71127a6b 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -66,7 +66,7 @@ func getTableName(val reflect.Value) string { return snakeString(reflect.Indirect(val).Type().Name()) } -// get table engine, mysiam or innodb. +// get table engine, myisam or innodb. func getTableEngine(val reflect.Value) string { fun := val.MethodByName("TableEngine") if fun.IsValid() { diff --git a/orm/types.go b/orm/types.go index 6c6443c7..2fd10774 100644 --- a/orm/types.go +++ b/orm/types.go @@ -55,7 +55,7 @@ type Ormer interface { // for example: // user := new(User) // id, err = Ormer.Insert(user) - // user must a pointer and Insert will set user's pk field + // 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") // if colu type is integer : can use(+-*/), string : convert(colu,"value") From 649c5c861db6fc7a08b40628226ade275da66dbb Mon Sep 17 00:00:00 2001 From: oberontang Date: Fri, 31 May 2019 15:47:21 +0800 Subject: [PATCH 100/112] fix bugs of ParseForm about time in RFC3339 format --- templatefunc.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templatefunc.go b/templatefunc.go index d62442ae..ba1ec5eb 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -361,6 +361,8 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e if len(value) >= 25 { value = value[:25] t, err = time.ParseInLocation(time.RFC3339, value, time.Local) + } else if strings.HasSuffix(strings.ToUpper(value), "Z") { + t, err = time.ParseInLocation(time.RFC3339, value, time.Local) } else if len(value) >= 19 { if strings.Contains(value, "T") { value = value[:19] From cc0eacbe023b95f74c240b35419c14722df45041 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Sat, 8 Jun 2019 23:53:42 +0800 Subject: [PATCH 101/112] update --- orm/db_alias.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++--- orm/orm.go | 9 +++-- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/orm/db_alias.go b/orm/db_alias.go index a43e70e3..2f624da1 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -15,6 +15,7 @@ package orm import ( + "context" "database/sql" "fmt" "reflect" @@ -103,6 +104,89 @@ func (ac *_dbCache) getDefault() (al *alias) { return } +type DB struct { + *sync.RWMutex + DB *sql.DB + stmts map[string]*sql.Stmt +} + +func (d *DB) getStmt(query string) (*sql.Stmt, error) { + d.RLock() + if stmt, ok := d.stmts[query]; ok { + d.RUnlock() + return stmt, nil + } + + stmt, err := d.Prepare(query) + if err != nil { + return nil, err + } + d.Lock() + d.stmts[query] = stmt + d.Unlock() + return stmt, nil +} + +func (d *DB) Prepare(query string) (*sql.Stmt, error) { + return d.DB.Prepare(query) +} + +func (d *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) { + return d.DB.PrepareContext(ctx, query) +} + +func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) { + stmt, err := d.getStmt(query) + if err != nil { + return nil, err + } + return stmt.Exec(args) +} + +func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { + stmt, err := d.getStmt(query) + if err != nil { + return nil, err + } + return stmt.ExecContext(ctx, args) +} + +func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) { + stmt, err := d.getStmt(query) + if err != nil { + return nil, err + } + return stmt.Query(args) +} + +func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { + stmt, err := d.getStmt(query) + if err != nil { + return nil, err + } + return stmt.QueryContext(ctx, args) +} + +func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { + stmt, err := d.getStmt(query) + if err != nil { + panic(err) + return nil + } + return stmt.QueryRow(args) + +} + +func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { + + stmt, err := d.getStmt(query) + if err != nil { + panic(err) + return nil + } + return stmt.QueryRowContext(ctx, args) +} + type alias struct { Name string Driver DriverType @@ -110,7 +194,7 @@ type alias struct { DataSource string MaxIdleConns int MaxOpenConns int - DB *sql.DB + DB *DB DbBaser dbBaser TZ *time.Location Engine string @@ -176,7 +260,10 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) { al := new(alias) al.Name = aliasName al.DriverName = driverName - al.DB = db + al.DB = &DB{ + DB: db, + stmts: make(map[string]*sql.Stmt), + } if dr, ok := drivers[driverName]; ok { al.DbBaser = dbBasers[dr] @@ -272,7 +359,7 @@ func SetDataBaseTZ(aliasName string, tz *time.Location) error { func SetMaxIdleConns(aliasName string, maxIdleConns int) { al := getDbAlias(aliasName) al.MaxIdleConns = maxIdleConns - al.DB.SetMaxIdleConns(maxIdleConns) + al.DB.DB.SetMaxIdleConns(maxIdleConns) } // SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name @@ -296,7 +383,7 @@ func GetDB(aliasNames ...string) (*sql.DB, error) { } al, ok := dataBaseCache.get(name) if ok { - return al.DB, nil + return al.DB.DB, nil } return nil, fmt.Errorf("DataBase of alias name `%s` not found", name) } diff --git a/orm/orm.go b/orm/orm.go index d322881b..0239428f 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -60,6 +60,7 @@ import ( "fmt" "os" "reflect" + "sync" "time" ) @@ -525,7 +526,7 @@ func (o *orm) Driver() Driver { // return sql.DBStats for current database func (o *orm) DBStats() *sql.DBStats { if o.alias != nil && o.alias.DB != nil { - stats := o.alias.DB.Stats() + stats := o.alias.DB.DB.Stats() return &stats } @@ -558,7 +559,11 @@ func NewOrmWithDB(driverName, aliasName string, db *sql.DB) (Ormer, error) { al.Name = aliasName al.DriverName = driverName - al.DB = db + al.DB = &DB{ + RWMutex: new(sync.RWMutex), + DB: db, + stmts: make(map[string]*sql.Stmt), + } detectTZ(al) From 873f62edff047d41b2b53a86f1fb9963b40698db Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Sun, 9 Jun 2019 01:19:17 +0800 Subject: [PATCH 102/112] update --- orm/db_alias.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/orm/db_alias.go b/orm/db_alias.go index 2f624da1..a581d82d 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -116,6 +116,7 @@ func (d *DB) getStmt(query string) (*sql.Stmt, error) { d.RUnlock() return stmt, nil } + d.RUnlock() stmt, err := d.Prepare(query) if err != nil { @@ -140,7 +141,7 @@ func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) { if err != nil { return nil, err } - return stmt.Exec(args) + return stmt.Exec(args...) } func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { @@ -148,7 +149,7 @@ func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) if err != nil { return nil, err } - return stmt.ExecContext(ctx, args) + return stmt.ExecContext(ctx, args...) } func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) { @@ -156,7 +157,7 @@ func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) { if err != nil { return nil, err } - return stmt.Query(args) + return stmt.Query(args...) } func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) { @@ -164,7 +165,7 @@ func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{} if err != nil { return nil, err } - return stmt.QueryContext(ctx, args) + return stmt.QueryContext(ctx, args...) } func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { @@ -173,7 +174,7 @@ func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { panic(err) return nil } - return stmt.QueryRow(args) + return stmt.QueryRow(args...) } @@ -261,8 +262,9 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) { al.Name = aliasName al.DriverName = driverName al.DB = &DB{ - DB: db, - stmts: make(map[string]*sql.Stmt), + RWMutex: new(sync.RWMutex), + DB: db, + stmts: make(map[string]*sql.Stmt), } if dr, ok := drivers[driverName]; ok { From b17e49e6aae4ef19a649104e654b7dd8acbcd2f0 Mon Sep 17 00:00:00 2001 From: Wusuluren <1634636348@qq.com> Date: Tue, 30 Apr 2019 00:15:24 +0800 Subject: [PATCH 103/112] fix concurrent map access problem on BeegoInput.data --- context/input.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/context/input.go b/context/input.go index 81952158..76040616 100644 --- a/context/input.go +++ b/context/input.go @@ -27,6 +27,7 @@ import ( "regexp" "strconv" "strings" + "sync" "github.com/astaxie/beego/session" ) @@ -49,6 +50,7 @@ type BeegoInput struct { pnames []string pvalues []string data map[interface{}]interface{} // store some values in this context when calling context in filter or controller. + dataLock sync.RWMutex RequestBody []byte RunMethod string RunController reflect.Type @@ -204,6 +206,7 @@ func (input *BeegoInput) AcceptsXML() bool { func (input *BeegoInput) AcceptsJSON() bool { return acceptsJSONRegex.MatchString(input.Header("Accept")) } + // AcceptsYAML Checks if request accepts json response func (input *BeegoInput) AcceptsYAML() bool { return acceptsYAMLRegex.MatchString(input.Header("Accept")) @@ -377,6 +380,8 @@ func (input *BeegoInput) CopyBody(MaxMemory int64) []byte { // Data return the implicit data in the input func (input *BeegoInput) Data() map[interface{}]interface{} { + input.dataLock.Lock() + defer input.dataLock.Unlock() if input.data == nil { input.data = make(map[interface{}]interface{}) } @@ -385,6 +390,8 @@ func (input *BeegoInput) Data() map[interface{}]interface{} { // GetData returns the stored data in this context. func (input *BeegoInput) GetData(key interface{}) interface{} { + input.dataLock.Lock() + defer input.dataLock.Unlock() if v, ok := input.data[key]; ok { return v } @@ -394,6 +401,8 @@ func (input *BeegoInput) GetData(key interface{}) interface{} { // SetData stores data with given key in this context. // This data are only available in this context. func (input *BeegoInput) SetData(key, val interface{}) { + input.dataLock.Lock() + defer input.dataLock.Unlock() if input.data == nil { input.data = make(map[interface{}]interface{}) } From 394a73c75feca441ee61920e8b918c27e27f30eb Mon Sep 17 00:00:00 2001 From: luxueyan Date: Fri, 14 Jun 2019 14:43:02 +0800 Subject: [PATCH 104/112] fix orm datarace --- orm/models_boot.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orm/models_boot.go b/orm/models_boot.go index badfd11b..456e5896 100644 --- a/orm/models_boot.go +++ b/orm/models_boot.go @@ -335,11 +335,11 @@ func RegisterModelWithSuffix(suffix string, models ...interface{}) { // BootStrap bootstrap models. // make all model parsed and can not add more models func BootStrap() { + modelCache.Lock() + defer modelCache.Unlock() if modelCache.done { return } - modelCache.Lock() - defer modelCache.Unlock() bootStrap() modelCache.done = true } From 06692c3e27a93c09d6ac60ac1931ded2af1ba1b9 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Mon, 17 Jun 2019 23:38:07 +0800 Subject: [PATCH 105/112] update --- orm/orm.go | 1 - 1 file changed, 1 deletion(-) diff --git a/orm/orm.go b/orm/orm.go index 0239428f..11e38fd9 100644 --- a/orm/orm.go +++ b/orm/orm.go @@ -529,7 +529,6 @@ func (o *orm) DBStats() *sql.DBStats { stats := o.alias.DB.DB.Stats() return &stats } - return nil } From 62d96c2e9377c62b9be988a3c5c1341d6da8fc14 Mon Sep 17 00:00:00 2001 From: Luqmanul Hakim Date: Tue, 25 Jun 2019 08:04:21 +0700 Subject: [PATCH 106/112] router.go: add comment func LogAccess --- router.go | 1 + 1 file changed, 1 insertion(+) diff --git a/router.go b/router.go index b30d2b17..3593be4c 100644 --- a/router.go +++ b/router.go @@ -971,6 +971,7 @@ func toURL(params map[string]string) string { return strings.TrimRight(u, "&") } +// LogAccess logging info HTTP Access func LogAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) { //Skip logging if AccessLogs config is false if !BConfig.Log.AccessLogs { From 8cfd7f5c1995adb77477816365b30428d94552dc Mon Sep 17 00:00:00 2001 From: hsht Date: Fri, 28 Jun 2019 20:09:23 +0800 Subject: [PATCH 107/112] =?UTF-8?q?email=E7=9A=84Attach=E5=92=8CAttachFile?= =?UTF-8?q?=20=E7=9A=84=E5=8F=82=E6=95=B0=E6=A3=80=E6=9F=A5=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=9C=89=E8=AF=AF=E3=80=82len(args)=20<=201=20&&=20le?= =?UTF-8?q?n(args)=20>=202=20=E6=94=B9=E4=B8=BA=20len(args)=20<=201=20||?= =?UTF-8?q?=20len(args)=20>=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/mail.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/mail.go b/utils/mail.go index e3fa1c90..42b1e4d4 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -162,7 +162,7 @@ func (e *Email) Bytes() ([]byte, error) { // AttachFile Add attach file to the send mail func (e *Email) AttachFile(args ...string) (a *Attachment, err error) { - if len(args) < 1 && len(args) > 2 { + if len(args) < 1 || len(args) > 2 { // change && to || err = errors.New("Must specify a file name and number of parameters can not exceed at least two") return } @@ -183,7 +183,7 @@ func (e *Email) AttachFile(args ...string) (a *Attachment, err error) { // Attach is used to attach content from an io.Reader to the email. // Parameters include an io.Reader, the desired filename for the attachment, and the Content-Type. func (e *Email) Attach(r io.Reader, filename string, args ...string) (a *Attachment, err error) { - if len(args) < 1 && len(args) > 2 { + if len(args) < 1 || len(args) > 2 { // change && to || err = errors.New("Must specify the file type and number of parameters can not exceed at least two") return } From 5d0c0a03d70d9b6fe32387e364e57d26f9161231 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Fri, 28 Jun 2019 22:56:32 +0800 Subject: [PATCH 108/112] update --- orm/db_alias.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/orm/db_alias.go b/orm/db_alias.go index a581d82d..9cb42748 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -172,7 +172,6 @@ func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row { stmt, err := d.getStmt(query) if err != nil { panic(err) - return nil } return stmt.QueryRow(args...) @@ -183,7 +182,6 @@ func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interfac stmt, err := d.getStmt(query) if err != nil { panic(err) - return nil } return stmt.QueryRowContext(ctx, args) } From 40078cba2cc3e243801b731e9a50aeab20eff4a8 Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Fri, 28 Jun 2019 23:13:18 +0800 Subject: [PATCH 109/112] update --- orm/db_alias.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/orm/db_alias.go b/orm/db_alias.go index 9cb42748..51ce10f3 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -110,6 +110,14 @@ type DB struct { stmts map[string]*sql.Stmt } +func (d *DB) Begin() (*sql.Tx, error) { + return d.DB.Begin() +} + +func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { + return d.DB.BeginTx(ctx, opts) +} + func (d *DB) getStmt(query string) (*sql.Stmt, error) { d.RLock() if stmt, ok := d.stmts[query]; ok { From 2909ff336667627a34edd5c9625c1e6812a6a85f Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Fri, 28 Jun 2019 23:23:01 +0800 Subject: [PATCH 110/112] update --- orm/db_alias.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/orm/db_alias.go b/orm/db_alias.go index 51ce10f3..74b5ec7d 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -105,17 +105,61 @@ func (ac *_dbCache) getDefault() (al *alias) { } type DB struct { + inTx bool + tx *sql.Tx *sync.RWMutex DB *sql.DB stmts map[string]*sql.Stmt } func (d *DB) Begin() (*sql.Tx, error) { - return d.DB.Begin() + if d.inTx { + return nil, ErrTxHasBegan + } + tx, err := d.DB.Begin() + if err != nil { + return nil, err + } + d.inTx = true + d.tx = tx + return d.tx, nil } func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { - return d.DB.BeginTx(ctx, opts) + if d.inTx { + return nil, ErrTxHasBegan + } + tx, err := d.DB.BeginTx(ctx, opts) + if err != nil { + return nil, err + } + d.inTx = true + d.tx = tx + return d.tx, nil +} + +func (d *DB) Commit() error { + if !d.inTx { + return ErrTxDone + } + err := d.tx.Commit() + if err != nil { + return err + } + d.inTx = false + return nil +} + +func (d *DB) Rollback() error { + if !d.inTx { + return ErrTxDone + } + err := d.tx.Commit() + if err != nil { + return err + } + d.inTx = false + return nil } func (d *DB) getStmt(query string) (*sql.Stmt, error) { From 5bcde306ea05300ae36282eece1353ce2d82749f Mon Sep 17 00:00:00 2001 From: BaoyangChai Date: Fri, 28 Jun 2019 23:37:32 +0800 Subject: [PATCH 111/112] Revert "update" This reverts commit 2909ff336667627a34edd5c9625c1e6812a6a85f. --- orm/db_alias.go | 48 ++---------------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/orm/db_alias.go b/orm/db_alias.go index 74b5ec7d..51ce10f3 100644 --- a/orm/db_alias.go +++ b/orm/db_alias.go @@ -105,61 +105,17 @@ func (ac *_dbCache) getDefault() (al *alias) { } type DB struct { - inTx bool - tx *sql.Tx *sync.RWMutex DB *sql.DB stmts map[string]*sql.Stmt } func (d *DB) Begin() (*sql.Tx, error) { - if d.inTx { - return nil, ErrTxHasBegan - } - tx, err := d.DB.Begin() - if err != nil { - return nil, err - } - d.inTx = true - d.tx = tx - return d.tx, nil + return d.DB.Begin() } func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) { - if d.inTx { - return nil, ErrTxHasBegan - } - tx, err := d.DB.BeginTx(ctx, opts) - if err != nil { - return nil, err - } - d.inTx = true - d.tx = tx - return d.tx, nil -} - -func (d *DB) Commit() error { - if !d.inTx { - return ErrTxDone - } - err := d.tx.Commit() - if err != nil { - return err - } - d.inTx = false - return nil -} - -func (d *DB) Rollback() error { - if !d.inTx { - return ErrTxDone - } - err := d.tx.Commit() - if err != nil { - return err - } - d.inTx = false - return nil + return d.DB.BeginTx(ctx, opts) } func (d *DB) getStmt(query string) (*sql.Stmt, error) { From de7ce2f9b02dc0f4afe4f7c0a0304cfecb1b62c1 Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 5 Jul 2019 11:58:41 +0800 Subject: [PATCH 112/112] v1.12.0 --- beego.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beego.go b/beego.go index 7ebea8a2..66b19f36 100644 --- a/beego.go +++ b/beego.go @@ -23,7 +23,7 @@ import ( const ( // VERSION represent beego web framework version. - VERSION = "1.11.2" + VERSION = "1.12.0" // DEV is for develop DEV = "dev"