- {{end}}
-
-See also
-
-http://beego.me/docs/mvc/view/page.md
-
-*/
-package pagination
diff --git a/core/utils/rand_test.go b/core/utils/rand_test.go
deleted file mode 100644
index 6c238b5e..00000000
--- a/core/utils/rand_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 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 utils
-
-import "testing"
-
-func TestRand_01(t *testing.T) {
- bs0 := RandomCreateBytes(16)
- bs1 := RandomCreateBytes(16)
-
- t.Log(string(bs0), string(bs1))
- if string(bs0) == string(bs1) {
- t.FailNow()
- }
-
- bs0 = RandomCreateBytes(4, []byte(`a`)...)
-
- if string(bs0) != "aaaa" {
- t.FailNow()
- }
-}
diff --git a/core/utils/safemap_test.go b/core/utils/safemap_test.go
deleted file mode 100644
index 65085195..00000000
--- a/core/utils/safemap_test.go
+++ /dev/null
@@ -1,89 +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 utils
-
-import "testing"
-
-var safeMap *BeeMap
-
-func TestNewBeeMap(t *testing.T) {
- safeMap = NewBeeMap()
- if safeMap == nil {
- t.Fatal("expected to return non-nil BeeMap", "got", safeMap)
- }
-}
-
-func TestSet(t *testing.T) {
- safeMap = NewBeeMap()
- if ok := safeMap.Set("astaxie", 1); !ok {
- t.Error("expected", true, "got", false)
- }
-}
-
-func TestReSet(t *testing.T) {
- safeMap := NewBeeMap()
- if ok := safeMap.Set("astaxie", 1); !ok {
- t.Error("expected", true, "got", false)
- }
- // set diff value
- if ok := safeMap.Set("astaxie", -1); !ok {
- t.Error("expected", true, "got", false)
- }
-
- // set same value
- if ok := safeMap.Set("astaxie", -1); ok {
- t.Error("expected", false, "got", true)
- }
-}
-
-func TestCheck(t *testing.T) {
- if exists := safeMap.Check("astaxie"); !exists {
- t.Error("expected", true, "got", false)
- }
-}
-
-func TestGet(t *testing.T) {
- if val := safeMap.Get("astaxie"); val.(int) != 1 {
- t.Error("expected value", 1, "got", val)
- }
-}
-
-func TestDelete(t *testing.T) {
- safeMap.Delete("astaxie")
- if exists := safeMap.Check("astaxie"); exists {
- t.Error("expected element to be deleted")
- }
-}
-
-func TestItems(t *testing.T) {
- safeMap := NewBeeMap()
- safeMap.Set("astaxie", "hello")
- for k, v := range safeMap.Items() {
- key := k.(string)
- value := v.(string)
- if key != "astaxie" {
- t.Error("expected the key should be astaxie")
- }
- if value != "hello" {
- t.Error("expected the value should be hello")
- }
- }
-}
-
-func TestCount(t *testing.T) {
- if count := safeMap.Count(); count != 0 {
- t.Error("expected count to be", 0, "got", count)
- }
-}
diff --git a/core/utils/slice_test.go b/core/utils/slice_test.go
deleted file mode 100644
index 142dec96..00000000
--- a/core/utils/slice_test.go
+++ /dev/null
@@ -1,29 +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 utils
-
-import (
- "testing"
-)
-
-func TestInSlice(t *testing.T) {
- sl := []string{"A", "b"}
- if !InSlice("A", sl) {
- t.Error("should be true")
- }
- if InSlice("B", sl) {
- t.Error("should be false")
- }
-}
diff --git a/core/utils/time.go b/core/utils/time.go
deleted file mode 100644
index 579b292a..00000000
--- a/core/utils/time.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package utils
-
-import (
- "fmt"
- "time"
-)
-
-// short string format
-func ToShortTimeFormat(d time.Duration) string {
-
- u := uint64(d)
- if u < uint64(time.Second) {
- switch {
- case u == 0:
- return "0"
- case u < uint64(time.Microsecond):
- return fmt.Sprintf("%.2fns", float64(u))
- case u < uint64(time.Millisecond):
- return fmt.Sprintf("%.2fus", float64(u)/1000)
- default:
- return fmt.Sprintf("%.2fms", float64(u)/1000/1000)
- }
- } else {
- switch {
- case u < uint64(time.Minute):
- return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000)
- case u < uint64(time.Hour):
- return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60)
- default:
- return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60)
- }
- }
-
-}
diff --git a/core/validation/validation_test.go b/core/validation/validation_test.go
deleted file mode 100644
index bca4f560..00000000
--- a/core/validation/validation_test.go
+++ /dev/null
@@ -1,634 +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 validation
-
-import (
- "regexp"
- "testing"
- "time"
-)
-
-func TestRequired(t *testing.T) {
- valid := Validation{}
-
- if valid.Required(nil, "nil").Ok {
- t.Error("nil object should be false")
- }
- if !valid.Required(true, "bool").Ok {
- t.Error("Bool value should always return true")
- }
- if !valid.Required(false, "bool").Ok {
- t.Error("Bool value should always return true")
- }
- if valid.Required("", "string").Ok {
- t.Error("\"'\" string should be false")
- }
- if valid.Required(" ", "string").Ok {
- t.Error("\" \" string should be false") // For #2361
- }
- if valid.Required("\n", "string").Ok {
- t.Error("new line string should be false") // For #2361
- }
- if !valid.Required("astaxie", "string").Ok {
- t.Error("string should be true")
- }
- if valid.Required(0, "zero").Ok {
- t.Error("Integer should not be equal 0")
- }
- if !valid.Required(1, "int").Ok {
- t.Error("Integer except 0 should be true")
- }
- if !valid.Required(time.Now(), "time").Ok {
- t.Error("time should be true")
- }
- if valid.Required([]string{}, "emptySlice").Ok {
- t.Error("empty slice should be false")
- }
- if !valid.Required([]interface{}{"ok"}, "slice").Ok {
- t.Error("slice should be true")
- }
-}
-
-func TestMin(t *testing.T) {
- valid := Validation{}
-
- if valid.Min(-1, 0, "min0").Ok {
- t.Error("-1 is less than the minimum value of 0 should be false")
- }
- if !valid.Min(1, 0, "min0").Ok {
- t.Error("1 is greater or equal than the minimum value of 0 should be true")
- }
-}
-
-func TestMax(t *testing.T) {
- valid := Validation{}
-
- if valid.Max(1, 0, "max0").Ok {
- t.Error("1 is greater than the minimum value of 0 should be false")
- }
- if !valid.Max(-1, 0, "max0").Ok {
- t.Error("-1 is less or equal than the maximum value of 0 should be true")
- }
-}
-
-func TestRange(t *testing.T) {
- valid := Validation{}
-
- if valid.Range(-1, 0, 1, "range0_1").Ok {
- t.Error("-1 is between 0 and 1 should be false")
- }
- if !valid.Range(1, 0, 1, "range0_1").Ok {
- t.Error("1 is between 0 and 1 should be true")
- }
-}
-
-func TestMinSize(t *testing.T) {
- valid := Validation{}
-
- if valid.MinSize("", 1, "minSize1").Ok {
- t.Error("the length of \"\" is less than the minimum value of 1 should be false")
- }
- if !valid.MinSize("ok", 1, "minSize1").Ok {
- t.Error("the length of \"ok\" is greater or equal than the minimum value of 1 should be true")
- }
- if valid.MinSize([]string{}, 1, "minSize1").Ok {
- t.Error("the length of empty slice is less than the minimum value of 1 should be false")
- }
- if !valid.MinSize([]interface{}{"ok"}, 1, "minSize1").Ok {
- t.Error("the length of [\"ok\"] is greater or equal than the minimum value of 1 should be true")
- }
-}
-
-func TestMaxSize(t *testing.T) {
- valid := Validation{}
-
- if valid.MaxSize("ok", 1, "maxSize1").Ok {
- t.Error("the length of \"ok\" is greater than the maximum value of 1 should be false")
- }
- if !valid.MaxSize("", 1, "maxSize1").Ok {
- t.Error("the length of \"\" is less or equal than the maximum value of 1 should be true")
- }
- if valid.MaxSize([]interface{}{"ok", false}, 1, "maxSize1").Ok {
- t.Error("the length of [\"ok\", false] is greater than the maximum value of 1 should be false")
- }
- if !valid.MaxSize([]string{}, 1, "maxSize1").Ok {
- t.Error("the length of empty slice is less or equal than the maximum value of 1 should be true")
- }
-}
-
-func TestLength(t *testing.T) {
- valid := Validation{}
-
- if valid.Length("", 1, "length1").Ok {
- t.Error("the length of \"\" must equal 1 should be false")
- }
- if !valid.Length("1", 1, "length1").Ok {
- t.Error("the length of \"1\" must equal 1 should be true")
- }
- if valid.Length([]string{}, 1, "length1").Ok {
- t.Error("the length of empty slice must equal 1 should be false")
- }
- if !valid.Length([]interface{}{"ok"}, 1, "length1").Ok {
- t.Error("the length of [\"ok\"] must equal 1 should be true")
- }
-}
-
-func TestAlpha(t *testing.T) {
- valid := Validation{}
-
- if valid.Alpha("a,1-@ $", "alpha").Ok {
- t.Error("\"a,1-@ $\" are valid alpha characters should be false")
- }
- if !valid.Alpha("abCD", "alpha").Ok {
- t.Error("\"abCD\" are valid alpha characters should be true")
- }
-}
-
-func TestNumeric(t *testing.T) {
- valid := Validation{}
-
- if valid.Numeric("a,1-@ $", "numeric").Ok {
- t.Error("\"a,1-@ $\" are valid numeric characters should be false")
- }
- if !valid.Numeric("1234", "numeric").Ok {
- t.Error("\"1234\" are valid numeric characters should be true")
- }
-}
-
-func TestAlphaNumeric(t *testing.T) {
- valid := Validation{}
-
- if valid.AlphaNumeric("a,1-@ $", "alphaNumeric").Ok {
- t.Error("\"a,1-@ $\" are valid alpha or numeric characters should be false")
- }
- if !valid.AlphaNumeric("1234aB", "alphaNumeric").Ok {
- t.Error("\"1234aB\" are valid alpha or numeric characters should be true")
- }
-}
-
-func TestMatch(t *testing.T) {
- valid := Validation{}
-
- if valid.Match("suchuangji@gmail", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
- t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be false")
- }
- if !valid.Match("suchuangji@gmail.com", regexp.MustCompile(`^\w+@\w+\.\w+$`), "match").Ok {
- t.Error("\"suchuangji@gmail\" match \"^\\w+@\\w+\\.\\w+$\" should be true")
- }
-}
-
-func TestNoMatch(t *testing.T) {
- valid := Validation{}
-
- if valid.NoMatch("123@gmail", regexp.MustCompile(`[^\w\d]`), "nomatch").Ok {
- t.Error("\"123@gmail\" not match \"[^\\w\\d]\" should be false")
- }
- if !valid.NoMatch("123gmail", regexp.MustCompile(`[^\w\d]`), "match").Ok {
- t.Error("\"123@gmail\" not match \"[^\\w\\d@]\" should be true")
- }
-}
-
-func TestAlphaDash(t *testing.T) {
- valid := Validation{}
-
- if valid.AlphaDash("a,1-@ $", "alphaDash").Ok {
- t.Error("\"a,1-@ $\" are valid alpha or numeric or dash(-_) characters should be false")
- }
- if !valid.AlphaDash("1234aB-_", "alphaDash").Ok {
- t.Error("\"1234aB\" are valid alpha or numeric or dash(-_) characters should be true")
- }
-}
-
-func TestEmail(t *testing.T) {
- valid := Validation{}
-
- if valid.Email("not@a email", "email").Ok {
- t.Error("\"not@a email\" is a valid email address should be false")
- }
- if !valid.Email("suchuangji@gmail.com", "email").Ok {
- t.Error("\"suchuangji@gmail.com\" is a valid email address should be true")
- }
- if valid.Email("@suchuangji@gmail.com", "email").Ok {
- t.Error("\"@suchuangji@gmail.com\" is a valid email address should be false")
- }
- if valid.Email("suchuangji@gmail.com ok", "email").Ok {
- t.Error("\"suchuangji@gmail.com ok\" is a valid email address should be false")
- }
-}
-
-func TestIP(t *testing.T) {
- valid := Validation{}
-
- if valid.IP("11.255.255.256", "IP").Ok {
- t.Error("\"11.255.255.256\" is a valid ip address should be false")
- }
- if !valid.IP("01.11.11.11", "IP").Ok {
- t.Error("\"suchuangji@gmail.com\" is a valid ip address should be true")
- }
-}
-
-func TestBase64(t *testing.T) {
- valid := Validation{}
-
- if valid.Base64("suchuangji@gmail.com", "base64").Ok {
- t.Error("\"suchuangji@gmail.com\" are a valid base64 characters should be false")
- }
- if !valid.Base64("c3VjaHVhbmdqaUBnbWFpbC5jb20=", "base64").Ok {
- t.Error("\"c3VjaHVhbmdqaUBnbWFpbC5jb20=\" are a valid base64 characters should be true")
- }
-}
-
-func TestMobile(t *testing.T) {
- valid := Validation{}
-
- validMobiles := []string{
- "19800008888",
- "18800008888",
- "18000008888",
- "8618300008888",
- "+8614700008888",
- "17300008888",
- "+8617100008888",
- "8617500008888",
- "8617400008888",
- "16200008888",
- "16500008888",
- "16600008888",
- "16700008888",
- "13300008888",
- "14900008888",
- "15300008888",
- "17300008888",
- "17700008888",
- "18000008888",
- "18900008888",
- "19100008888",
- "19900008888",
- "19300008888",
- "13000008888",
- "13100008888",
- "13200008888",
- "14500008888",
- "15500008888",
- "15600008888",
- "16600008888",
- "17100008888",
- "17500008888",
- "17600008888",
- "18500008888",
- "18600008888",
- "13400008888",
- "13500008888",
- "13600008888",
- "13700008888",
- "13800008888",
- "13900008888",
- "14700008888",
- "15000008888",
- "15100008888",
- "15200008888",
- "15800008888",
- "15900008888",
- "17200008888",
- "17800008888",
- "18200008888",
- "18300008888",
- "18400008888",
- "18700008888",
- "18800008888",
- "19800008888",
- }
-
- for _, m := range validMobiles {
- if !valid.Mobile(m, "mobile").Ok {
- t.Error(m + " is a valid mobile phone number should be true")
- }
- }
-}
-
-func TestTel(t *testing.T) {
- valid := Validation{}
-
- if valid.Tel("222-00008888", "telephone").Ok {
- t.Error("\"222-00008888\" is a valid telephone number should be false")
- }
- if !valid.Tel("022-70008888", "telephone").Ok {
- t.Error("\"022-70008888\" is a valid telephone number should be true")
- }
- if !valid.Tel("02270008888", "telephone").Ok {
- t.Error("\"02270008888\" is a valid telephone number should be true")
- }
- if !valid.Tel("70008888", "telephone").Ok {
- t.Error("\"70008888\" is a valid telephone number should be true")
- }
-}
-
-func TestPhone(t *testing.T) {
- valid := Validation{}
-
- if valid.Phone("222-00008888", "phone").Ok {
- t.Error("\"222-00008888\" is a valid phone number should be false")
- }
- if !valid.Mobile("+8614700008888", "phone").Ok {
- t.Error("\"+8614700008888\" is a valid phone number should be true")
- }
- if !valid.Tel("02270008888", "phone").Ok {
- t.Error("\"02270008888\" is a valid phone number should be true")
- }
-}
-
-func TestZipCode(t *testing.T) {
- valid := Validation{}
-
- if valid.ZipCode("", "zipcode").Ok {
- t.Error("\"00008888\" is a valid zipcode should be false")
- }
- if !valid.ZipCode("536000", "zipcode").Ok {
- t.Error("\"536000\" is a valid zipcode should be true")
- }
-}
-
-func TestValid(t *testing.T) {
- type user struct {
- ID int
- Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
- Age int `valid:"Required;Range(1, 140)"`
- }
- valid := Validation{}
-
- u := user{Name: "test@/test/;com", Age: 40}
- b, err := valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if !b {
- t.Error("validation should be passed")
- }
-
- uptr := &user{Name: "test", Age: 40}
- valid.Clear()
- b, err = valid.Valid(uptr)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Error("validation should not be passed")
- }
- if len(valid.Errors) != 1 {
- t.Fatalf("valid errors len should be 1 but got %d", len(valid.Errors))
- }
- if valid.Errors[0].Key != "Name.Match" {
- t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key)
- }
-
- u = user{Name: "test@/test/;com", Age: 180}
- valid.Clear()
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Error("validation should not be passed")
- }
- if len(valid.Errors) != 1 {
- t.Fatalf("valid errors len should be 1 but got %d", len(valid.Errors))
- }
- if valid.Errors[0].Key != "Age.Range." {
- t.Errorf("Message key should be `Age.Range` but got %s", valid.Errors[0].Key)
- }
-}
-
-func TestRecursiveValid(t *testing.T) {
- type User struct {
- ID int
- Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
- Age int `valid:"Required;Range(1, 140)"`
- }
-
- type AnonymouseUser struct {
- ID2 int
- Name2 string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
- Age2 int `valid:"Required;Range(1, 140)"`
- }
-
- type Account struct {
- Password string `valid:"Required"`
- U User
- AnonymouseUser
- }
- valid := Validation{}
-
- u := Account{Password: "abc123_", U: User{}}
- b, err := valid.RecursiveValid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Error("validation should not be passed")
- }
-}
-
-func TestSkipValid(t *testing.T) {
- type User struct {
- ID int
-
- Email string `valid:"Email"`
- ReqEmail string `valid:"Required;Email"`
-
- IP string `valid:"IP"`
- ReqIP string `valid:"Required;IP"`
-
- Mobile string `valid:"Mobile"`
- ReqMobile string `valid:"Required;Mobile"`
-
- Tel string `valid:"Tel"`
- ReqTel string `valid:"Required;Tel"`
-
- Phone string `valid:"Phone"`
- ReqPhone string `valid:"Required;Phone"`
-
- ZipCode string `valid:"ZipCode"`
- ReqZipCode string `valid:"Required;ZipCode"`
- }
-
- u := User{
- ReqEmail: "a@a.com",
- ReqIP: "127.0.0.1",
- ReqMobile: "18888888888",
- ReqTel: "02088888888",
- ReqPhone: "02088888888",
- ReqZipCode: "510000",
- }
-
- valid := Validation{}
- b, err := valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-
- valid = Validation{RequiredFirst: true}
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if !b {
- t.Fatal("validation should be passed")
- }
-}
-
-func TestPointer(t *testing.T) {
- type User struct {
- ID int
-
- Email *string `valid:"Email"`
- ReqEmail *string `valid:"Required;Email"`
- }
-
- u := User{
- ReqEmail: nil,
- Email: nil,
- }
-
- valid := Validation{}
- b, err := valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-
- validEmail := "a@a.com"
- u = User{
- ReqEmail: &validEmail,
- Email: nil,
- }
-
- valid = Validation{RequiredFirst: true}
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if !b {
- t.Fatal("validation should be passed")
- }
-
- u = User{
- ReqEmail: &validEmail,
- Email: nil,
- }
-
- valid = Validation{}
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-
- invalidEmail := "a@a"
- u = User{
- ReqEmail: &validEmail,
- Email: &invalidEmail,
- }
-
- valid = Validation{RequiredFirst: true}
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-
- u = User{
- ReqEmail: &validEmail,
- Email: &invalidEmail,
- }
-
- valid = Validation{}
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-}
-
-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)"`
- }
-
- u := User{
- ReqEmail: "a@a.com",
- Email: "",
- MatchRange: 0,
- }
-
- valid := Validation{RequiredFirst: true}
- b, err := valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should not be passed")
- }
-
- valid = Validation{RequiredFirst: true}
- valid.CanSkipAlso("Range")
- b, err = valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if !b {
- t.Fatal("validation should be passed")
- }
-
-}
-
-func TestFieldNoEmpty(t *testing.T) {
- type User struct {
- Name string `json:"name" valid:"Match(/^[a-zA-Z][a-zA-Z0-9._-]{0,31}$/)"`
- }
- u := User{
- Name: "*",
- }
-
- valid := Validation{}
- b, err := valid.Valid(u)
- if err != nil {
- t.Fatal(err)
- }
- if b {
- t.Fatal("validation should be passed")
- }
- if len(valid.Errors) == 0 {
- t.Fatal("validation should be passed")
- }
- validErr := valid.Errors[0]
- if len(validErr.Field) == 0 {
- t.Fatal("validation should be passed")
- }
-}
diff --git a/doc.go b/doc.go
index 6975885a..8825bd29 100644
--- a/doc.go
+++ b/doc.go
@@ -1,15 +1,17 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+Package beego provide a MVC framework
+beego: an open-source, high-performance, modular, full-stack web framework
+It is used for rapid development of RESTful APIs, web apps and backend services in Go.
+beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding.
+
+ package main
+ import "github.com/astaxie/beego"
+
+ func main() {
+ beego.Run()
+ }
+
+more information: http://beego.me
+*/
package beego
diff --git a/server/web/error.go b/error.go
similarity index 94%
rename from server/web/error.go
rename to error.go
index b5ef1d2d..e5e9fd47 100644
--- a/server/web/error.go
+++ b/error.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"fmt"
@@ -23,14 +23,12 @@ import (
"strconv"
"strings"
- "github.com/astaxie/beego"
- "github.com/astaxie/beego/core/utils"
-
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/utils"
)
const (
- errorTypeHandler = iota
+ errorTypeHandler = iota
errorTypeController
)
@@ -92,7 +90,7 @@ func showErr(err interface{}, ctx *context.Context, stack string) {
"RequestURL": ctx.Input.URI(),
"RemoteAddr": ctx.Input.IP(),
"Stack": stack,
- "BeegoVersion": beego.VERSION,
+ "BeegoVersion": VERSION,
"GoVersion": runtime.Version(),
}
t.Execute(ctx.ResponseWriter, data)
@@ -361,25 +359,11 @@ func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
)
}
-// show 413 Payload Too Large
-func payloadTooLarge(rw http.ResponseWriter, r *http.Request) {
- responseError(rw, r,
- 413,
- ` The page you have requested is unavailable.
- Perhaps you are here because:
-
- The request entity is larger than limits defined by server.
- Please change the request entity and try again.
-
- `,
- )
-}
-
func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
t, _ := template.New("beegoerrortemp").Parse(errtpl)
data := M{
"Title": http.StatusText(errCode),
- "BeegoVersion": beego.VERSION,
+ "BeegoVersion": VERSION,
"Content": template.HTML(errContent),
}
t.Execute(rw, data)
@@ -389,7 +373,7 @@ func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errCont
// usage:
// beego.ErrorHandler("404",NotFound)
// beego.ErrorHandler("500",InternalServerError)
-func ErrorHandler(code string, h http.HandlerFunc) *HttpServer {
+func ErrorHandler(code string, h http.HandlerFunc) *App {
ErrorMaps[code] = &errorInfo{
errorType: errorTypeHandler,
handler: h,
@@ -401,7 +385,7 @@ func ErrorHandler(code string, h http.HandlerFunc) *HttpServer {
// ErrorController registers ControllerInterface to each http err code string.
// usage:
// beego.ErrorController(&controllers.ErrorController{})
-func ErrorController(c ControllerInterface) *HttpServer {
+func ErrorController(c ControllerInterface) *App {
reflectVal := reflect.ValueOf(c)
rt := reflectVal.Type()
ct := reflect.Indirect(reflectVal).Type()
diff --git a/server/web/error_test.go b/error_test.go
similarity index 99%
rename from server/web/error_test.go
rename to error_test.go
index 2685a985..378aa953 100644
--- a/server/web/error_test.go
+++ b/error_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"net/http"
diff --git a/adapter/filter.go b/filter.go
similarity index 79%
rename from adapter/filter.go
rename to filter.go
index 283d8879..9cc6e913 100644
--- a/adapter/filter.go
+++ b/filter.go
@@ -12,13 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package adapter
+package beego
-import (
- "github.com/astaxie/beego/adapter/context"
- "github.com/astaxie/beego/server/web"
- beecontext "github.com/astaxie/beego/server/web/context"
-)
+import "github.com/astaxie/beego/context"
// FilterFunc defines a filter function which is invoked before the controller handler is executed.
type FilterFunc func(*context.Context)
@@ -26,11 +22,23 @@ type FilterFunc func(*context.Context)
// FilterRouter defines a filter operation which is invoked before the controller handler is executed.
// It can match the URL against a pattern, and execute a filter function
// when a request with a matching URL arrives.
-type FilterRouter web.FilterRouter
+type FilterRouter struct {
+ filterFunc FilterFunc
+ tree *Tree
+ pattern string
+ returnOnOutput bool
+ resetParams bool
+}
// ValidRouter checks if the current request is matched by this filter.
// If the request is matched, the values of the URL parameters defined
// by the filter pattern are also returned.
func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool {
- return (*web.FilterRouter)(f).ValidRouter(url, (*beecontext.Context)(ctx))
+ isOk := f.tree.Match(url, ctx)
+ if isOk != nil {
+ if b, ok := isOk.(bool); ok {
+ return b
+ }
+ }
+ return false
}
diff --git a/server/web/filter_test.go b/filter_test.go
similarity index 97%
rename from server/web/filter_test.go
rename to filter_test.go
index 11f575d6..4ca4d2b8 100644
--- a/server/web/filter_test.go
+++ b/filter_test.go
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"net/http"
"net/http/httptest"
"testing"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
)
var FilterUser = func(ctx *context.Context) {
diff --git a/server/web/flash.go b/flash.go
similarity index 99%
rename from server/web/flash.go
rename to flash.go
index 55f6435d..a6485a17 100644
--- a/server/web/flash.go
+++ b/flash.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"fmt"
diff --git a/server/web/flash_test.go b/flash_test.go
similarity index 99%
rename from server/web/flash_test.go
rename to flash_test.go
index 2deef54e..d5e9608d 100644
--- a/server/web/flash_test.go
+++ b/flash_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"net/http"
diff --git a/server/web/fs.go b/fs.go
similarity index 99%
rename from server/web/fs.go
rename to fs.go
index 5457457a..41cc6f6e 100644
--- a/server/web/fs.go
+++ b/fs.go
@@ -1,4 +1,4 @@
-package web
+package beego
import (
"net/http"
diff --git a/go.mod b/go.mod
index 7527aa47..ec500f51 100644
--- a/go.mod
+++ b/go.mod
@@ -7,53 +7,34 @@ require (
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
- github.com/coreos/etcd v3.3.25+incompatible
- github.com/coreos/go-semver v0.3.0 // indirect
- github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
- github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 // indirect
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect
github.com/elastic/go-elasticsearch/v6 v6.8.5
github.com/elazarl/go-bindata-assetfs v1.0.0
- github.com/go-kit/kit v0.9.0
github.com/go-redis/redis v6.14.2+incompatible
- github.com/go-redis/redis/v7 v7.4.0
github.com/go-sql-driver/mysql v1.5.0
- github.com/gogo/protobuf v1.3.1
+ github.com/gogo/protobuf v1.1.1
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/gomodule/redigo v2.0.0+incompatible
- github.com/google/go-cmp v0.5.0 // indirect
- github.com/google/uuid v1.1.1 // indirect
- github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hashicorp/golang-lru v0.5.4
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6
github.com/lib/pq v1.0.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
- github.com/mitchellh/mapstructure v1.3.3
- github.com/opentracing/opentracing-go v1.2.0
- github.com/pelletier/go-toml v1.8.1
- github.com/pkg/errors v0.9.1
+ github.com/pelletier/go-toml v1.2.0 // indirect
github.com/prometheus/client_golang v1.7.0
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
- go.etcd.io/etcd v3.3.25+incompatible // indirect
- go.uber.org/zap v1.15.0 // indirect
- golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
- golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
- golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 // indirect
- golang.org/x/text v0.3.3 // indirect
+ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c
- google.golang.org/grpc v1.26.0
gopkg.in/yaml.v2 v2.2.8
- honnef.co/go/tools v0.0.1-2020.1.5 // indirect
)
replace golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 => github.com/golang/crypto v0.0.0-20181127143415-eb0de9b17e85
replace gopkg.in/yaml.v2 v2.2.1 => github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d
-go 1.14
+go 1.13
diff --git a/go.sum b/go.sum
index 994d1ec4..c7b861ac 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,3 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
@@ -21,22 +20,10 @@ github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737 h1:rRISKWyXfVx
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/casbin/casbin v1.7.0 h1:PuzlE8w0JBg/DhIqnkF1Dewf3z+qmUZMVN07PonvVUQ=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/coreos/etcd v0.5.0-alpha.5 h1:0Qi6Jzjk2CDuuGlIeecpu+em2nrjhOgz2wsIwCmQHmc=
-github.com/coreos/etcd v3.3.25+incompatible h1:0GQEw6h3YnuOVdtwygkIfJ+Omx0tZ8/QkVyXI4LkbeY=
-github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
-github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
-github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d h1:OMrhQqj1QCyDT2sxHCDjE+k8aMdn2ngTCGG7g4wrdLo=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808 h1:8s2l8TVUwMXl6tZMe3+hPCRJ25nQXiA3d1x622JtOqc=
@@ -54,45 +41,30 @@ github.com/elastic/go-elasticsearch/v6 v6.8.5 h1:U2HtkBseC1FNBmDr0TR2tKltL6FxoY+
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
-github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
-github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d h1:xy93KVe+KrIIwWDEAfQBdIfsiHJkepbYsDr+VY3g9/o=
github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
-github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -100,18 +72,11 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
@@ -119,10 +84,7 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -136,8 +98,6 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
-github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@@ -146,26 +106,19 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
-github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
-github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
-github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pingcap/tidb v2.0.11+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -174,7 +127,6 @@ github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -184,7 +136,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 h1:QIF48X1cihydXibm+4wfAc0r/qyPyuFiPFRNphdMpEE=
@@ -208,137 +159,52 @@ github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2K
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b h1:0Ve0/CCjiAiyKddUMUn3RwIGlq2iTW4GuVzyoKBYO/8=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
-go.etcd.io/etcd v0.5.0-alpha.5 h1:VOolFSo3XgsmnYDLozjvZ6JL6AAwIDu1Yx1y+4EYLDo=
-go.etcd.io/etcd v3.3.25+incompatible h1:V1RzkZJj9LqsJRy+TUBgpWSbZXITLB819lstuTFoZOY=
-go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
-go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
-go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
-golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4=
-golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20200117065230-39095c1d176c h1:FodBYPZKH5tAN2O60HlglMwXGAeV/4k+NKbli79M/2c=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200815165600-90abf76919f3 h1:0aScV/0rLmANzEYIhjCOi2pTvDyhZNduBUMD2q3iqs4=
-golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
@@ -349,9 +215,3 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k=
-honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
diff --git a/server/web/grace/grace.go b/grace/grace.go
similarity index 100%
rename from server/web/grace/grace.go
rename to grace/grace.go
diff --git a/server/web/grace/server.go b/grace/server.go
similarity index 98%
rename from server/web/grace/server.go
rename to grace/server.go
index 13fa6e34..008a6171 100644
--- a/server/web/grace/server.go
+++ b/grace/server.go
@@ -29,8 +29,8 @@ type Server struct {
terminalChan chan error
}
-// Serve accepts incoming connections on the Listener l
-// and creates a new service goroutine for each.
+// 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) {
srv.state = StateRunning
diff --git a/server/web/hooks.go b/hooks.go
similarity index 84%
rename from server/web/hooks.go
rename to hooks.go
index 58e2c0f3..b8671d35 100644
--- a/server/web/hooks.go
+++ b/hooks.go
@@ -1,4 +1,4 @@
-package web
+package beego
import (
"encoding/json"
@@ -6,9 +6,9 @@ import (
"net/http"
"path/filepath"
- "github.com/astaxie/beego/core/logs"
- "github.com/astaxie/beego/server/web/context"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/logs"
+ "github.com/astaxie/beego/session"
)
// register MIME type with content type
@@ -34,7 +34,6 @@ func registerDefaultErrorHandler() error {
"504": gatewayTimeout,
"417": invalidxsrf,
"422": missingxsrf,
- "413": payloadTooLarge,
}
for e, h := range m {
if _, ok := ErrorMaps[e]; !ok {
@@ -47,9 +46,9 @@ func registerDefaultErrorHandler() error {
func registerSession() error {
if BConfig.WebConfig.Session.SessionOn {
var err error
- sessionConfig, err := AppConfig.String("sessionConfig")
+ sessionConfig := AppConfig.String("sessionConfig")
conf := new(session.ManagerConfig)
- if sessionConfig == "" || err != nil {
+ if sessionConfig == "" {
conf.CookieName = BConfig.WebConfig.Session.SessionName
conf.EnableSetCookie = BConfig.WebConfig.Session.SessionAutoSetCookie
conf.Gclifetime = BConfig.WebConfig.Session.SessionGCMaxLifetime
@@ -85,6 +84,13 @@ func registerTemplate() error {
return nil
}
+func registerAdmin() error {
+ if BConfig.Listen.EnableAdmin {
+ go beeAdminApp.Run()
+ }
+ return nil
+}
+
func registerGzip() error {
if BConfig.EnableGzip {
context.InitGzip(
@@ -95,13 +101,3 @@ func registerGzip() error {
}
return nil
}
-
-func registerCommentRouter() error {
- if BConfig.RunMode == DEV {
- if err := parserPkg(filepath.Join(WorkPath, BConfig.WebConfig.CommentRouterPath)); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/client/httplib/README.md b/httplib/README.md
similarity index 100%
rename from client/httplib/README.md
rename to httplib/README.md
diff --git a/client/httplib/httplib.go b/httplib/httplib.go
similarity index 85%
rename from client/httplib/httplib.go
rename to httplib/httplib.go
index f8ab80a1..e094a6a6 100644
--- a/client/httplib/httplib.go
+++ b/httplib/httplib.go
@@ -34,7 +34,6 @@ package httplib
import (
"bytes"
"compress/gzip"
- "context"
"crypto/tls"
"encoding/json"
"encoding/xml"
@@ -67,11 +66,6 @@ var defaultSetting = BeegoHTTPSettings{
var defaultCookieJar http.CookieJar
var settingMutex sync.Mutex
-// it will be the last filter and execute request.Do
-var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
- return req.doRequest(ctx)
-}
-
// createDefaultCookie creates a global cookiejar to store cookies.
func createDefaultCookie() {
settingMutex.Lock()
@@ -79,14 +73,14 @@ func createDefaultCookie() {
defaultCookieJar, _ = cookiejar.New(nil)
}
-// SetDefaultSetting overwrites default settings
+// SetDefaultSetting Overwrite default settings
func SetDefaultSetting(setting BeegoHTTPSettings) {
settingMutex.Lock()
defer settingMutex.Unlock()
defaultSetting = setting
}
-// NewBeegoRequest returns *BeegoHttpRequest with specific method
+// NewBeegoRequest return *BeegoHttpRequest with specific method
func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest {
var resp http.Response
u, err := url.Parse(rawurl)
@@ -150,11 +144,9 @@ type BeegoHTTPSettings struct {
Gzip bool
DumpBody bool
Retries int // if set to -1 means will retry forever
- RetryDelay time.Duration
- FilterChains []FilterChain
}
-// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url.
+// BeegoHTTPRequest provides more useful methods for requesting one url than http.Request.
type BeegoHTTPRequest struct {
url string
req *http.Request
@@ -166,12 +158,12 @@ type BeegoHTTPRequest struct {
dump []byte
}
-// GetRequest returns the request object
+// GetRequest return the request object
func (b *BeegoHTTPRequest) GetRequest() *http.Request {
return b.req
}
-// Setting changes request settings
+// Setting Change request settings
func (b *BeegoHTTPRequest) Setting(setting BeegoHTTPSettings) *BeegoHTTPRequest {
b.setting = setting
return b
@@ -202,27 +194,21 @@ func (b *BeegoHTTPRequest) Debug(isdebug bool) *BeegoHTTPRequest {
}
// Retries sets Retries times.
-// default is 0 (never retry)
-// -1 retry indefinitely (forever)
-// Other numbers specify the exact retry amount
+// default is 0 means no retried.
+// -1 means retried forever.
+// others means retried times.
func (b *BeegoHTTPRequest) Retries(times int) *BeegoHTTPRequest {
b.setting.Retries = times
return b
}
-// RetryDelay sets the time to sleep between reconnection attempts
-func (b *BeegoHTTPRequest) RetryDelay(delay time.Duration) *BeegoHTTPRequest {
- b.setting.RetryDelay = delay
- return b
-}
-
-// DumpBody sets the DumbBody field
+// DumpBody setting whether need to Dump the Body.
func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
b.setting.DumpBody = isdump
return b
}
-// DumpRequest returns the DumpRequest
+// DumpRequest return the DumpRequest
func (b *BeegoHTTPRequest) DumpRequest() []byte {
return b.dump
}
@@ -234,13 +220,13 @@ func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Dura
return b
}
-// SetTLSClientConfig sets TLS connection configuration if visiting HTTPS url.
+// SetTLSClientConfig sets tls connection configurations if visiting https url.
func (b *BeegoHTTPRequest) SetTLSClientConfig(config *tls.Config) *BeegoHTTPRequest {
b.setting.TLSClientConfig = config
return b
}
-// Header adds header item string in request.
+// Header add header item string in request.
func (b *BeegoHTTPRequest) Header(key, value string) *BeegoHTTPRequest {
b.req.Header.Set(key, value)
return b
@@ -252,7 +238,7 @@ func (b *BeegoHTTPRequest) SetHost(host string) *BeegoHTTPRequest {
return b
}
-// SetProtocolVersion sets the protocol version for incoming requests.
+// SetProtocolVersion Set the protocol version for incoming requests.
// Client requests always use HTTP/1.1.
func (b *BeegoHTTPRequest) SetProtocolVersion(vers string) *BeegoHTTPRequest {
if len(vers) == 0 {
@@ -269,19 +255,19 @@ func (b *BeegoHTTPRequest) SetProtocolVersion(vers string) *BeegoHTTPRequest {
return b
}
-// SetCookie adds a cookie to the request.
+// SetCookie add cookie into request.
func (b *BeegoHTTPRequest) SetCookie(cookie *http.Cookie) *BeegoHTTPRequest {
b.req.Header.Add("Cookie", cookie.String())
return b
}
-// SetTransport sets the transport field
+// SetTransport set the setting transport
func (b *BeegoHTTPRequest) SetTransport(transport http.RoundTripper) *BeegoHTTPRequest {
b.setting.Transport = transport
return b
}
-// SetProxy sets the HTTP proxy
+// SetProxy set the http proxy
// example:
//
// func(req *http.Request) (*url.URL, error) {
@@ -302,18 +288,6 @@ func (b *BeegoHTTPRequest) SetCheckRedirect(redirect func(req *http.Request, via
return b
}
-// SetFilters will use the filter as the invocation filters
-func (b *BeegoHTTPRequest) SetFilters(fcs ...FilterChain) *BeegoHTTPRequest {
- b.setting.FilterChains = fcs
- return b
-}
-
-// AddFilters adds filter
-func (b *BeegoHTTPRequest) AddFilters(fcs ...FilterChain) *BeegoHTTPRequest {
- b.setting.FilterChains = append(b.setting.FilterChains, fcs...)
- return b
-}
-
// Param adds query param in to request.
// params build query string as ?key1=value1&key2=value2...
func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest {
@@ -325,14 +299,14 @@ func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest {
return b
}
-// PostFile adds a post file to the request
+// PostFile add a post file to the request
func (b *BeegoHTTPRequest) PostFile(formname, filename string) *BeegoHTTPRequest {
b.files[formname] = filename
return b
}
// Body adds request raw body.
-// Supports string and []byte.
+// it supports string and []byte.
func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest {
switch t := data.(type) {
case string:
@@ -347,7 +321,7 @@ func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest {
return b
}
-// XMLBody adds the request raw body encoded in XML.
+// XMLBody adds request raw body encoding by XML.
func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
if b.req.Body == nil && obj != nil {
byts, err := xml.Marshal(obj)
@@ -361,7 +335,7 @@ func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
return b, nil
}
-// YAMLBody adds the request raw body encoded in YAML.
+// YAMLBody adds request raw body encoding by YAML.
func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error) {
if b.req.Body == nil && obj != nil {
byts, err := yaml.Marshal(obj)
@@ -375,7 +349,7 @@ func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error)
return b, nil
}
-// JSONBody adds the request raw body encoded in JSON.
+// JSONBody adds request raw body encoding by JSON.
func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) {
if b.req.Body == nil && obj != nil {
byts, err := json.Marshal(obj)
@@ -416,7 +390,7 @@ func (b *BeegoHTTPRequest) buildURL(paramBody string) {
if err != nil {
log.Println("Httplib:", err)
}
- // iocopy
+ //iocopy
_, err = io.Copy(fileWriter, fh)
fh.Close()
if err != nil {
@@ -457,23 +431,8 @@ func (b *BeegoHTTPRequest) getResponse() (*http.Response, error) {
return resp, nil
}
-// DoRequest executes client.Do
+// DoRequest will do the client.Do
func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
- return b.DoRequestWithCtx(context.Background())
-}
-
-func (b *BeegoHTTPRequest) DoRequestWithCtx(ctx context.Context) (resp *http.Response, err error) {
-
- root := doRequestFilter
- if len(b.setting.FilterChains) > 0 {
- for i := len(b.setting.FilterChains) - 1; i >= 0; i-- {
- root = b.setting.FilterChains[i](root)
- }
- }
- return root(ctx, b)
-}
-
-func (b *BeegoHTTPRequest) doRequest(ctx context.Context) (resp *http.Response, err error) {
var paramBody string
if len(b.params) > 0 {
var buf bytes.Buffer
@@ -553,19 +512,17 @@ func (b *BeegoHTTPRequest) doRequest(ctx context.Context) (resp *http.Response,
// retries default value is 0, it will run once.
// retries equal to -1, it will run forever until success
// retries is setted, it will retries fixed times.
- // Sleeps for a 400ms inbetween calls to reduce spam
for i := 0; b.setting.Retries == -1 || i <= b.setting.Retries; i++ {
resp, err = client.Do(b.req)
if err == nil {
break
}
- time.Sleep(b.setting.RetryDelay)
}
return resp, err
}
// String returns the body string in response.
-// Calls Response inner.
+// it calls Response inner.
func (b *BeegoHTTPRequest) String() (string, error) {
data, err := b.Bytes()
if err != nil {
@@ -576,7 +533,7 @@ func (b *BeegoHTTPRequest) String() (string, error) {
}
// Bytes returns the body []byte in response.
-// Calls Response inner.
+// it calls Response inner.
func (b *BeegoHTTPRequest) Bytes() ([]byte, error) {
if b.body != nil {
return b.body, nil
@@ -602,7 +559,7 @@ func (b *BeegoHTTPRequest) Bytes() ([]byte, error) {
}
// ToFile saves the body data in response to one file.
-// Calls Response inner.
+// it calls Response inner.
func (b *BeegoHTTPRequest) ToFile(filename string) error {
resp, err := b.getResponse()
if err != nil {
@@ -625,7 +582,7 @@ func (b *BeegoHTTPRequest) ToFile(filename string) error {
return err
}
-// Check if the file directory exists. If it doesn't then it's created
+//Check that the file directory exists, there is no automatically created
func pathExistAndMkdir(filename string) (err error) {
filename = path.Dir(filename)
_, err = os.Stat(filename)
@@ -641,8 +598,8 @@ func pathExistAndMkdir(filename string) (err error) {
return err
}
-// ToJSON returns the map that marshals from the body bytes as json in response.
-// Calls Response inner.
+// ToJSON returns the map that marshals from the body bytes as json in response .
+// it calls Response inner.
func (b *BeegoHTTPRequest) ToJSON(v interface{}) error {
data, err := b.Bytes()
if err != nil {
@@ -652,7 +609,7 @@ func (b *BeegoHTTPRequest) ToJSON(v interface{}) error {
}
// ToXML returns the map that marshals from the body bytes as xml in response .
-// Calls Response inner.
+// it calls Response inner.
func (b *BeegoHTTPRequest) ToXML(v interface{}) error {
data, err := b.Bytes()
if err != nil {
@@ -662,7 +619,7 @@ func (b *BeegoHTTPRequest) ToXML(v interface{}) error {
}
// ToYAML returns the map that marshals from the body bytes as yaml in response .
-// Calls Response inner.
+// it calls Response inner.
func (b *BeegoHTTPRequest) ToYAML(v interface{}) error {
data, err := b.Bytes()
if err != nil {
@@ -671,7 +628,7 @@ func (b *BeegoHTTPRequest) ToYAML(v interface{}) error {
return yaml.Unmarshal(data, v)
}
-// Response executes request client gets response manually.
+// Response executes request client gets response mannually.
func (b *BeegoHTTPRequest) Response() (*http.Response, error) {
return b.getResponse()
}
diff --git a/adapter/httplib/httplib_test.go b/httplib/httplib_test.go
similarity index 86%
rename from adapter/httplib/httplib_test.go
rename to httplib/httplib_test.go
index e7605c87..dd2a4f1c 100644
--- a/adapter/httplib/httplib_test.go
+++ b/httplib/httplib_test.go
@@ -15,7 +15,6 @@
package httplib
import (
- "errors"
"io/ioutil"
"net"
"net/http"
@@ -34,34 +33,6 @@ func TestResponse(t *testing.T) {
t.Log(resp)
}
-func TestDoRequest(t *testing.T) {
- req := Get("https://goolnk.com/33BD2j")
- retryAmount := 1
- req.Retries(1)
- req.RetryDelay(1400 * time.Millisecond)
- retryDelay := 1400 * time.Millisecond
-
- req.SetCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error {
- return errors.New("Redirect triggered")
- })
-
- startTime := time.Now().UnixNano() / int64(time.Millisecond)
-
- _, err := req.Response()
- if err == nil {
- t.Fatal("Response should have yielded an error")
- }
-
- endTime := time.Now().UnixNano() / int64(time.Millisecond)
- elapsedTime := endTime - startTime
- delayedTime := int64(retryAmount) * retryDelay.Milliseconds()
-
- if elapsedTime < delayedTime {
- t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime)
- }
-
-}
-
func TestGet(t *testing.T) {
req := Get("http://httpbin.org/get")
b, err := req.Bytes()
@@ -98,7 +69,7 @@ func TestSimplePost(t *testing.T) {
}
}
-// func TestPostFile(t *testing.T) {
+//func TestPostFile(t *testing.T) {
// v := "smallfish"
// req := Post("http://httpbin.org/post")
// req.Debug(true)
@@ -115,7 +86,7 @@ func TestSimplePost(t *testing.T) {
// if n == -1 {
// t.Fatal(v + " not found in post")
// }
-// }
+//}
func TestSimplePut(t *testing.T) {
str, err := Put("http://httpbin.org/put").String()
diff --git a/adapter/log.go b/log.go
similarity index 88%
rename from adapter/log.go
rename to log.go
index 9d07ec1a..cc4c0f81 100644
--- a/adapter/log.go
+++ b/log.go
@@ -12,27 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package adapter
+package beego
import (
"strings"
- "github.com/astaxie/beego/core/logs"
-
- webLog "github.com/astaxie/beego/core/logs"
+ "github.com/astaxie/beego/logs"
)
// Log levels to control the logging output.
// Deprecated: use github.com/astaxie/beego/logs instead.
const (
- LevelEmergency = webLog.LevelEmergency
- LevelAlert = webLog.LevelAlert
- LevelCritical = webLog.LevelCritical
- LevelError = webLog.LevelError
- LevelWarning = webLog.LevelWarning
- LevelNotice = webLog.LevelNotice
- LevelInformational = webLog.LevelInformational
- LevelDebug = webLog.LevelDebug
+ LevelEmergency = iota
+ LevelAlert
+ LevelCritical
+ LevelError
+ LevelWarning
+ LevelNotice
+ LevelInformational
+ LevelDebug
)
// BeeLogger references the used application logger.
diff --git a/core/logs/README.md b/logs/README.md
similarity index 100%
rename from core/logs/README.md
rename to logs/README.md
diff --git a/core/logs/access_log.go b/logs/accesslog.go
similarity index 89%
rename from core/logs/access_log.go
rename to logs/accesslog.go
index 10455fe9..3ff9e20f 100644
--- a/core/logs/access_log.go
+++ b/logs/accesslog.go
@@ -16,9 +16,9 @@ package logs
import (
"bytes"
+ "strings"
"encoding/json"
"fmt"
- "strings"
"time"
)
@@ -28,7 +28,7 @@ const (
jsonFormat = "JSON_FORMAT"
)
-// AccessLogRecord is astruct for holding access log data.
+// AccessLogRecord struct for holding access log data.
type AccessLogRecord struct {
RemoteAddr string `json:"remote_addr"`
RequestTime time.Time `json:"request_time"`
@@ -63,17 +63,7 @@ func disableEscapeHTML(i interface{}) {
// AccessLog - Format and print access log.
func AccessLog(r *AccessLogRecord, format string) {
- msg := r.format(format)
- lm := &LogMsg{
- Msg: strings.TrimSpace(msg),
- When: time.Now(),
- Level: levelLoggerImpl,
- }
- beeLogger.writeMsg(lm)
-}
-
-func (r *AccessLogRecord) format(format string) string {
- msg := ""
+ var msg string
switch format {
case apacheFormat:
timeFormatted := r.RequestTime.Format("02/Jan/2006 03:04:05")
@@ -89,5 +79,5 @@ func (r *AccessLogRecord) format(format string) string {
msg = string(jsonData)
}
}
- return msg
+ beeLogger.writeMsg(levelLoggerImpl, strings.TrimSpace(msg))
}
diff --git a/core/logs/alils/alils.go b/logs/alils/alils.go
similarity index 69%
rename from core/logs/alils/alils.go
rename to logs/alils/alils.go
index 484d31e4..867ff4cb 100644
--- a/core/logs/alils/alils.go
+++ b/logs/alils/alils.go
@@ -2,20 +2,18 @@ package alils
import (
"encoding/json"
- "fmt"
"strings"
"sync"
+ "time"
+ "github.com/astaxie/beego/logs"
"github.com/gogo/protobuf/proto"
- "github.com/pkg/errors"
-
- "github.com/astaxie/beego/core/logs"
)
const (
- // CacheSize sets the flush size
+ // CacheSize set the flush size
CacheSize int = 64
- // Delimiter defines the topic delimiter
+ // Delimiter define the topic delimiter
Delimiter string = "##"
)
@@ -30,11 +28,10 @@ type Config struct {
Source string `json:"source"`
Level int `json:"level"`
FlushWhen int `json:"flush_when"`
- Formatter string `json:"formatter"`
}
// aliLSWriter implements LoggerInterface.
-// Writes messages in keep-live tcp connection.
+// it writes messages in keep-live tcp connection.
type aliLSWriter struct {
store *LogStore
group []*LogGroup
@@ -42,23 +39,19 @@ type aliLSWriter struct {
groupMap map[string]*LogGroup
lock *sync.Mutex
Config
- formatter logs.LogFormatter
}
-// NewAliLS creates a new Logger
+// NewAliLS create a new Logger
func NewAliLS() logs.Logger {
alils := new(aliLSWriter)
alils.Level = logs.LevelTrace
- alils.formatter = alils
return alils
}
-// Init parses config and initializes struct
-func (c *aliLSWriter) Init(config string) error {
- err := json.Unmarshal([]byte(config), c)
- if err != nil {
- return err
- }
+// Init parse config and init struct
+func (c *aliLSWriter) Init(jsonConfig string) (err error) {
+
+ json.Unmarshal([]byte(jsonConfig), c)
if c.FlushWhen > CacheSize {
c.FlushWhen = CacheSize
@@ -71,13 +64,11 @@ func (c *aliLSWriter) Init(config string) error {
AccessKeySecret: c.KeySecret,
}
- store, err := prj.GetLogStore(c.LogStore)
+ c.store, err = prj.GetLogStore(c.LogStore)
if err != nil {
return err
}
- c.store = store
-
// Create default Log Group
c.group = append(c.group, &LogGroup{
Topic: proto.String(""),
@@ -107,29 +98,14 @@ func (c *aliLSWriter) Init(config string) error {
c.lock = &sync.Mutex{}
- if len(c.Formatter) > 0 {
- fmtr, ok := logs.GetFormatter(c.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", c.Formatter))
- }
- c.formatter = fmtr
- }
-
return nil
}
-func (c *aliLSWriter) Format(lm *logs.LogMsg) string {
- return lm.OldStyleFormat()
-}
+// WriteMsg write message in connection.
+// if connection is down, try to re-connect.
+func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error) {
-func (c *aliLSWriter) SetFormatter(f logs.LogFormatter) {
- c.formatter = f
-}
-
-// WriteMsg writes a message in connection.
-// If connection is down, try to re-connect.
-func (c *aliLSWriter) WriteMsg(lm *logs.LogMsg) error {
- if lm.Level > c.Level {
+ if level > c.Level {
return nil
}
@@ -139,30 +115,31 @@ func (c *aliLSWriter) WriteMsg(lm *logs.LogMsg) error {
if c.withMap {
// Topic,LogGroup
- strs := strings.SplitN(lm.Msg, Delimiter, 2)
+ strs := strings.SplitN(msg, Delimiter, 2)
if len(strs) == 2 {
pos := strings.LastIndex(strs[0], " ")
topic = strs[0][pos+1 : len(strs[0])]
+ content = strs[0][0:pos] + strs[1]
lg = c.groupMap[topic]
}
// send to empty Topic
if lg == nil {
+ content = msg
lg = c.group[0]
}
} else {
+ content = msg
lg = c.group[0]
}
- content = c.formatter.Format(lm)
-
c1 := &LogContent{
Key: proto.String("msg"),
Value: proto.String(content),
}
l := &Log{
- Time: proto.Uint32(uint32(lm.When.Unix())),
+ Time: proto.Uint32(uint32(when.Unix())),
Contents: []*LogContent{
c1,
},
@@ -175,6 +152,7 @@ func (c *aliLSWriter) WriteMsg(lm *logs.LogMsg) error {
if len(lg.Logs) >= c.FlushWhen {
c.flush(lg)
}
+
return nil
}
diff --git a/core/logs/alils/config.go b/logs/alils/config.go
similarity index 61%
rename from core/logs/alils/config.go
rename to logs/alils/config.go
index d0b67c24..e8c24448 100755
--- a/core/logs/alils/config.go
+++ b/logs/alils/config.go
@@ -4,10 +4,10 @@ const (
version = "0.5.0" // SDK version
signatureMethod = "hmac-sha1" // Signature method
- // OffsetNewest is the log head offset, i.e. the offset that will be
+ // OffsetNewest stands for the log head offset, i.e. the offset that will be
// assigned to the next message that will be produced to the shard.
OffsetNewest = "end"
- // OffsetOldest is the the oldest offset available on the logstore for a
+ // OffsetOldest stands for the oldest offset available on the logstore for a
// shard.
OffsetOldest = "begin"
)
diff --git a/core/logs/alils/log.pb.go b/logs/alils/log.pb.go
similarity index 95%
rename from core/logs/alils/log.pb.go
rename to logs/alils/log.pb.go
index b18fb9b7..601b0d78 100755
--- a/core/logs/alils/log.pb.go
+++ b/logs/alils/log.pb.go
@@ -31,13 +31,13 @@ type Log struct {
// Reset the Log
func (m *Log) Reset() { *m = Log{} }
-// String returns the Compact Log
+// String return the Compact Log
func (m *Log) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*Log) ProtoMessage() {}
-// GetTime returns the Log's Time
+// GetTime return the Log's Time
func (m *Log) GetTime() uint32 {
if m != nil && m.Time != nil {
return *m.Time
@@ -45,7 +45,7 @@ func (m *Log) GetTime() uint32 {
return 0
}
-// GetContents returns the Log's Contents
+// GetContents return the Log's Contents
func (m *Log) GetContents() []*LogContent {
if m != nil {
return m.Contents
@@ -53,7 +53,7 @@ func (m *Log) GetContents() []*LogContent {
return nil
}
-// LogContent defines the Log content struct
+// LogContent define the Log content struct
type LogContent struct {
Key *string `protobuf:"bytes,1,req,name=Key" json:"Key,omitempty"`
Value *string `protobuf:"bytes,2,req,name=Value" json:"Value,omitempty"`
@@ -63,13 +63,13 @@ type LogContent struct {
// Reset LogContent
func (m *LogContent) Reset() { *m = LogContent{} }
-// String returns the compact text
+// String return the compact text
func (m *LogContent) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogContent) ProtoMessage() {}
-// GetKey returns the key
+// GetKey return the Key
func (m *LogContent) GetKey() string {
if m != nil && m.Key != nil {
return *m.Key
@@ -77,7 +77,7 @@ func (m *LogContent) GetKey() string {
return ""
}
-// GetValue returns the value
+// GetValue return the Value
func (m *LogContent) GetValue() string {
if m != nil && m.Value != nil {
return *m.Value
@@ -85,7 +85,7 @@ func (m *LogContent) GetValue() string {
return ""
}
-// LogGroup defines the logs struct
+// LogGroup define the logs struct
type LogGroup struct {
Logs []*Log `protobuf:"bytes,1,rep,name=Logs" json:"Logs,omitempty"`
Reserved *string `protobuf:"bytes,2,opt,name=Reserved" json:"Reserved,omitempty"`
@@ -97,13 +97,13 @@ type LogGroup struct {
// Reset LogGroup
func (m *LogGroup) Reset() { *m = LogGroup{} }
-// String returns the compact text
+// String return the compact text
func (m *LogGroup) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogGroup) ProtoMessage() {}
-// GetLogs returns the loggroup logs
+// GetLogs return the loggroup logs
func (m *LogGroup) GetLogs() []*Log {
if m != nil {
return m.Logs
@@ -111,8 +111,7 @@ func (m *LogGroup) GetLogs() []*Log {
return nil
}
-// GetReserved returns Reserved. An empty string is returned
-// if an error occurs
+// GetReserved return Reserved
func (m *LogGroup) GetReserved() string {
if m != nil && m.Reserved != nil {
return *m.Reserved
@@ -120,8 +119,7 @@ func (m *LogGroup) GetReserved() string {
return ""
}
-// GetTopic returns Topic. An empty string is returned
-// if an error occurs
+// GetTopic return Topic
func (m *LogGroup) GetTopic() string {
if m != nil && m.Topic != nil {
return *m.Topic
@@ -129,8 +127,7 @@ func (m *LogGroup) GetTopic() string {
return ""
}
-// GetSource returns source. An empty string is returned
-// if an error occurs
+// GetSource return Source
func (m *LogGroup) GetSource() string {
if m != nil && m.Source != nil {
return *m.Source
@@ -138,7 +135,7 @@ func (m *LogGroup) GetSource() string {
return ""
}
-// LogGroupList defines the LogGroups
+// LogGroupList define the LogGroups
type LogGroupList struct {
LogGroups []*LogGroup `protobuf:"bytes,1,rep,name=logGroups" json:"logGroups,omitempty"`
XXXUnrecognized []byte `json:"-"`
@@ -147,13 +144,13 @@ type LogGroupList struct {
// Reset LogGroupList
func (m *LogGroupList) Reset() { *m = LogGroupList{} }
-// String returns compact text
+// String return compact text
func (m *LogGroupList) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogGroupList) ProtoMessage() {}
-// GetLogGroups returns the LogGroups
+// GetLogGroups return the LogGroups
func (m *LogGroupList) GetLogGroups() []*LogGroup {
if m != nil {
return m.LogGroups
@@ -161,7 +158,7 @@ func (m *LogGroupList) GetLogGroups() []*LogGroup {
return nil
}
-// Marshal marshals the logs to byte slice
+// Marshal the logs to byte slice
func (m *Log) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
@@ -356,7 +353,7 @@ func encodeVarintLog(data []byte, offset int, v uint64) int {
return offset + 1
}
-// Size returns the log's size
+// Size return the log's size
func (m *Log) Size() (n int) {
var l int
_ = l
@@ -375,7 +372,7 @@ func (m *Log) Size() (n int) {
return n
}
-// Size returns LogContent size based on Key and Value
+// Size return LogContent size based on Key and Value
func (m *LogContent) Size() (n int) {
var l int
_ = l
@@ -393,7 +390,7 @@ func (m *LogContent) Size() (n int) {
return n
}
-// Size returns LogGroup size based on Logs
+// Size return LogGroup size based on Logs
func (m *LogGroup) Size() (n int) {
var l int
_ = l
@@ -421,7 +418,7 @@ func (m *LogGroup) Size() (n int) {
return n
}
-// Size returns LogGroupList size
+// Size return LogGroupList size
func (m *LogGroupList) Size() (n int) {
var l int
_ = l
@@ -451,7 +448,7 @@ func sozLog(x uint64) (n int) {
return sovLog((x << 1) ^ (x >> 63))
}
-// Unmarshal unmarshals data to log
+// Unmarshal data to log
func (m *Log) Unmarshal(data []byte) error {
var hasFields [1]uint64
l := len(data)
@@ -560,7 +557,7 @@ func (m *Log) Unmarshal(data []byte) error {
return nil
}
-// Unmarshal unmarshals data to LogContent
+// Unmarshal data to LogContent
func (m *LogContent) Unmarshal(data []byte) error {
var hasFields [1]uint64
l := len(data)
@@ -682,7 +679,7 @@ func (m *LogContent) Unmarshal(data []byte) error {
return nil
}
-// Unmarshal unmarshals data to LogGroup
+// Unmarshal data to LogGroup
func (m *LogGroup) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
@@ -856,7 +853,7 @@ func (m *LogGroup) Unmarshal(data []byte) error {
return nil
}
-// Unmarshal unmarshals data to LogGroupList
+// Unmarshal data to LogGroupList
func (m *LogGroupList) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
diff --git a/core/logs/alils/log_config.go b/logs/alils/log_config.go
similarity index 91%
rename from core/logs/alils/log_config.go
rename to logs/alils/log_config.go
index 7daeb864..e8564efb 100755
--- a/core/logs/alils/log_config.go
+++ b/logs/alils/log_config.go
@@ -1,6 +1,6 @@
package alils
-// InputDetail defines log detail
+// InputDetail define log detail
type InputDetail struct {
LogType string `json:"logType"`
LogPath string `json:"logPath"`
@@ -15,13 +15,13 @@ type InputDetail struct {
TopicFormat string `json:"topicFormat"`
}
-// OutputDetail defines the output detail
+// OutputDetail define the output detail
type OutputDetail struct {
Endpoint string `json:"endpoint"`
LogStoreName string `json:"logstoreName"`
}
-// LogConfig defines Log Config
+// LogConfig define Log Config
type LogConfig struct {
Name string `json:"configName"`
InputType string `json:"inputType"`
diff --git a/core/logs/alils/log_project.go b/logs/alils/log_project.go
similarity index 99%
rename from core/logs/alils/log_project.go
rename to logs/alils/log_project.go
index 7ede3fef..59db8cbf 100755
--- a/core/logs/alils/log_project.go
+++ b/logs/alils/log_project.go
@@ -20,7 +20,7 @@ type errorMessage struct {
Message string `json:"errorMessage"`
}
-// LogProject defines the Ali Project detail
+// LogProject Define the Ali Project detail
type LogProject struct {
Name string // Project name
Endpoint string // IP or hostname of SLS endpoint
diff --git a/core/logs/alils/log_store.go b/logs/alils/log_store.go
similarity index 98%
rename from core/logs/alils/log_store.go
rename to logs/alils/log_store.go
index d5ff25e2..fa502736 100755
--- a/core/logs/alils/log_store.go
+++ b/logs/alils/log_store.go
@@ -12,7 +12,7 @@ import (
"github.com/gogo/protobuf/proto"
)
-// LogStore stores the logs
+// LogStore Store the logs
type LogStore struct {
Name string `json:"logstoreName"`
TTL int
@@ -24,7 +24,7 @@ type LogStore struct {
project *LogProject
}
-// Shard defines the Log Shard
+// Shard define the Log Shard
type Shard struct {
ShardID int `json:"shardID"`
}
@@ -71,7 +71,7 @@ func (s *LogStore) ListShards() (shardIDs []int, err error) {
return
}
-// PutLogs puts logs into logstore.
+// PutLogs put logs into logstore.
// The callers should transform user logs into LogGroup.
func (s *LogStore) PutLogs(lg *LogGroup) (err error) {
body, err := proto.Marshal(lg)
diff --git a/core/logs/alils/machine_group.go b/logs/alils/machine_group.go
similarity index 88%
rename from core/logs/alils/machine_group.go
rename to logs/alils/machine_group.go
index 101faeb4..b6c69a14 100755
--- a/core/logs/alils/machine_group.go
+++ b/logs/alils/machine_group.go
@@ -8,13 +8,13 @@ import (
"net/http/httputil"
)
-// MachineGroupAttribute defines the Attribute
+// MachineGroupAttribute define the Attribute
type MachineGroupAttribute struct {
ExternalName string `json:"externalName"`
TopicName string `json:"groupTopic"`
}
-// MachineGroup defines the machine Group
+// MachineGroup define the machine Group
type MachineGroup struct {
Name string `json:"groupName"`
Type string `json:"groupType"`
@@ -29,20 +29,20 @@ type MachineGroup struct {
project *LogProject
}
-// Machine defines the Machine
+// Machine define the Machine
type Machine struct {
IP string
UniqueID string `json:"machine-uniqueid"`
UserdefinedID string `json:"userdefined-id"`
}
-// MachineList defines the Machine List
+// MachineList define the Machine List
type MachineList struct {
Total int
Machines []*Machine
}
-// ListMachines returns the machine list of this machine group.
+// ListMachines returns machine list of this machine group.
func (m *MachineGroup) ListMachines() (ms []*Machine, total int, err error) {
h := map[string]string{
"x-sls-bodyrawsize": "0",
diff --git a/core/logs/alils/request.go b/logs/alils/request.go
similarity index 100%
rename from core/logs/alils/request.go
rename to logs/alils/request.go
diff --git a/core/logs/alils/signature.go b/logs/alils/signature.go
similarity index 100%
rename from core/logs/alils/signature.go
rename to logs/alils/signature.go
diff --git a/core/logs/conn.go b/logs/conn.go
similarity index 65%
rename from core/logs/conn.go
rename to logs/conn.go
index 1fd71be7..afe0cbb7 100644
--- a/core/logs/conn.go
+++ b/logs/conn.go
@@ -16,20 +16,16 @@ package logs
import (
"encoding/json"
- "fmt"
"io"
"net"
-
- "github.com/pkg/errors"
+ "time"
)
// connWriter implements LoggerInterface.
-// Writes messages in keep-live tcp connection.
+// it writes messages in keep-live tcp connection.
type connWriter struct {
lg *logWriter
innerWriter io.WriteCloser
- formatter LogFormatter
- Formatter string `json:"formatter"`
ReconnectOnMsg bool `json:"reconnectOnMsg"`
Reconnect bool `json:"reconnect"`
Net string `json:"net"`
@@ -37,40 +33,23 @@ type connWriter struct {
Level int `json:"level"`
}
-// NewConn creates new ConnWrite returning as LoggerInterface.
+// NewConn create new ConnWrite returning as LoggerInterface.
func NewConn() Logger {
conn := new(connWriter)
conn.Level = LevelTrace
- conn.formatter = conn
return conn
}
-func (c *connWriter) Format(lm *LogMsg) string {
- return lm.OldStyleFormat()
+// Init init connection writer with json config.
+// json config only need key "level".
+func (c *connWriter) Init(jsonConfig string) error {
+ return json.Unmarshal([]byte(jsonConfig), c)
}
-// Init initializes a connection writer with json config.
-// json config only needs they "level" key
-func (c *connWriter) Init(config string) error {
- res := json.Unmarshal([]byte(config), c)
- if res == nil && len(c.Formatter) > 0 {
- fmtr, ok := GetFormatter(c.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", c.Formatter))
- }
- c.formatter = fmtr
- }
- return res
-}
-
-func (c *connWriter) SetFormatter(f LogFormatter) {
- c.formatter = f
-}
-
-// WriteMsg writes message in connection.
-// If connection is down, try to re-connect.
-func (c *connWriter) WriteMsg(lm *LogMsg) error {
- if lm.Level > c.Level {
+// WriteMsg write message in connection.
+// if connection is down, try to re-connect.
+func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > c.Level {
return nil
}
if c.needToConnectOnMsg() {
@@ -84,12 +63,7 @@ func (c *connWriter) WriteMsg(lm *LogMsg) error {
defer c.innerWriter.Close()
}
- msg := c.formatter.Format(lm)
-
- _, err := c.lg.writeln(msg)
- if err != nil {
- return err
- }
+ c.lg.writeln(when, msg)
return nil
}
@@ -127,6 +101,7 @@ func (c *connWriter) connect() error {
func (c *connWriter) needToConnectOnMsg() bool {
if c.Reconnect {
+ c.Reconnect = false
return true
}
diff --git a/adapter/utils/caller.go b/logs/conn_test.go
similarity index 78%
rename from adapter/utils/caller.go
rename to logs/conn_test.go
index 419f11d6..747fb890 100644
--- a/adapter/utils/caller.go
+++ b/logs/conn_test.go
@@ -12,13 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package utils
+package logs
import (
- "github.com/astaxie/beego/core/utils"
+ "testing"
)
-// GetFuncName get function name
-func GetFuncName(i interface{}) string {
- return utils.GetFuncName(i)
+func TestConn(t *testing.T) {
+ log := NewLogger(1000)
+ log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
+ log.Informational("informational")
}
diff --git a/core/logs/console.go b/logs/console.go
similarity index 57%
rename from core/logs/console.go
rename to logs/console.go
index 66e2c7ea..3dcaee1d 100644
--- a/core/logs/console.go
+++ b/logs/console.go
@@ -16,18 +16,17 @@ package logs
import (
"encoding/json"
- "fmt"
"os"
"strings"
+ "time"
- "github.com/pkg/errors"
"github.com/shiena/ansicolor"
)
// brush is a color join function
type brush func(string) string
-// newBrush returns a fix color Brush
+// newBrush return a fix color Brush
func newBrush(color string) brush {
pre := "\033["
reset := "\033[0m"
@@ -49,68 +48,39 @@ var colors = []brush{
// consoleWriter implements LoggerInterface and writes messages to terminal.
type consoleWriter struct {
- lg *logWriter
- formatter LogFormatter
- Formatter string `json:"formatter"`
- Level int `json:"level"`
- Colorful bool `json:"color"` // this filed is useful only when system's terminal supports color
+ lg *logWriter
+ Level int `json:"level"`
+ Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color
}
-func (c *consoleWriter) Format(lm *LogMsg) string {
- msg := lm.OldStyleFormat()
- if c.Colorful {
- msg = strings.Replace(msg, levelPrefix[lm.Level], colors[lm.Level](levelPrefix[lm.Level]), 1)
- }
- h, _, _ := formatTimeHeader(lm.When)
- bytes := append(append(h, msg...), '\n')
- return string(bytes)
-}
-
-func (c *consoleWriter) SetFormatter(f LogFormatter) {
- c.formatter = f
-}
-
-// NewConsole creates ConsoleWriter returning as LoggerInterface.
+// NewConsole create ConsoleWriter returning as LoggerInterface.
func NewConsole() Logger {
- return newConsole()
-}
-
-func newConsole() *consoleWriter {
cw := &consoleWriter{
lg: newLogWriter(ansicolor.NewAnsiColorWriter(os.Stdout)),
Level: LevelDebug,
Colorful: true,
}
- cw.formatter = cw
return cw
}
-// Init initianlizes the console logger.
-// jsonConfig must be in the format '{"level":LevelTrace}'
-func (c *consoleWriter) Init(config string) error {
-
- if len(config) == 0 {
+// Init init console logger.
+// jsonConfig like '{"level":LevelTrace}'.
+func (c *consoleWriter) Init(jsonConfig string) error {
+ if len(jsonConfig) == 0 {
return nil
}
-
- res := json.Unmarshal([]byte(config), c)
- if res == nil && len(c.Formatter) > 0 {
- fmtr, ok := GetFormatter(c.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", c.Formatter))
- }
- c.formatter = fmtr
- }
- return res
+ return json.Unmarshal([]byte(jsonConfig), c)
}
-// WriteMsg writes message in console.
-func (c *consoleWriter) WriteMsg(lm *LogMsg) error {
- if lm.Level > c.Level {
+// WriteMsg write message in console.
+func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > c.Level {
return nil
}
- msg := c.formatter.Format(lm)
- c.lg.writeln(msg)
+ if c.Colorful {
+ msg = strings.Replace(msg, levelPrefix[level], colors[level](levelPrefix[level]), 1)
+ }
+ c.lg.writeln(when, msg)
return nil
}
diff --git a/core/logs/console_test.go b/logs/console_test.go
similarity index 78%
rename from core/logs/console_test.go
rename to logs/console_test.go
index e345ba40..4bc45f57 100644
--- a/core/logs/console_test.go
+++ b/logs/console_test.go
@@ -17,8 +17,6 @@ package logs
import (
"testing"
"time"
-
- "github.com/stretchr/testify/assert"
)
// Try each log level in decreasing order of priority.
@@ -64,19 +62,3 @@ func TestConsoleAsync(t *testing.T) {
time.Sleep(1 * time.Millisecond)
}
}
-
-func TestFormat(t *testing.T) {
- log := newConsole()
- lm := &LogMsg{
- Level: LevelDebug,
- Msg: "Hello, world",
- When: time.Date(2020, 9, 19, 20, 12, 37, 9, time.UTC),
- FilePath: "/user/home/main.go",
- LineNumber: 13,
- Prefix: "Cus",
- }
- res := log.Format(lm)
- assert.Equal(t, "2020/09/19 20:12:37.000 \x1b[1;44m[D]\x1b[0m Cus Hello, world\n", res)
- err := log.WriteMsg(lm)
- assert.Nil(t, err)
-}
diff --git a/core/logs/es/es.go b/logs/es/es.go
similarity index 56%
rename from core/logs/es/es.go
rename to logs/es/es.go
index 6175f253..2b7b1710 100644
--- a/core/logs/es/es.go
+++ b/logs/es/es.go
@@ -12,14 +12,13 @@ import (
"github.com/elastic/go-elasticsearch/v6"
"github.com/elastic/go-elasticsearch/v6/esapi"
- "github.com/astaxie/beego/core/logs"
+ "github.com/astaxie/beego/logs"
)
-// NewES returns a LoggerInterface
+// NewES return a LoggerInterface
func NewES() logs.Logger {
cw := &esLogger{
- Level: logs.LevelDebug,
- indexNaming: indexNaming,
+ Level: logs.LevelDebug,
}
return cw
}
@@ -32,36 +31,13 @@ func NewES() logs.Logger {
// import _ "github.com/astaxie/beego/logs/es"
type esLogger struct {
*elasticsearch.Client
- DSN string `json:"dsn"`
- Level int `json:"level"`
- formatter logs.LogFormatter
- Formatter string `json:"formatter"`
-
- indexNaming IndexNaming
-}
-
-func (el *esLogger) Format(lm *logs.LogMsg) string {
-
- msg := lm.OldStyleFormat()
- idx := LogDocument{
- Timestamp: lm.When.Format(time.RFC3339),
- Msg: msg,
- }
- body, err := json.Marshal(idx)
- if err != nil {
- return msg
- }
- return string(body)
-}
-
-func (el *esLogger) SetFormatter(f logs.LogFormatter) {
- el.formatter = f
+ DSN string `json:"dsn"`
+ Level int `json:"level"`
}
// {"dsn":"http://localhost:9200/","level":1}
-func (el *esLogger) Init(config string) error {
-
- err := json.Unmarshal([]byte(config), el)
+func (el *esLogger) Init(jsonconfig string) error {
+ err := json.Unmarshal([]byte(jsonconfig), el)
if err != nil {
return err
}
@@ -80,30 +56,30 @@ func (el *esLogger) Init(config string) error {
}
el.Client = conn
}
- if len(el.Formatter) > 0 {
- fmtr, ok := logs.GetFormatter(el.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", el.Formatter))
- }
- el.formatter = fmtr
- }
return nil
}
-// WriteMsg writes the msg and level into es
-func (el *esLogger) WriteMsg(lm *logs.LogMsg) error {
- if lm.Level > el.Level {
+// WriteMsg will write the msg and level into es
+func (el *esLogger) WriteMsg(when time.Time, msg string, level int) error {
+ if level > el.Level {
return nil
}
- msg := el.formatter.Format(lm)
-
- req := esapi.IndexRequest{
- Index: indexNaming.IndexName(lm),
- DocumentType: "logs",
- Body: strings.NewReader(msg),
+ idx := LogDocument{
+ Timestamp: when.Format(time.RFC3339),
+ Msg: msg,
}
- _, err := req.Do(context.Background(), el.Client)
+
+ body, err := json.Marshal(idx)
+ if err != nil {
+ return err
+ }
+ req := esapi.IndexRequest{
+ Index: fmt.Sprintf("%04d.%02d.%02d", when.Year(), when.Month(), when.Day()),
+ DocumentType: "logs",
+ Body: strings.NewReader(string(body)),
+ }
+ _, err = req.Do(context.Background(), el.Client)
return err
}
diff --git a/core/logs/file.go b/logs/file.go
similarity index 80%
rename from core/logs/file.go
rename to logs/file.go
index b01be357..222db989 100644
--- a/core/logs/file.go
+++ b/logs/file.go
@@ -30,7 +30,7 @@ import (
)
// fileLogWriter implements LoggerInterface.
-// Writes messages by lines limit, file size limit, or time frequency.
+// It writes messages by lines limit, file size limit, or time frequency.
type fileLogWriter struct {
sync.RWMutex // write log order by order and atomic incr maxLinesCurLines and maxSizeCurSize
// The opened file
@@ -69,12 +69,9 @@ type fileLogWriter struct {
RotatePerm string `json:"rotateperm"`
fileNameOnly, suffix string // like "project.log", project is fileNameOnly and .log is suffix
-
- formatter LogFormatter
- Formatter string `json:"formatter"`
}
-// newFileWriter creates a FileLogWriter returning as LoggerInterface.
+// newFileWriter create a FileLogWriter returning as LoggerInterface.
func newFileWriter() Logger {
w := &fileLogWriter{
Daily: true,
@@ -89,21 +86,9 @@ func newFileWriter() Logger {
MaxFiles: 999,
MaxSize: 1 << 28,
}
- w.formatter = w
return w
}
-func (w *fileLogWriter) Format(lm *LogMsg) string {
- msg := lm.OldStyleFormat()
- hd, _, _ := formatTimeHeader(lm.When)
- msg = fmt.Sprintf("%s %s\n", string(hd), msg)
- return msg
-}
-
-func (w *fileLogWriter) SetFormatter(f LogFormatter) {
- w.formatter = f
-}
-
// Init file logger with json config.
// jsonConfig like:
// {
@@ -115,9 +100,8 @@ func (w *fileLogWriter) SetFormatter(f LogFormatter) {
// "rotate":true,
// "perm":"0600"
// }
-func (w *fileLogWriter) Init(config string) error {
-
- err := json.Unmarshal([]byte(config), w)
+func (w *fileLogWriter) Init(jsonConfig string) error {
+ err := json.Unmarshal([]byte(jsonConfig), w)
if err != nil {
return err
}
@@ -129,14 +113,6 @@ func (w *fileLogWriter) Init(config string) error {
if w.suffix == "" {
w.suffix = ".log"
}
-
- if len(w.Formatter) > 0 {
- fmtr, ok := GetFormatter(w.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", w.Formatter))
- }
- w.formatter = fmtr
- }
err = w.startLogger()
return err
}
@@ -154,44 +130,42 @@ func (w *fileLogWriter) startLogger() error {
return w.initFd()
}
-func (w *fileLogWriter) needRotateDaily(day int) bool {
+func (w *fileLogWriter) needRotateDaily(size int, day int) bool {
return (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) ||
(w.MaxSize > 0 && w.maxSizeCurSize >= w.MaxSize) ||
(w.Daily && day != w.dailyOpenDate)
}
-func (w *fileLogWriter) needRotateHourly(hour int) bool {
+func (w *fileLogWriter) needRotateHourly(size int, hour int) bool {
return (w.MaxLines > 0 && w.maxLinesCurLines >= w.MaxLines) ||
(w.MaxSize > 0 && w.maxSizeCurSize >= w.MaxSize) ||
(w.Hourly && hour != w.hourlyOpenDate)
}
-// WriteMsg writes logger message into file.
-func (w *fileLogWriter) WriteMsg(lm *LogMsg) error {
- if lm.Level > w.Level {
+// WriteMsg write logger message into file.
+func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > w.Level {
return nil
}
-
- _, d, h := formatTimeHeader(lm.When)
-
- msg := w.formatter.Format(lm)
+ hd, d, h := formatTimeHeader(when)
+ msg = string(hd) + msg + "\n"
if w.Rotate {
w.RLock()
- if w.needRotateHourly(h) {
+ if w.needRotateHourly(len(msg), h) {
w.RUnlock()
w.Lock()
- if w.needRotateHourly(h) {
- if err := w.doRotate(lm.When); err != nil {
+ if w.needRotateHourly(len(msg), h) {
+ if err := w.doRotate(when); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
}
w.Unlock()
- } else if w.needRotateDaily(d) {
+ } else if w.needRotateDaily(len(msg), d) {
w.RUnlock()
w.Lock()
- if w.needRotateDaily(d) {
- if err := w.doRotate(lm.When); err != nil {
+ if w.needRotateDaily(len(msg), d) {
+ if err := w.doRotate(when); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
}
@@ -262,7 +236,7 @@ func (w *fileLogWriter) dailyRotate(openTime time.Time) {
tm := time.NewTimer(time.Duration(nextDay.UnixNano() - openTime.UnixNano() + 100))
<-tm.C
w.Lock()
- if w.needRotateDaily(time.Now().Day()) {
+ if w.needRotateDaily(0, time.Now().Day()) {
if err := w.doRotate(time.Now()); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
@@ -277,7 +251,7 @@ func (w *fileLogWriter) hourlyRotate(openTime time.Time) {
tm := time.NewTimer(time.Duration(nextHour.UnixNano() - openTime.UnixNano() + 100))
<-tm.C
w.Lock()
- if w.needRotateHourly(time.Now().Hour()) {
+ if w.needRotateHourly(0, time.Now().Hour()) {
if err := w.doRotate(time.Now()); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
@@ -312,7 +286,7 @@ func (w *fileLogWriter) lines() (int, error) {
return count, nil
}
-// DoRotate means it needs to write logs into a new file.
+// DoRotate means it need to write file in new file.
// new file name like xx.2013-01-01.log (daily) or xx.001.log (by line or size)
func (w *fileLogWriter) doRotate(logTime time.Time) error {
// file exists
@@ -328,7 +302,7 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error {
_, err = os.Lstat(w.Filename)
if err != nil {
- // even if the file is not exist or other ,we should RESTART the logger
+ //even if the file is not exist or other ,we should RESTART the logger
goto RESTART_LOGGER
}
@@ -399,21 +373,21 @@ func (w *fileLogWriter) deleteOldLog() {
if info == nil {
return
}
- if w.Hourly {
- if !info.IsDir() && info.ModTime().Add(1*time.Hour*time.Duration(w.MaxHours)).Before(time.Now()) {
- if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
- strings.HasSuffix(filepath.Base(path), w.suffix) {
- os.Remove(path)
- }
- }
- } else if w.Daily {
- if !info.IsDir() && info.ModTime().Add(24*time.Hour*time.Duration(w.MaxDays)).Before(time.Now()) {
- if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
- strings.HasSuffix(filepath.Base(path), w.suffix) {
- os.Remove(path)
- }
- }
- }
+ if w.Hourly {
+ if !info.IsDir() && info.ModTime().Add(1 * time.Hour * time.Duration(w.MaxHours)).Before(time.Now()) {
+ if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
+ strings.HasSuffix(filepath.Base(path), w.suffix) {
+ os.Remove(path)
+ }
+ }
+ } else if w.Daily {
+ if !info.IsDir() && info.ModTime().Add(24 * time.Hour * time.Duration(w.MaxDays)).Before(time.Now()) {
+ if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
+ strings.HasSuffix(filepath.Base(path), w.suffix) {
+ os.Remove(path)
+ }
+ }
+ }
return
})
}
@@ -423,7 +397,7 @@ func (w *fileLogWriter) Destroy() {
w.fileWriter.Close()
}
-// Flush flushes file logger.
+// Flush flush file logger.
// there are no buffering messages in file logger in memory.
// flush file means sync file from disk.
func (w *fileLogWriter) Flush() {
diff --git a/core/logs/file_test.go b/logs/file_test.go
similarity index 89%
rename from core/logs/file_test.go
rename to logs/file_test.go
index 6612ebe6..e7c2ca9a 100644
--- a/core/logs/file_test.go
+++ b/logs/file_test.go
@@ -22,8 +22,6 @@ import (
"strconv"
"testing"
"time"
-
- "github.com/stretchr/testify/assert"
)
func TestFilePerm(t *testing.T) {
@@ -188,7 +186,7 @@ func TestFileDailyRotate_06(t *testing.T) { //test file mode
func TestFileHourlyRotate_01(t *testing.T) {
log := NewLogger(10000)
- log.SetLogger("file", `{"filename":"test3.log","hourly":true,"maxlines":4}`)
+ log.SetLogger("file", `{"filename":"test3.log","hourly":true,"maxlines":4}`)
log.Debug("debug")
log.Info("info")
log.Notice("notice")
@@ -239,7 +237,7 @@ func TestFileHourlyRotate_05(t *testing.T) {
func TestFileHourlyRotate_06(t *testing.T) { //test file mode
log := NewLogger(10000)
- log.SetLogger("file", `{"filename":"test3.log", "hourly":true, "maxlines":4}`)
+ log.SetLogger("file", `{"filename":"test3.log", "hourly":true, "maxlines":4}`)
log.Debug("debug")
log.Info("info")
log.Notice("notice")
@@ -270,26 +268,20 @@ func testFileRotate(t *testing.T, fn1, fn2 string, daily, hourly bool) {
Perm: "0660",
RotatePerm: "0440",
}
- fw.formatter = fw
- if daily {
- fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
- fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
- fw.dailyOpenDate = fw.dailyOpenTime.Day()
- }
+ if daily {
+ fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
+ fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
+ fw.dailyOpenDate = fw.dailyOpenTime.Day()
+ }
- if hourly {
- fw.Init(fmt.Sprintf(`{"filename":"%v","maxhours":1}`, fn1))
- fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
- fw.hourlyOpenDate = fw.hourlyOpenTime.Day()
- }
- lm := &LogMsg{
- Msg: "Test message",
- Level: LevelDebug,
- When: time.Now(),
- }
+ if hourly {
+ fw.Init(fmt.Sprintf(`{"filename":"%v","maxhours":1}`, fn1))
+ fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
+ fw.hourlyOpenDate = fw.hourlyOpenTime.Day()
+ }
- fw.WriteMsg(lm)
+ fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
for _, file := range []string{fn1, fn2} {
_, err := os.Stat(file)
@@ -311,8 +303,6 @@ func testFileDailyRotate(t *testing.T, fn1, fn2 string) {
Perm: "0660",
RotatePerm: "0440",
}
- fw.formatter = fw
-
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
fw.dailyOpenDate = fw.dailyOpenTime.Day()
@@ -338,15 +328,13 @@ func testFileDailyRotate(t *testing.T, fn1, fn2 string) {
func testFileHourlyRotate(t *testing.T, fn1, fn2 string) {
fw := &fileLogWriter{
- Hourly: true,
- MaxHours: 168,
+ Hourly: true,
+ MaxHours: 168,
Rotate: true,
Level: LevelTrace,
Perm: "0660",
RotatePerm: "0440",
}
-
- fw.formatter = fw
fw.Init(fmt.Sprintf(`{"filename":"%v","maxhours":1}`, fn1))
fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
fw.hourlyOpenDate = fw.hourlyOpenTime.Hour()
@@ -430,18 +418,3 @@ func BenchmarkFileOnGoroutine(b *testing.B) {
}
os.Remove("test4.log")
}
-
-func TestFileLogWriter_Format(t *testing.T) {
- lg := &LogMsg{
- Level: LevelDebug,
- Msg: "Hello, world",
- When: time.Date(2020, 9, 19, 20, 12, 37, 9, time.UTC),
- FilePath: "/user/home/main.go",
- LineNumber: 13,
- Prefix: "Cus",
- }
-
- fw := newFileWriter().(*fileLogWriter)
- res := fw.Format(lg)
- assert.Equal(t, "2020/09/19 20:12:37.000 [D] Cus Hello, world\n", res)
-}
diff --git a/core/logs/jianliao.go b/logs/jianliao.go
similarity index 56%
rename from core/logs/jianliao.go
rename to logs/jianliao.go
index c82a0957..88ba0f9a 100644
--- a/core/logs/jianliao.go
+++ b/logs/jianliao.go
@@ -5,8 +5,7 @@ import (
"fmt"
"net/http"
"net/url"
-
- "github.com/pkg/errors"
+ "time"
)
// JLWriter implements beego LoggerInterface and is used to send jiaoliao webhook
@@ -17,50 +16,26 @@ type JLWriter struct {
RedirectURL string `json:"redirecturl,omitempty"`
ImageURL string `json:"imageurl,omitempty"`
Level int `json:"level"`
-
- formatter LogFormatter
- Formatter string `json:"formatter"`
}
-// newJLWriter creates jiaoliao writer.
+// newJLWriter create jiaoliao writer.
func newJLWriter() Logger {
- res := &JLWriter{Level: LevelTrace}
- res.formatter = res
- return res
+ return &JLWriter{Level: LevelTrace}
}
// Init JLWriter with json config string
-func (s *JLWriter) Init(config string) error {
-
- res := json.Unmarshal([]byte(config), s)
- if res == nil && len(s.Formatter) > 0 {
- fmtr, ok := GetFormatter(s.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", s.Formatter))
- }
- s.formatter = fmtr
- }
- return res
+func (s *JLWriter) Init(jsonconfig string) error {
+ return json.Unmarshal([]byte(jsonconfig), s)
}
-func (s *JLWriter) Format(lm *LogMsg) string {
- msg := lm.OldStyleFormat()
- msg = fmt.Sprintf("%s %s", lm.When.Format("2006-01-02 15:04:05"), msg)
- return msg
-}
-
-func (s *JLWriter) SetFormatter(f LogFormatter) {
- s.formatter = f
-}
-
-// WriteMsg writes message in smtp writer.
-// Sends an email with subject and only this message.
-func (s *JLWriter) WriteMsg(lm *LogMsg) error {
- if lm.Level > s.Level {
+// WriteMsg write message in smtp writer.
+// it will send an email with subject and only this message.
+func (s *JLWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > s.Level {
return nil
}
- text := s.formatter.Format(lm)
+ text := fmt.Sprintf("%s %s", when.Format("2006-01-02 15:04:05"), msg)
form := url.Values{}
form.Add("authorName", s.AuthorName)
diff --git a/core/logs/log.go b/logs/log.go
similarity index 78%
rename from core/logs/log.go
rename to logs/log.go
index d5953dfb..39c006d2 100644
--- a/core/logs/log.go
+++ b/logs/log.go
@@ -37,12 +37,12 @@ import (
"fmt"
"log"
"os"
+ "path"
"runtime"
+ "strconv"
"strings"
"sync"
"time"
-
- "github.com/pkg/errors"
)
// RFC5424 log message levels.
@@ -86,10 +86,9 @@ type newLoggerFunc func() Logger
// Logger defines the behavior of a log provider.
type Logger interface {
Init(config string) error
- WriteMsg(lm *LogMsg) error
+ WriteMsg(when time.Time, msg string, level int) error
Destroy()
Flush()
- SetFormatter(f LogFormatter)
}
var adapters = make(map[string]newLoggerFunc)
@@ -109,22 +108,20 @@ func Register(name string, log newLoggerFunc) {
}
// BeeLogger is default logger in beego application.
-// Can contain several providers and log message into all providers.
+// it can contain several providers and log message into all providers.
type BeeLogger struct {
lock sync.Mutex
level int
init bool
enableFuncCallDepth bool
loggerFuncCallDepth int
- enableFullFilePath bool
asynchronous bool
prefix string
msgChanLen int64
- msgChan chan *LogMsg
+ msgChan chan *logMsg
signalChan chan string
wg sync.WaitGroup
outputs []*nameLogger
- globalFormatter string
}
const defaultAsyncMsgLen = 1e3
@@ -134,15 +131,21 @@ type nameLogger struct {
name string
}
+type logMsg struct {
+ level int
+ msg string
+ when time.Time
+}
+
var logMsgPool *sync.Pool
// NewLogger returns a new BeeLogger.
-// channelLen: the number of messages in chan(used where asynchronous is true).
+// channelLen means the number of messages in chan(used where asynchronous is true).
// if the buffering chan is full, logger adapters write to file or other way.
func NewLogger(channelLens ...int64) *BeeLogger {
bl := new(BeeLogger)
bl.level = LevelDebug
- bl.loggerFuncCallDepth = 3
+ bl.loggerFuncCallDepth = 2
bl.msgChanLen = append(channelLens, 0)[0]
if bl.msgChanLen <= 0 {
bl.msgChanLen = defaultAsyncMsgLen
@@ -152,7 +155,7 @@ func NewLogger(channelLens ...int64) *BeeLogger {
return bl
}
-// Async sets the log to asynchronous and start the goroutine
+// Async set the log to asynchronous and start the goroutine
func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger {
bl.lock.Lock()
defer bl.lock.Unlock()
@@ -163,10 +166,10 @@ func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger {
if len(msgLen) > 0 && msgLen[0] > 0 {
bl.msgChanLen = msgLen[0]
}
- bl.msgChan = make(chan *LogMsg, bl.msgChanLen)
+ bl.msgChan = make(chan *logMsg, bl.msgChanLen)
logMsgPool = &sync.Pool{
New: func() interface{} {
- return &LogMsg{}
+ return &logMsg{}
},
}
bl.wg.Add(1)
@@ -175,7 +178,7 @@ func (bl *BeeLogger) Async(msgLen ...int64) *BeeLogger {
}
// SetLogger provides a given logger adapter into BeeLogger with config string.
-// config must in in JSON format like {"interval":360}}
+// config need to be correct JSON as string: {"interval":360}.
func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error {
config := append(configs, "{}")[0]
for _, l := range bl.outputs {
@@ -190,18 +193,7 @@ func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error {
}
lg := logAdapter()
-
- // Global formatter overrides the default set formatter
- if len(bl.globalFormatter) > 0 {
- fmtr, ok := GetFormatter(bl.globalFormatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", bl.globalFormatter))
- }
- lg.SetFormatter(fmtr)
- }
-
err := lg.Init(config)
-
if err != nil {
fmt.Fprintln(os.Stderr, "logs.BeeLogger.SetLogger: "+err.Error())
return err
@@ -211,7 +203,7 @@ func (bl *BeeLogger) setLogger(adapterName string, configs ...string) error {
}
// SetLogger provides a given logger adapter into BeeLogger with config string.
-// config must in in JSON format like {"interval":360}}
+// config need to be correct JSON as string: {"interval":360}.
func (bl *BeeLogger) SetLogger(adapterName string, configs ...string) error {
bl.lock.Lock()
defer bl.lock.Unlock()
@@ -222,7 +214,7 @@ func (bl *BeeLogger) SetLogger(adapterName string, configs ...string) error {
return bl.setLogger(adapterName, configs...)
}
-// DelLogger removes a logger adapter in BeeLogger.
+// DelLogger remove a logger adapter in BeeLogger.
func (bl *BeeLogger) DelLogger(adapterName string) error {
bl.lock.Lock()
defer bl.lock.Unlock()
@@ -241,9 +233,9 @@ func (bl *BeeLogger) DelLogger(adapterName string) error {
return nil
}
-func (bl *BeeLogger) writeToLoggers(lm *LogMsg) {
+func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) {
for _, l := range bl.outputs {
- err := l.WriteMsg(lm)
+ err := l.WriteMsg(when, msg, level)
if err != nil {
fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err)
}
@@ -258,72 +250,65 @@ func (bl *BeeLogger) Write(p []byte) (n int, err error) {
if p[len(p)-1] == '\n' {
p = p[0 : len(p)-1]
}
- lm := &LogMsg{
- Msg: string(p),
- Level: levelLoggerImpl,
- }
-
// set levelLoggerImpl to ensure all log message will be write out
- err = bl.writeMsg(lm)
+ err = bl.writeMsg(levelLoggerImpl, string(p))
if err == nil {
return len(p), err
}
return 0, err
}
-func (bl *BeeLogger) writeMsg(lm *LogMsg) error {
+func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error {
if !bl.init {
bl.lock.Lock()
bl.setLogger(AdapterConsole)
bl.lock.Unlock()
}
- var (
- file string
- line int
- ok bool
- )
-
- _, file, line, ok = runtime.Caller(bl.loggerFuncCallDepth)
- if !ok {
- file = "???"
- line = 0
+ if len(v) > 0 {
+ msg = fmt.Sprintf(msg, v...)
}
- lm.FilePath = file
- lm.LineNumber = line
- lm.enableFullFilePath = bl.enableFullFilePath
- lm.enableFuncCallDepth = bl.enableFuncCallDepth
+ msg = bl.prefix + " " + msg
- // set level info in front of filename info
- if lm.Level == levelLoggerImpl {
+ when := time.Now()
+ if bl.enableFuncCallDepth {
+ _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth)
+ if !ok {
+ file = "???"
+ line = 0
+ }
+ _, filename := path.Split(file)
+ msg = "[" + filename + ":" + strconv.Itoa(line) + "] " + msg
+ }
+
+ //set level info in front of filename info
+ if logLevel == levelLoggerImpl {
// set to emergency to ensure all log will be print out correctly
- lm.Level = LevelEmergency
+ logLevel = LevelEmergency
+ } else {
+ msg = levelPrefix[logLevel] + " " + msg
}
if bl.asynchronous {
- logM := logMsgPool.Get().(*LogMsg)
- logM.Level = lm.Level
- logM.Msg = lm.Msg
- logM.When = lm.When
- logM.Args = lm.Args
- logM.FilePath = lm.FilePath
- logM.LineNumber = lm.LineNumber
- logM.Prefix = lm.Prefix
+ lm := logMsgPool.Get().(*logMsg)
+ lm.level = logLevel
+ lm.msg = msg
+ lm.when = when
if bl.outputs != nil {
bl.msgChan <- lm
} else {
logMsgPool.Put(lm)
}
} else {
- bl.writeToLoggers(lm)
+ bl.writeToLoggers(when, msg, logLevel)
}
return nil
}
-// SetLevel sets log message level.
+// SetLevel Set log message level.
// If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
-// log providers will not be sent the message.
+// log providers will not even be sent the message.
func (bl *BeeLogger) SetLevel(l int) {
bl.level = l
}
@@ -360,7 +345,7 @@ func (bl *BeeLogger) startLogger() {
for {
select {
case bm := <-bl.msgChan:
- bl.writeToLoggers(bm)
+ bl.writeToLoggers(bm.when, bm.msg, bm.level)
logMsgPool.Put(bm)
case sg := <-bl.signalChan:
// Now should only send "flush" or "close" to bl.signalChan
@@ -380,33 +365,12 @@ func (bl *BeeLogger) startLogger() {
}
}
-func (bl *BeeLogger) setGlobalFormatter(fmtter string) error {
- bl.globalFormatter = fmtter
- return nil
-}
-
-// SetGlobalFormatter sets the global formatter for all log adapters
-// don't forget to register the formatter by invoking RegisterFormatter
-func SetGlobalFormatter(fmtter string) error {
- return beeLogger.setGlobalFormatter(fmtter)
-}
-
// Emergency Log EMERGENCY level message.
func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
if LevelEmergency > bl.level {
return
}
-
- lm := &LogMsg{
- Level: LevelEmergency,
- Msg: format,
- When: time.Now(),
- }
- if len(v) > 0 {
- lm.Msg = fmt.Sprintf(lm.Msg, v...)
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelEmergency, format, v...)
}
// Alert Log ALERT level message.
@@ -414,14 +378,7 @@ func (bl *BeeLogger) Alert(format string, v ...interface{}) {
if LevelAlert > bl.level {
return
}
-
- lm := &LogMsg{
- Level: LevelAlert,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
- bl.writeMsg(lm)
+ bl.writeMsg(LevelAlert, format, v...)
}
// Critical Log CRITICAL level message.
@@ -429,14 +386,7 @@ func (bl *BeeLogger) Critical(format string, v ...interface{}) {
if LevelCritical > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelCritical,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelCritical, format, v...)
}
// Error Log ERROR level message.
@@ -444,14 +394,7 @@ func (bl *BeeLogger) Error(format string, v ...interface{}) {
if LevelError > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelError,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelError, format, v...)
}
// Warning Log WARNING level message.
@@ -459,14 +402,7 @@ func (bl *BeeLogger) Warning(format string, v ...interface{}) {
if LevelWarn > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelWarn,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelWarn, format, v...)
}
// Notice Log NOTICE level message.
@@ -474,14 +410,7 @@ func (bl *BeeLogger) Notice(format string, v ...interface{}) {
if LevelNotice > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelNotice,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelNotice, format, v...)
}
// Informational Log INFORMATIONAL level message.
@@ -489,14 +418,7 @@ func (bl *BeeLogger) Informational(format string, v ...interface{}) {
if LevelInfo > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelInfo,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelInfo, format, v...)
}
// Debug Log DEBUG level message.
@@ -504,14 +426,7 @@ func (bl *BeeLogger) Debug(format string, v ...interface{}) {
if LevelDebug > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelDebug,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelDebug, format, v...)
}
// Warn Log WARN level message.
@@ -520,14 +435,7 @@ func (bl *BeeLogger) Warn(format string, v ...interface{}) {
if LevelWarn > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelWarn,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelWarn, format, v...)
}
// Info Log INFO level message.
@@ -536,14 +444,7 @@ func (bl *BeeLogger) Info(format string, v ...interface{}) {
if LevelInfo > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelInfo,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelInfo, format, v...)
}
// Trace Log TRACE level message.
@@ -552,14 +453,7 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) {
if LevelDebug > bl.level {
return
}
- lm := &LogMsg{
- Level: LevelDebug,
- Msg: format,
- When: time.Now(),
- Args: v,
- }
-
- bl.writeMsg(lm)
+ bl.writeMsg(LevelDebug, format, v...)
}
// Flush flush all chan data.
@@ -603,7 +497,7 @@ func (bl *BeeLogger) flush() {
for {
if len(bl.msgChan) > 0 {
bm := <-bl.msgChan
- bl.writeToLoggers(bm)
+ bl.writeToLoggers(bm.when, bm.msg, bm.level)
logMsgPool.Put(bm)
continue
}
@@ -653,12 +547,6 @@ func GetLogger(prefixes ...string) *log.Logger {
return l
}
-// EnableFullFilePath enables full file path logging. Disabled by default
-// e.g "/home/Documents/GitHub/beego/mainapp/" instead of "mainapp"
-func EnableFullFilePath(b bool) {
- beeLogger.enableFullFilePath = b
-}
-
// Reset will remove all the adapter
func Reset() {
beeLogger.Reset()
@@ -687,7 +575,7 @@ func EnableFuncCallDepth(b bool) {
// SetLogFuncCall set the CallDepth, default is 4
func SetLogFuncCall(b bool) {
beeLogger.EnableFuncCallDepth(b)
- beeLogger.SetLogFuncCallDepth(3)
+ beeLogger.SetLogFuncCallDepth(4)
}
// SetLogFuncCallDepth set log funcCallDepth
@@ -765,9 +653,9 @@ func formatLog(f interface{}, v ...interface{}) string {
return msg
}
if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
- // format string
+ //format string
} else {
- // do not contain format char
+ //do not contain format char
msg += strings.Repeat(" %v", len(v))
}
default:
diff --git a/core/logs/logger.go b/logs/logger.go
similarity index 96%
rename from core/logs/logger.go
rename to logs/logger.go
index d8b334d4..c7cf8a56 100644
--- a/core/logs/logger.go
+++ b/logs/logger.go
@@ -30,12 +30,11 @@ func newLogWriter(wr io.Writer) *logWriter {
return &logWriter{writer: wr}
}
-func (lg *logWriter) writeln(msg string) (int, error) {
+func (lg *logWriter) writeln(when time.Time, msg string) {
lg.Lock()
- msg += "\n"
- n, err := lg.writer.Write([]byte(msg))
+ h, _, _ := formatTimeHeader(when)
+ lg.writer.Write(append(append(h, msg...), '\n'))
lg.Unlock()
- return n, err
}
const (
diff --git a/core/logs/logger_test.go b/logs/logger_test.go
similarity index 100%
rename from core/logs/logger_test.go
rename to logs/logger_test.go
diff --git a/core/logs/multifile.go b/logs/multifile.go
similarity index 83%
rename from core/logs/multifile.go
rename to logs/multifile.go
index 79178211..90168274 100644
--- a/core/logs/multifile.go
+++ b/logs/multifile.go
@@ -16,6 +16,7 @@ package logs
import (
"encoding/json"
+ "time"
)
// A filesLogWriter manages several fileLogWriter
@@ -45,7 +46,6 @@ var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning
// }
func (f *multiFileLogWriter) Init(config string) error {
-
writer := newFileWriter().(*fileLogWriter)
err := writer.Init(config)
if err != nil {
@@ -54,17 +54,11 @@ func (f *multiFileLogWriter) Init(config string) error {
f.fullLogWriter = writer
f.writers[LevelDebug+1] = writer
- // unmarshal "separate" field to f.Separate
- err = json.Unmarshal([]byte(config), f)
- if err != nil {
- return err
- }
+ //unmarshal "separate" field to f.Separate
+ json.Unmarshal([]byte(config), f)
jsonMap := map[string]interface{}{}
- err = json.Unmarshal([]byte(config), &jsonMap)
- if err != nil {
- return err
- }
+ json.Unmarshal([]byte(config), &jsonMap)
for i := LevelEmergency; i < LevelDebug+1; i++ {
for _, v := range f.Separate {
@@ -81,17 +75,10 @@ func (f *multiFileLogWriter) Init(config string) error {
}
}
}
+
return nil
}
-func (f *multiFileLogWriter) Format(lm *LogMsg) string {
- return lm.OldStyleFormat()
-}
-
-func (f *multiFileLogWriter) SetFormatter(fmt LogFormatter) {
- f.fullLogWriter.SetFormatter(f)
-}
-
func (f *multiFileLogWriter) Destroy() {
for i := 0; i < len(f.writers); i++ {
if f.writers[i] != nil {
@@ -100,14 +87,14 @@ func (f *multiFileLogWriter) Destroy() {
}
}
-func (f *multiFileLogWriter) WriteMsg(lm *LogMsg) error {
+func (f *multiFileLogWriter) WriteMsg(when time.Time, msg string, level int) error {
if f.fullLogWriter != nil {
- f.fullLogWriter.WriteMsg(lm)
+ f.fullLogWriter.WriteMsg(when, msg, level)
}
for i := 0; i < len(f.writers)-1; i++ {
if f.writers[i] != nil {
- if lm.Level == f.writers[i].Level {
- f.writers[i].WriteMsg(lm)
+ if level == f.writers[i].Level {
+ f.writers[i].WriteMsg(when, msg, level)
}
}
}
@@ -124,8 +111,7 @@ func (f *multiFileLogWriter) Flush() {
// newFilesWriter create a FileLogWriter returning as LoggerInterface.
func newFilesWriter() Logger {
- res := &multiFileLogWriter{}
- return res
+ return &multiFileLogWriter{}
}
func init() {
diff --git a/core/logs/multifile_test.go b/logs/multifile_test.go
similarity index 100%
rename from core/logs/multifile_test.go
rename to logs/multifile_test.go
diff --git a/logs/slack.go b/logs/slack.go
new file mode 100644
index 00000000..1cd2e5ae
--- /dev/null
+++ b/logs/slack.go
@@ -0,0 +1,60 @@
+package logs
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "time"
+)
+
+// SLACKWriter implements beego LoggerInterface and is used to send jiaoliao webhook
+type SLACKWriter struct {
+ WebhookURL string `json:"webhookurl"`
+ Level int `json:"level"`
+}
+
+// newSLACKWriter create jiaoliao writer.
+func newSLACKWriter() Logger {
+ return &SLACKWriter{Level: LevelTrace}
+}
+
+// Init SLACKWriter with json config string
+func (s *SLACKWriter) Init(jsonconfig string) error {
+ return json.Unmarshal([]byte(jsonconfig), s)
+}
+
+// WriteMsg write message in smtp writer.
+// it will send an email with subject and only this message.
+func (s *SLACKWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > s.Level {
+ return nil
+ }
+
+ text := fmt.Sprintf("{\"text\": \"%s %s\"}", when.Format("2006-01-02 15:04:05"), msg)
+
+ form := url.Values{}
+ form.Add("payload", text)
+
+ resp, err := http.PostForm(s.WebhookURL, form)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("Post webhook failed %s %d", resp.Status, resp.StatusCode)
+ }
+ return nil
+}
+
+// Flush implementing method. empty.
+func (s *SLACKWriter) Flush() {
+}
+
+// Destroy implementing method. empty.
+func (s *SLACKWriter) Destroy() {
+}
+
+func init() {
+ Register(AdapterSlack, newSLACKWriter)
+}
diff --git a/core/logs/smtp.go b/logs/smtp.go
similarity index 77%
rename from core/logs/smtp.go
rename to logs/smtp.go
index 40891a7c..6208d7b8 100644
--- a/core/logs/smtp.go
+++ b/logs/smtp.go
@@ -21,8 +21,7 @@ import (
"net"
"net/smtp"
"strings"
-
- "github.com/pkg/errors"
+ "time"
)
// SMTPWriter implements LoggerInterface and is used to send emails via given SMTP-server.
@@ -34,15 +33,11 @@ type SMTPWriter struct {
FromAddress string `json:"fromAddress"`
RecipientAddresses []string `json:"sendTos"`
Level int `json:"level"`
- formatter LogFormatter
- Formatter string `json:"formatter"`
}
-// NewSMTPWriter creates the smtp writer.
+// NewSMTPWriter create smtp writer.
func newSMTPWriter() Logger {
- res := &SMTPWriter{Level: LevelTrace}
- res.formatter = res
- return res
+ return &SMTPWriter{Level: LevelTrace}
}
// Init smtp writer with json config.
@@ -56,16 +51,8 @@ func newSMTPWriter() Logger {
// "sendTos":["email1","email2"],
// "level":LevelError
// }
-func (s *SMTPWriter) Init(config string) error {
- res := json.Unmarshal([]byte(config), s)
- if res == nil && len(s.Formatter) > 0 {
- fmtr, ok := GetFormatter(s.Formatter)
- if !ok {
- return errors.New(fmt.Sprintf("the formatter with name: %s not found", s.Formatter))
- }
- s.formatter = fmtr
- }
- return res
+func (s *SMTPWriter) Init(jsonconfig string) error {
+ return json.Unmarshal([]byte(jsonconfig), s)
}
func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth {
@@ -80,10 +67,6 @@ func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth {
)
}
-func (s *SMTPWriter) SetFormatter(f LogFormatter) {
- s.formatter = f
-}
-
func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAddress string, recipients []string, msgContent []byte) error {
client, err := smtp.Dial(hostAddressWithPort)
if err != nil {
@@ -132,14 +115,10 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
return client.Quit()
}
-func (s *SMTPWriter) Format(lm *LogMsg) string {
- return lm.OldStyleFormat()
-}
-
-// WriteMsg writes message in smtp writer.
-// Sends an email with subject and only this message.
-func (s *SMTPWriter) WriteMsg(lm *LogMsg) error {
- if lm.Level > s.Level {
+// WriteMsg write message in smtp writer.
+// it will send an email with subject and only this message.
+func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error {
+ if level > s.Level {
return nil
}
@@ -148,13 +127,11 @@ func (s *SMTPWriter) WriteMsg(lm *LogMsg) error {
// Set up authentication information.
auth := s.getSMTPAuth(hp[0])
- msg := s.Format(lm)
-
// Connect to the server, authenticate, set the sender and recipient,
// and send the email all in one step.
contentType := "Content-Type: text/plain" + "; charset=UTF-8"
mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress +
- ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", lm.When.Format("2006-01-02 15:04:05")) + msg)
+ ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", when.Format("2006-01-02 15:04:05")) + msg)
return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg)
}
diff --git a/core/logs/smtp_test.go b/logs/smtp_test.go
similarity index 100%
rename from core/logs/smtp_test.go
rename to logs/smtp_test.go
diff --git a/adapter/metric/prometheus.go b/metric/prometheus.go
similarity index 87%
rename from adapter/metric/prometheus.go
rename to metric/prometheus.go
index 4660f626..7722240b 100644
--- a/adapter/metric/prometheus.go
+++ b/metric/prometheus.go
@@ -24,8 +24,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/astaxie/beego"
- "github.com/astaxie/beego/core/logs"
- "github.com/astaxie/beego/server/web"
+ "github.com/astaxie/beego/logs"
)
func PrometheusMiddleWare(next http.Handler) http.Handler {
@@ -33,9 +32,9 @@ func PrometheusMiddleWare(next http.Handler) http.Handler {
Name: "beego",
Subsystem: "http_request",
ConstLabels: map[string]string{
- "server": web.BConfig.ServerName,
- "env": web.BConfig.RunMode,
- "appname": web.BConfig.AppName,
+ "server": beego.BConfig.ServerName,
+ "env": beego.BConfig.RunMode,
+ "appname": beego.BConfig.AppName,
},
Help: "The statics info for http request",
}, []string{"pattern", "method", "status", "duration"})
@@ -58,15 +57,15 @@ func registerBuildInfo() {
Subsystem: "build_info",
Help: "The building information",
ConstLabels: map[string]string{
- "appname": web.BConfig.AppName,
+ "appname": beego.BConfig.AppName,
"build_version": beego.BuildVersion,
"build_revision": beego.BuildGitRevision,
"build_status": beego.BuildStatus,
"build_tag": beego.BuildTag,
- "build_time": strings.Replace(beego.BuildTime, "--", " ", 1),
+ "build_time": strings.Replace(beego.BuildTime, "--", " ", 1),
"go_version": beego.GoVersion,
"git_branch": beego.GitBranch,
- "start_time": time.Now().Format("2006-01-02 15:04:05"),
+ "start_time": time.Now().Format("2006-01-02 15:04:05"),
},
}, []string{})
@@ -75,7 +74,7 @@ func registerBuildInfo() {
}
func report(dur time.Duration, writer http.ResponseWriter, q *http.Request, vec *prometheus.SummaryVec) {
- ctrl := web.BeeApp.Handlers
+ ctrl := beego.BeeApp.Handlers
ctx := ctrl.GetContext()
ctx.Reset(writer, q)
defer ctrl.GiveBackContext(ctx)
diff --git a/adapter/metric/prometheus_test.go b/metric/prometheus_test.go
similarity index 96%
rename from adapter/metric/prometheus_test.go
rename to metric/prometheus_test.go
index 751348bf..d82a6dec 100644
--- a/adapter/metric/prometheus_test.go
+++ b/metric/prometheus_test.go
@@ -22,7 +22,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
- "github.com/astaxie/beego/adapter/context"
+ "github.com/astaxie/beego/context"
)
func TestPrometheusMiddleWare(t *testing.T) {
diff --git a/client/orm/migration/ddl.go b/migration/ddl.go
similarity index 85%
rename from client/orm/migration/ddl.go
rename to migration/ddl.go
index a396d39a..cd2c1c49 100644
--- a/client/orm/migration/ddl.go
+++ b/migration/ddl.go
@@ -17,7 +17,7 @@ package migration
import (
"fmt"
- "github.com/astaxie/beego/core/logs"
+ "github.com/astaxie/beego/logs"
)
// Index struct defines the structure of Index Columns
@@ -31,7 +31,7 @@ type Unique struct {
Columns []*Column
}
-// Column struct defines a single column of a table
+//Column struct defines a single column of a table
type Column struct {
Name string
Inc string
@@ -84,7 +84,7 @@ func (m *Migration) NewCol(name string) *Column {
return col
}
-// PriCol creates a new primary column and attaches it to m struct
+//PriCol creates a new primary column and attaches it to m struct
func (m *Migration) PriCol(name string) *Column {
col := &Column{Name: name}
m.AddColumns(col)
@@ -92,7 +92,7 @@ func (m *Migration) PriCol(name string) *Column {
return col
}
-// UniCol creates / appends columns to specified unique key and attaches it to m struct
+//UniCol creates / appends columns to specified unique key and attaches it to m struct
func (m *Migration) UniCol(uni, name string) *Column {
col := &Column{Name: name}
m.AddColumns(col)
@@ -114,7 +114,7 @@ func (m *Migration) UniCol(uni, name string) *Column {
return col
}
-// ForeignCol creates a new foreign column and returns the instance of column
+//ForeignCol creates a new foreign column and returns the instance of column
func (m *Migration) ForeignCol(colname, foreigncol, foreigntable string) (foreign *Foreign) {
foreign = &Foreign{ForeignColumn: foreigncol, ForeignTable: foreigntable}
@@ -123,25 +123,25 @@ func (m *Migration) ForeignCol(colname, foreigncol, foreigntable string) (foreig
return foreign
}
-// SetOnDelete sets the on delete of foreign
+//SetOnDelete sets the on delete of foreign
func (foreign *Foreign) SetOnDelete(del string) *Foreign {
foreign.OnDelete = "ON DELETE" + del
return foreign
}
-// SetOnUpdate sets the on update of foreign
+//SetOnUpdate sets the on update of foreign
func (foreign *Foreign) SetOnUpdate(update string) *Foreign {
foreign.OnUpdate = "ON UPDATE" + update
return foreign
}
-// Remove marks the columns to be removed.
-// it allows reverse m to create the column.
+//Remove marks the columns to be removed.
+//it allows reverse m to create the column.
func (c *Column) Remove() {
c.remove = true
}
-// SetAuto enables auto_increment of column (can be used once)
+//SetAuto enables auto_increment of column (can be used once)
func (c *Column) SetAuto(inc bool) *Column {
if inc {
c.Inc = "auto_increment"
@@ -149,7 +149,7 @@ func (c *Column) SetAuto(inc bool) *Column {
return c
}
-// SetNullable sets the column to be null
+//SetNullable sets the column to be null
func (c *Column) SetNullable(null bool) *Column {
if null {
c.Null = ""
@@ -160,13 +160,13 @@ func (c *Column) SetNullable(null bool) *Column {
return c
}
-// SetDefault sets the default value, prepend with "DEFAULT "
+//SetDefault sets the default value, prepend with "DEFAULT "
func (c *Column) SetDefault(def string) *Column {
c.Default = "DEFAULT " + def
return c
}
-// SetUnsigned sets the column to be unsigned int
+//SetUnsigned sets the column to be unsigned int
func (c *Column) SetUnsigned(unsign bool) *Column {
if unsign {
c.Unsign = "UNSIGNED"
@@ -174,13 +174,13 @@ func (c *Column) SetUnsigned(unsign bool) *Column {
return c
}
-// SetDataType sets the dataType of the column
+//SetDataType sets the dataType of the column
func (c *Column) SetDataType(dataType string) *Column {
c.DataType = dataType
return c
}
-// SetOldNullable allows reverting to previous nullable on reverse ms
+//SetOldNullable allows reverting to previous nullable on reverse ms
func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn {
if null {
c.OldNull = ""
@@ -191,13 +191,13 @@ func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn {
return c
}
-// SetOldDefault allows reverting to previous default on reverse ms
+//SetOldDefault allows reverting to previous default on reverse ms
func (c *RenameColumn) SetOldDefault(def string) *RenameColumn {
c.OldDefault = def
return c
}
-// SetOldUnsigned allows reverting to previous unsgined on reverse ms
+//SetOldUnsigned allows reverting to previous unsgined on reverse ms
func (c *RenameColumn) SetOldUnsigned(unsign bool) *RenameColumn {
if unsign {
c.OldUnsign = "UNSIGNED"
@@ -205,19 +205,19 @@ func (c *RenameColumn) SetOldUnsigned(unsign bool) *RenameColumn {
return c
}
-// SetOldDataType allows reverting to previous datatype on reverse ms
+//SetOldDataType allows reverting to previous datatype on reverse ms
func (c *RenameColumn) SetOldDataType(dataType string) *RenameColumn {
c.OldDataType = dataType
return c
}
-// SetPrimary adds the columns to the primary key (can only be used any number of times in only one m)
+//SetPrimary adds the columns to the primary key (can only be used any number of times in only one m)
func (c *Column) SetPrimary(m *Migration) *Column {
m.Primary = append(m.Primary, c)
return c
}
-// AddColumnsToUnique adds the columns to Unique Struct
+//AddColumnsToUnique adds the columns to Unique Struct
func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique {
unique.Columns = append(unique.Columns, columns...)
@@ -225,7 +225,7 @@ func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique {
return unique
}
-// AddColumns adds columns to m struct
+//AddColumns adds columns to m struct
func (m *Migration) AddColumns(columns ...*Column) *Migration {
m.Columns = append(m.Columns, columns...)
@@ -233,38 +233,38 @@ func (m *Migration) AddColumns(columns ...*Column) *Migration {
return m
}
-// AddPrimary adds the column to primary in m struct
+//AddPrimary adds the column to primary in m struct
func (m *Migration) AddPrimary(primary *Column) *Migration {
m.Primary = append(m.Primary, primary)
return m
}
-// AddUnique adds the column to unique in m struct
+//AddUnique adds the column to unique in m struct
func (m *Migration) AddUnique(unique *Unique) *Migration {
m.Uniques = append(m.Uniques, unique)
return m
}
-// AddForeign adds the column to foreign in m struct
+//AddForeign adds the column to foreign in m struct
func (m *Migration) AddForeign(foreign *Foreign) *Migration {
m.Foreigns = append(m.Foreigns, foreign)
return m
}
-// AddIndex adds the column to index in m struct
+//AddIndex adds the column to index in m struct
func (m *Migration) AddIndex(index *Index) *Migration {
m.Indexes = append(m.Indexes, index)
return m
}
-// RenameColumn allows renaming of columns
+//RenameColumn allows renaming of columns
func (m *Migration) RenameColumn(from, to string) *RenameColumn {
rename := &RenameColumn{OldName: from, NewName: to}
m.Renames = append(m.Renames, rename)
return rename
}
-// GetSQL returns the generated sql depending on ModifyType
+//GetSQL returns the generated sql depending on ModifyType
func (m *Migration) GetSQL() (sql string) {
sql = ""
switch m.ModifyType {
diff --git a/adapter/migration/doc.go b/migration/doc.go
similarity index 100%
rename from adapter/migration/doc.go
rename to migration/doc.go
diff --git a/client/orm/migration/migration.go b/migration/migration.go
similarity index 99%
rename from client/orm/migration/migration.go
rename to migration/migration.go
index aeea12c6..5ddfd972 100644
--- a/client/orm/migration/migration.go
+++ b/migration/migration.go
@@ -33,8 +33,8 @@ import (
"strings"
"time"
- "github.com/astaxie/beego/client/orm"
- "github.com/astaxie/beego/core/logs"
+ "github.com/astaxie/beego/logs"
+ "github.com/astaxie/beego/orm"
)
// const the data format for the bee generate migration datatype
diff --git a/server/web/mime.go b/mime.go
similarity index 99%
rename from server/web/mime.go
rename to mime.go
index 9393e9c7..ca2878ab 100644
--- a/server/web/mime.go
+++ b/mime.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
var mimemaps = map[string]string{
".3dm": "x-world/x-3dmf",
diff --git a/server/web/namespace.go b/namespace.go
similarity index 98%
rename from server/web/namespace.go
rename to namespace.go
index 58afb6c7..4952c9d5 100644
--- a/server/web/namespace.go
+++ b/namespace.go
@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"net/http"
"strings"
- beecontext "github.com/astaxie/beego/server/web/context"
+ beecontext "github.com/astaxie/beego/context"
)
type namespaceCond func(*beecontext.Context) bool
@@ -91,7 +91,7 @@ func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace {
a = FinishRouter
}
for _, f := range filter {
- n.handlers.InsertFilter("*", a, f, WithReturnOnOutput(true))
+ n.handlers.InsertFilter("*", a, f)
}
return n
}
diff --git a/server/web/namespace_test.go b/namespace_test.go
similarity index 98%
rename from server/web/namespace_test.go
rename to namespace_test.go
index a6f87bba..b3f20dff 100644
--- a/server/web/namespace_test.go
+++ b/namespace_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"net/http"
@@ -20,7 +20,7 @@ import (
"strconv"
"testing"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
)
func TestNamespaceGet(t *testing.T) {
diff --git a/client/orm/README.md b/orm/README.md
similarity index 100%
rename from client/orm/README.md
rename to orm/README.md
diff --git a/client/orm/cmd.go b/orm/cmd.go
similarity index 85%
rename from client/orm/cmd.go
rename to orm/cmd.go
index b0661971..0ff4dc40 100644
--- a/client/orm/cmd.go
+++ b/orm/cmd.go
@@ -46,7 +46,7 @@ func printHelp(errs ...string) {
os.Exit(2)
}
-// RunCommand listens for orm command and runs if command arguments have been passed.
+// RunCommand listen for orm command and then run it if command arguments passed.
func RunCommand() {
if len(os.Args) < 2 || os.Args[1] != "orm" {
return
@@ -83,7 +83,7 @@ type commandSyncDb struct {
rtOnError bool
}
-// Parse the orm command line arguments.
+// parse orm command line arguments.
func (d *commandSyncDb) Parse(args []string) {
var name string
@@ -96,20 +96,16 @@ func (d *commandSyncDb) Parse(args []string) {
d.al = getDbAlias(name)
}
-// Run orm line command.
+// run orm line command.
func (d *commandSyncDb) Run() error {
var drops []string
- var err error
if d.force {
- drops, err = modelCache.getDbDropSQL(d.al)
- if err != nil {
- return err
- }
+ drops = getDbDropSQL(d.al)
}
db := d.al.DB
- if d.force && len(drops) > 0 {
+ if d.force {
for i, mi := range modelCache.allOrdered() {
query := drops[i]
if !d.noInfo {
@@ -128,10 +124,7 @@ func (d *commandSyncDb) Run() error {
}
}
- createQueries, indexes, err := modelCache.getDbCreateSQL(d.al)
- if err != nil {
- return err
- }
+ sqls, indexes := getDbCreateSQL(d.al)
tables, err := d.al.DbBaser.GetTables(db)
if err != nil {
@@ -142,12 +135,6 @@ func (d *commandSyncDb) Run() error {
}
for i, mi := range modelCache.allOrdered() {
-
- if !isApplicableTableForDB(mi.addrField, d.al.Name) {
- fmt.Printf("table `%s` is not applicable to database '%s'\n", mi.table, d.al.Name)
- continue
- }
-
if tables[mi.table] {
if !d.noInfo {
fmt.Printf("table `%s` already exists, skip\n", mi.table)
@@ -214,7 +201,7 @@ func (d *commandSyncDb) Run() error {
fmt.Printf("create table `%s` \n", mi.table)
}
- queries := []string{createQueries[i]}
+ queries := []string{sqls[i]}
for _, idx := range indexes[mi.table] {
queries = append(queries, idx.SQL)
}
@@ -245,7 +232,7 @@ type commandSQLAll struct {
al *alias
}
-// Parse orm command line arguments.
+// parse orm command line arguments.
func (d *commandSQLAll) Parse(args []string) {
var name string
@@ -256,15 +243,12 @@ func (d *commandSQLAll) Parse(args []string) {
d.al = getDbAlias(name)
}
-// Run orm line command.
+// run orm line command.
func (d *commandSQLAll) Run() error {
- createQueries, indexes, err := modelCache.getDbCreateSQL(d.al)
- if err != nil {
- return err
- }
+ sqls, indexes := getDbCreateSQL(d.al)
var all []string
for i, mi := range modelCache.allOrdered() {
- queries := []string{createQueries[i]}
+ queries := []string{sqls[i]}
for _, idx := range indexes[mi.table] {
queries = append(queries, idx.SQL)
}
@@ -282,9 +266,9 @@ func init() {
}
// RunSyncdb run syncdb command line.
-// name: Table's alias name (default is "default")
-// force: Run the next sql command even if the current gave an error
-// verbose: Print all information, useful for debugging
+// name means table's alias name. default is "default".
+// force means run next sql if the current is error.
+// verbose means show all info when running command or not.
func RunSyncdb(name string, force bool, verbose bool) error {
BootStrap()
diff --git a/orm/cmd_utils.go b/orm/cmd_utils.go
new file mode 100644
index 00000000..61f17346
--- /dev/null
+++ b/orm/cmd_utils.go
@@ -0,0 +1,320 @@
+// 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 orm
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+type dbIndex struct {
+ Table string
+ Name string
+ SQL string
+}
+
+// create database drop sql.
+func getDbDropSQL(al *alias) (sqls []string) {
+ if len(modelCache.cache) == 0 {
+ fmt.Println("no Model found, need register your model")
+ os.Exit(2)
+ }
+
+ Q := al.DbBaser.TableQuote()
+
+ for _, mi := range modelCache.allOrdered() {
+ sqls = append(sqls, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.table, Q))
+ }
+ return sqls
+}
+
+// get database column type string.
+func getColumnTyp(al *alias, fi *fieldInfo) (col string) {
+ T := al.DbBaser.DbTypes()
+ fieldType := fi.fieldType
+ fieldSize := fi.size
+
+checkColumn:
+ switch fieldType {
+ case TypeBooleanField:
+ col = T["bool"]
+ case TypeVarCharField:
+ if al.Driver == DRPostgres && fi.toText {
+ col = T["string-text"]
+ } else {
+ col = fmt.Sprintf(T["string"], fieldSize)
+ }
+ case TypeCharField:
+ col = fmt.Sprintf(T["string-char"], fieldSize)
+ case TypeTextField:
+ col = T["string-text"]
+ case TypeTimeField:
+ col = T["time.Time-clock"]
+ case TypeDateField:
+ col = T["time.Time-date"]
+ case TypeDateTimeField:
+ col = T["time.Time"]
+ case TypeBitField:
+ col = T["int8"]
+ case TypeSmallIntegerField:
+ col = T["int16"]
+ case TypeIntegerField:
+ col = T["int32"]
+ case TypeBigIntegerField:
+ if al.Driver == DRSqlite {
+ fieldType = TypeIntegerField
+ goto checkColumn
+ }
+ col = T["int64"]
+ case TypePositiveBitField:
+ col = T["uint8"]
+ case TypePositiveSmallIntegerField:
+ col = T["uint16"]
+ case TypePositiveIntegerField:
+ col = T["uint32"]
+ case TypePositiveBigIntegerField:
+ col = T["uint64"]
+ case TypeFloatField:
+ col = T["float64"]
+ case TypeDecimalField:
+ s := T["float64-decimal"]
+ if !strings.Contains(s, "%d") {
+ col = s
+ } else {
+ col = fmt.Sprintf(s, fi.digits, fi.decimals)
+ }
+ case TypeJSONField:
+ if al.Driver != DRPostgres {
+ fieldType = TypeVarCharField
+ goto checkColumn
+ }
+ col = T["json"]
+ case TypeJsonbField:
+ if al.Driver != DRPostgres {
+ fieldType = TypeVarCharField
+ goto checkColumn
+ }
+ col = T["jsonb"]
+ case RelForeignKey, RelOneToOne:
+ fieldType = fi.relModelInfo.fields.pk.fieldType
+ fieldSize = fi.relModelInfo.fields.pk.size
+ goto checkColumn
+ }
+
+ return
+}
+
+// create alter sql string.
+func getColumnAddQuery(al *alias, fi *fieldInfo) string {
+ Q := al.DbBaser.TableQuote()
+ typ := getColumnTyp(al, fi)
+
+ if !fi.null {
+ typ += " " + "NOT NULL"
+ }
+
+ return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s %s",
+ Q, fi.mi.table, Q,
+ Q, fi.column, Q,
+ typ, getColumnDefault(fi),
+ )
+}
+
+// create database creation string.
+func getDbCreateSQL(al *alias) (sqls []string, tableIndexes map[string][]dbIndex) {
+ if len(modelCache.cache) == 0 {
+ fmt.Println("no Model found, need register your model")
+ os.Exit(2)
+ }
+
+ Q := al.DbBaser.TableQuote()
+ T := al.DbBaser.DbTypes()
+ sep := fmt.Sprintf("%s, %s", Q, Q)
+
+ tableIndexes = make(map[string][]dbIndex)
+
+ for _, mi := range modelCache.allOrdered() {
+ sql := fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
+ sql += fmt.Sprintf("-- Table Structure for `%s`\n", mi.fullName)
+ sql += fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
+
+ sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.table, Q)
+
+ columns := make([]string, 0, len(mi.fields.fieldsDB))
+
+ sqlIndexes := [][]string{}
+
+ for _, fi := range mi.fields.fieldsDB {
+
+ column := fmt.Sprintf(" %s%s%s ", Q, fi.column, Q)
+ col := getColumnTyp(al, fi)
+
+ if fi.auto {
+ switch al.Driver {
+ case DRSqlite, DRPostgres:
+ column += T["auto"]
+ default:
+ column += col + " " + T["auto"]
+ }
+ } else if fi.pk {
+ column += col + " " + T["pk"]
+ } else {
+ column += col
+
+ if !fi.null {
+ column += " " + "NOT NULL"
+ }
+
+ //if fi.initial.String() != "" {
+ // column += " DEFAULT " + fi.initial.String()
+ //}
+
+ // Append attribute DEFAULT
+ column += getColumnDefault(fi)
+
+ if fi.unique {
+ column += " " + "UNIQUE"
+ }
+
+ if fi.index {
+ sqlIndexes = append(sqlIndexes, []string{fi.column})
+ }
+ }
+
+ if strings.Contains(column, "%COL%") {
+ column = strings.Replace(column, "%COL%", fi.column, -1)
+ }
+
+ if fi.description != "" && al.Driver!=DRSqlite {
+ column += " " + fmt.Sprintf("COMMENT '%s'",fi.description)
+ }
+
+ columns = append(columns, column)
+ }
+
+ if mi.model != nil {
+ allnames := getTableUnique(mi.addrField)
+ if !mi.manual && len(mi.uniques) > 0 {
+ allnames = append(allnames, mi.uniques)
+ }
+ for _, names := range allnames {
+ cols := make([]string, 0, len(names))
+ for _, name := range names {
+ if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
+ cols = append(cols, fi.column)
+ } else {
+ panic(fmt.Errorf("cannot found column `%s` when parse UNIQUE in `%s.TableUnique`", name, mi.fullName))
+ }
+ }
+ column := fmt.Sprintf(" UNIQUE (%s%s%s)", Q, strings.Join(cols, sep), Q)
+ columns = append(columns, column)
+ }
+ }
+
+ sql += strings.Join(columns, ",\n")
+ sql += "\n)"
+
+ if al.Driver == DRMySQL {
+ var engine string
+ if mi.model != nil {
+ engine = getTableEngine(mi.addrField)
+ }
+ if engine == "" {
+ engine = al.Engine
+ }
+ sql += " ENGINE=" + engine
+ }
+
+ sql += ";"
+ sqls = append(sqls, sql)
+
+ if mi.model != nil {
+ for _, names := range getTableIndex(mi.addrField) {
+ cols := make([]string, 0, len(names))
+ for _, name := range names {
+ if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
+ cols = append(cols, fi.column)
+ } else {
+ panic(fmt.Errorf("cannot found column `%s` when parse INDEX in `%s.TableIndex`", name, mi.fullName))
+ }
+ }
+ sqlIndexes = append(sqlIndexes, cols)
+ }
+ }
+
+ for _, names := range sqlIndexes {
+ name := mi.table + "_" + strings.Join(names, "_")
+ cols := strings.Join(names, sep)
+ sql := fmt.Sprintf("CREATE INDEX %s%s%s ON %s%s%s (%s%s%s);", Q, name, Q, Q, mi.table, Q, Q, cols, Q)
+
+ index := dbIndex{}
+ index.Table = mi.table
+ index.Name = name
+ index.SQL = sql
+
+ tableIndexes[mi.table] = append(tableIndexes[mi.table], index)
+ }
+
+ }
+
+ return
+}
+
+// Get string value for the attribute "DEFAULT" for the CREATE, ALTER commands
+func getColumnDefault(fi *fieldInfo) string {
+ var (
+ v, t, d string
+ )
+
+ // Skip default attribute if field is in relations
+ if fi.rel || fi.reverse {
+ return v
+ }
+
+ t = " DEFAULT '%s' "
+
+ // These defaults will be useful if there no config value orm:"default" and NOT NULL is on
+ switch fi.fieldType {
+ case TypeTimeField, TypeDateField, TypeDateTimeField, TypeTextField:
+ return v
+
+ case TypeBitField, TypeSmallIntegerField, TypeIntegerField,
+ TypeBigIntegerField, TypePositiveBitField, TypePositiveSmallIntegerField,
+ TypePositiveIntegerField, TypePositiveBigIntegerField, TypeFloatField,
+ TypeDecimalField:
+ t = " DEFAULT %s "
+ d = "0"
+ case TypeBooleanField:
+ t = " DEFAULT %s "
+ d = "FALSE"
+ case TypeJSONField, TypeJsonbField:
+ d = "{}"
+ }
+
+ if fi.colDefault {
+ if !fi.initial.Exist() {
+ v = fmt.Sprintf(t, "")
+ } else {
+ v = fmt.Sprintf(t, fi.initial.String())
+ }
+ } else {
+ if !fi.null {
+ v = fmt.Sprintf(t, d)
+ }
+ }
+
+ return v
+}
diff --git a/client/orm/db.go b/orm/db.go
similarity index 94%
rename from client/orm/db.go
rename to orm/db.go
index b103d218..9a1827e8 100644
--- a/client/orm/db.go
+++ b/orm/db.go
@@ -21,8 +21,6 @@ import (
"reflect"
"strings"
"time"
-
- "github.com/astaxie/beego/client/orm/hints"
)
const (
@@ -38,11 +36,10 @@ var (
var (
operators = map[string]bool{
- "exact": true,
- "iexact": true,
- "strictexact": true,
- "contains": true,
- "icontains": true,
+ "exact": true,
+ "iexact": true,
+ "contains": true,
+ "icontains": true,
// "regex": true,
// "iregex": true,
"gt": true,
@@ -487,14 +484,7 @@ func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []s
if isMulti {
return res.RowsAffected()
}
-
- lastInsertId, err := res.LastInsertId()
- if err != nil {
- DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
- return lastInsertId, ErrLastInsertIdUnavailable
- } else {
- return lastInsertId, nil
- }
+ return res.LastInsertId()
}
return 0, err
}
@@ -595,14 +585,7 @@ func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a
if isMulti {
return res.RowsAffected()
}
-
- lastInsertId, err := res.LastInsertId()
- if err != nil {
- DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
- return lastInsertId, ErrLastInsertIdUnavailable
- } else {
- return lastInsertId, nil
- }
+ return res.LastInsertId()
}
return 0, err
}
@@ -755,10 +738,8 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
}
tables := newDbTables(mi, d.ins)
- var specifyIndexes string
if qs != nil {
tables.parseRelated(qs.related, qs.relDepth)
- specifyIndexes = tables.getIndexSql(mi.table, qs.useIndex, qs.indexes)
}
where, args := tables.getCondSQL(cond, false, tz)
@@ -809,12 +790,9 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
sets := strings.Join(cols, ", ") + " "
if d.ins.SupportUpdateJoin() {
- query = fmt.Sprintf("UPDATE %s%s%s T0 %s%sSET %s%s", Q, mi.table, Q, specifyIndexes, join, sets, where)
+ query = fmt.Sprintf("UPDATE %s%s%s T0 %sSET %s%s", Q, mi.table, Q, join, sets, where)
} else {
- supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s%s",
- Q, mi.fields.pk.column, Q,
- Q, mi.table, Q,
- specifyIndexes, join, where)
+ supQuery := fmt.Sprintf("SELECT T0.%s%s%s FROM %s%s%s T0 %s%s", Q, mi.fields.pk.column, Q, Q, mi.table, Q, join, where)
query = fmt.Sprintf("UPDATE %s%s%s SET %sWHERE %s%s%s IN ( %s )", Q, mi.table, Q, sets, Q, mi.fields.pk.column, Q, supQuery)
}
@@ -865,10 +843,8 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
tables := newDbTables(mi, d.ins)
tables.skipEnd = true
- var specifyIndexes string
if qs != nil {
tables.parseRelated(qs.related, qs.relDepth)
- specifyIndexes = tables.getIndexSql(mi.table, qs.useIndex, qs.indexes)
}
if cond == nil || cond.IsEmpty() {
@@ -881,7 +857,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
join := tables.getJoinSQL()
cols := fmt.Sprintf("T0.%s%s%s", Q, mi.fields.pk.column, Q)
- query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s", cols, Q, mi.table, Q, specifyIndexes, join, where)
+ query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s", cols, Q, mi.table, Q, join, where)
d.ins.ReplaceMarks(&query)
@@ -1026,7 +1002,6 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
orderBy := tables.getOrderSQL(qs.orders)
limit := tables.getLimitSQL(mi, offset, rlimit)
join := tables.getJoinSQL()
- specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes)
for _, tbl := range tables.tables {
if tbl.sel {
@@ -1040,11 +1015,9 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
if qs.distinct {
sqlSelect += " DISTINCT"
}
- query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s%s",
- sqlSelect, sels, Q, mi.table, Q,
- specifyIndexes, join, where, groupBy, orderBy, limit)
+ query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s", sqlSelect, sels, Q, mi.table, Q, join, where, groupBy, orderBy, limit)
- if qs.forUpdate {
+ if qs.forupdate {
query += " FOR UPDATE"
}
@@ -1180,13 +1153,10 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition
groupBy := tables.getGroupSQL(qs.groups)
tables.getOrderSQL(qs.orders)
join := tables.getJoinSQL()
- specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes)
Q := d.ins.TableQuote()
- query := fmt.Sprintf("SELECT COUNT(*) FROM %s%s%s T0 %s%s%s%s",
- Q, mi.table, Q,
- specifyIndexes, join, where, groupBy)
+ query := fmt.Sprintf("SELECT COUNT(*) FROM %s%s%s T0 %s%s%s", Q, mi.table, Q, join, where, groupBy)
if groupBy != "" {
query = fmt.Sprintf("SELECT COUNT(*) FROM (%s) AS T", query)
@@ -1356,14 +1326,7 @@ setValue:
t time.Time
err error
)
-
- if fi.timePrecision != nil && len(s) >= (20+*fi.timePrecision) {
- layout := formatDateTime + "."
- for i := 0; i < *fi.timePrecision; i++ {
- layout += "0"
- }
- t, err = time.ParseInLocation(layout, s[:20+*fi.timePrecision], tz)
- } else if len(s) >= 19 {
+ if len(s) >= 19 {
s = s[:19]
t, err = time.ParseInLocation(formatDateTime, s, tz)
} else if len(s) >= 10 {
@@ -1717,7 +1680,6 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
orderBy := tables.getOrderSQL(qs.orders)
limit := tables.getLimitSQL(mi, qs.offset, qs.limit)
join := tables.getJoinSQL()
- specifyIndexes := tables.getIndexSql(mi.table, qs.useIndex, qs.indexes)
sels := strings.Join(cols, ", ")
@@ -1725,10 +1687,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
if qs.distinct {
sqlSelect += " DISTINCT"
}
- query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s%s",
- sqlSelect, sels,
- Q, mi.table, Q,
- specifyIndexes, join, where, groupBy, orderBy, limit)
+ query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s", sqlSelect, sels, Q, mi.table, Q, join, where, groupBy, orderBy, limit)
d.ins.ReplaceMarks(&query)
@@ -1822,6 +1781,10 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
return cnt, nil
}
+func (d *dbBase) RowsTo(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, string, string, *time.Location) (int64, error) {
+ return 0, nil
+}
+
// flag of update joined record.
func (d *dbBase) SupportUpdateJoin() bool {
return true
@@ -1937,29 +1900,3 @@ func (d *dbBase) ShowColumnsQuery(table string) string {
func (d *dbBase) IndexExists(dbQuerier, string, string) bool {
panic(ErrNotImplement)
}
-
-// GenerateSpecifyIndex return a specifying index clause
-func (d *dbBase) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string {
- var s []string
- Q := d.TableQuote()
- for _, index := range indexes {
- tmp := fmt.Sprintf(`%s%s%s`, Q, index, Q)
- s = append(s, tmp)
- }
-
- var useWay string
-
- switch useIndex {
- case hints.KeyUseIndex:
- useWay = `USE`
- case hints.KeyForceIndex:
- useWay = `FORCE`
- case hints.KeyIgnoreIndex:
- useWay = `IGNORE`
- default:
- DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored")
- return ``
- }
-
- return fmt.Sprintf(` %s INDEX(%s) `, useWay, strings.Join(s, `,`))
-}
diff --git a/client/orm/db_alias.go b/orm/db_alias.go
similarity index 62%
rename from client/orm/db_alias.go
rename to orm/db_alias.go
index 29e0904c..cf6a5935 100644
--- a/client/orm/db_alias.go
+++ b/orm/db_alias.go
@@ -18,10 +18,10 @@ import (
"context"
"database/sql"
"fmt"
+ lru "github.com/hashicorp/golang-lru"
+ "reflect"
"sync"
"time"
-
- lru "github.com/hashicorp/golang-lru"
)
// DriverType database driver constant int.
@@ -63,7 +63,7 @@ var (
"tidb": DRTiDB,
"oracle": DROracle,
"oci8": DROracle, // github.com/mattn/go-oci8
- "ora": DROracle, // https://github.com/rana/ora
+ "ora": DROracle, //https://github.com/rana/ora
}
dbBasers = map[DriverType]dbBaser{
DRMySQL: newdbBaseMysql(),
@@ -107,14 +107,10 @@ func (ac *_dbCache) getDefault() (al *alias) {
type DB struct {
*sync.RWMutex
- DB *sql.DB
- stmtDecorators *lru.Cache
- stmtDecoratorsLimit int
+ DB *sql.DB
+ stmtDecorators *lru.Cache
}
-var _ dbQuerier = new(DB)
-var _ txer = new(DB)
-
func (d *DB) Begin() (*sql.Tx, error) {
return d.DB.Begin()
}
@@ -123,7 +119,7 @@ func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
return d.DB.BeginTx(ctx, opts)
}
-// su must call release to release *sql.Stmt after using
+//su must call release to release *sql.Stmt after using
func (d *DB) getStmtDecorator(query string) (*stmtDecorator, error) {
d.RLock()
c, ok := d.stmtDecorators.Get(query)
@@ -164,14 +160,16 @@ func (d *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error
}
func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) {
- return d.ExecContext(context.Background(), query, args...)
+ sd, err := d.getStmtDecorator(query)
+ if err != nil {
+ return nil, err
+ }
+ stmt := sd.getStmt()
+ defer sd.release()
+ return stmt.Exec(args...)
}
func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
- if d.stmtDecorators == nil {
- return d.DB.ExecContext(ctx, query, args...)
- }
-
sd, err := d.getStmtDecorator(query)
if err != nil {
return nil, err
@@ -182,14 +180,16 @@ func (d *DB) ExecContext(ctx context.Context, query string, args ...interface{})
}
func (d *DB) Query(query string, args ...interface{}) (*sql.Rows, error) {
- return d.QueryContext(context.Background(), query, args...)
+ sd, err := d.getStmtDecorator(query)
+ if err != nil {
+ return nil, err
+ }
+ stmt := sd.getStmt()
+ defer sd.release()
+ return stmt.Query(args...)
}
func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
- if d.stmtDecorators == nil {
- return d.DB.QueryContext(ctx, query, args...)
- }
-
sd, err := d.getStmtDecorator(query)
if err != nil {
return nil, err
@@ -200,86 +200,37 @@ func (d *DB) QueryContext(ctx context.Context, query string, args ...interface{}
}
func (d *DB) QueryRow(query string, args ...interface{}) *sql.Row {
- return d.QueryRowContext(context.Background(), query, args...)
-}
-
-func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
- if d.stmtDecorators == nil {
- return d.DB.QueryRowContext(ctx, query, args...)
- }
-
sd, err := d.getStmtDecorator(query)
if err != nil {
panic(err)
}
stmt := sd.getStmt()
defer sd.release()
- return stmt.QueryRowContext(ctx, args...)
+ return stmt.QueryRow(args...)
+
}
-type TxDB struct {
- tx *sql.Tx
-}
-
-var _ dbQuerier = new(TxDB)
-var _ txEnder = new(TxDB)
-
-func (t *TxDB) Commit() error {
- return t.tx.Commit()
-}
-
-func (t *TxDB) Rollback() error {
- return t.tx.Rollback()
-}
-
-var _ dbQuerier = new(TxDB)
-var _ txEnder = new(TxDB)
-
-func (t *TxDB) Prepare(query string) (*sql.Stmt, error) {
- return t.PrepareContext(context.Background(), query)
-}
-
-func (t *TxDB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) {
- return t.tx.PrepareContext(ctx, query)
-}
-
-func (t *TxDB) Exec(query string, args ...interface{}) (sql.Result, error) {
- return t.ExecContext(context.Background(), query, args...)
-}
-
-func (t *TxDB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
- return t.tx.ExecContext(ctx, query, args...)
-}
-
-func (t *TxDB) Query(query string, args ...interface{}) (*sql.Rows, error) {
- return t.QueryContext(context.Background(), query, args...)
-}
-
-func (t *TxDB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
- return t.tx.QueryContext(ctx, query, args...)
-}
-
-func (t *TxDB) QueryRow(query string, args ...interface{}) *sql.Row {
- return t.QueryRowContext(context.Background(), query, args...)
-}
-
-func (t *TxDB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
- return t.tx.QueryRowContext(ctx, query, args...)
+func (d *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
+ sd, err := d.getStmtDecorator(query)
+ if err != nil {
+ panic(err)
+ }
+ stmt := sd.getStmt()
+ defer sd.release()
+ return stmt.QueryRowContext(ctx, args)
}
type alias struct {
- Name string
- Driver DriverType
- DriverName string
- DataSource string
- MaxIdleConns int
- MaxOpenConns int
- ConnMaxLifetime time.Duration
- StmtCacheSize int
- DB *DB
- DbBaser dbBaser
- TZ *time.Location
- Engine string
+ Name string
+ Driver DriverType
+ DriverName string
+ DataSource string
+ MaxIdleConns int
+ MaxOpenConns int
+ DB *DB
+ DbBaser dbBaser
+ TZ *time.Location
+ Engine string
}
func detectTZ(al *alias) {
@@ -338,53 +289,15 @@ func detectTZ(al *alias) {
}
}
-func addAliasWthDB(aliasName, driverName string, db *sql.DB, params ...DBOption) (*alias, error) {
- existErr := fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName)
- if _, ok := dataBaseCache.get(aliasName); ok {
- return nil, existErr
- }
-
- al, err := newAliasWithDb(aliasName, driverName, db, params...)
- if err != nil {
- return nil, err
- }
-
- if !dataBaseCache.add(aliasName, al) {
- return nil, existErr
- }
-
- return al, nil
-}
-
-func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...DBOption) (*alias, error) {
-
- al := &alias{}
- al.DB = &DB{
- RWMutex: new(sync.RWMutex),
- DB: db,
- }
-
- for _, p := range params {
- p(al)
- }
-
- var stmtCache *lru.Cache
- var stmtCacheSize int
-
- if al.StmtCacheSize > 0 {
- _stmtCache, errC := newStmtDecoratorLruWithEvict(al.StmtCacheSize)
- if errC != nil {
- return nil, errC
- } else {
- stmtCache = _stmtCache
- stmtCacheSize = al.StmtCacheSize
- }
- }
-
+func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
+ al := new(alias)
al.Name = aliasName
al.DriverName = driverName
- al.DB.stmtDecorators = stmtCache
- al.DB.stmtDecoratorsLimit = stmtCacheSize
+ al.DB = &DB{
+ RWMutex: new(sync.RWMutex),
+ DB: db,
+ stmtDecorators: newStmtDecoratorLruWithEvict(),
+ }
if dr, ok := drivers[driverName]; ok {
al.DbBaser = dbBasers[dr]
@@ -398,50 +311,21 @@ func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...DBOption
return nil, fmt.Errorf("register db Ping `%s`, %s", aliasName, err.Error())
}
- detectTZ(al)
+ if !dataBaseCache.add(aliasName, al) {
+ return nil, fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName)
+ }
return al, nil
}
-// SetMaxIdleConns Change the max idle conns for *sql.DB, use specify database alias name
-// Deprecated you should not use this, we will remove it in the future
-func SetMaxIdleConns(aliasName string, maxIdleConns int) {
- al := getDbAlias(aliasName)
- al.SetMaxIdleConns(maxIdleConns)
-}
-
-// SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name
-// Deprecated you should not use this, we will remove it in the future
-func SetMaxOpenConns(aliasName string, maxOpenConns int) {
- al := getDbAlias(aliasName)
- al.SetMaxIdleConns(maxOpenConns)
-}
-
-// SetMaxIdleConns Change the max idle conns for *sql.DB, use specify database alias name
-func (al *alias) SetMaxIdleConns(maxIdleConns int) {
- al.MaxIdleConns = maxIdleConns
- al.DB.DB.SetMaxIdleConns(maxIdleConns)
-}
-
-// SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name
-func (al *alias) SetMaxOpenConns(maxOpenConns int) {
- al.MaxOpenConns = maxOpenConns
- al.DB.DB.SetMaxOpenConns(maxOpenConns)
-}
-
-func (al *alias) SetConnMaxLifetime(lifeTime time.Duration) {
- al.ConnMaxLifetime = lifeTime
- al.DB.DB.SetConnMaxLifetime(lifeTime)
-}
-
// AddAliasWthDB add a aliasName for the drivename
-func AddAliasWthDB(aliasName, driverName string, db *sql.DB, params ...DBOption) error {
- _, err := addAliasWthDB(aliasName, driverName, db, params...)
+func AddAliasWthDB(aliasName, driverName string, db *sql.DB) error {
+ _, err := addAliasWthDB(aliasName, driverName, db)
return err
}
// RegisterDataBase Setting the database connect params. Use the database driver self dataSource args.
-func RegisterDataBase(aliasName, driverName, dataSource string, params ...DBOption) error {
+func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) error {
var (
err error
db *sql.DB
@@ -454,13 +338,24 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...DBOpti
goto end
}
- al, err = addAliasWthDB(aliasName, driverName, db, params...)
+ al, err = addAliasWthDB(aliasName, driverName, db)
if err != nil {
goto end
}
al.DataSource = dataSource
+ detectTZ(al)
+
+ for i, v := range params {
+ switch i {
+ case 0:
+ SetMaxIdleConns(al.Name, v)
+ case 1:
+ SetMaxOpenConns(al.Name, v)
+ }
+ }
+
end:
if err != nil {
if db != nil {
@@ -494,6 +389,24 @@ func SetDataBaseTZ(aliasName string, tz *time.Location) error {
return nil
}
+// SetMaxIdleConns Change the max idle conns for *sql.DB, use specify database alias name
+func SetMaxIdleConns(aliasName string, maxIdleConns int) {
+ al := getDbAlias(aliasName)
+ al.MaxIdleConns = maxIdleConns
+ al.DB.DB.SetMaxIdleConns(maxIdleConns)
+}
+
+// SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name
+func SetMaxOpenConns(aliasName string, maxOpenConns int) {
+ al := getDbAlias(aliasName)
+ al.MaxOpenConns = maxOpenConns
+ al.DB.DB.SetMaxOpenConns(maxOpenConns)
+ // for tip go 1.2
+ if fun := reflect.ValueOf(al.DB).MethodByName("SetMaxOpenConns"); fun.IsValid() {
+ fun.Call([]reflect.Value{reflect.ValueOf(maxOpenConns)})
+ }
+}
+
// GetDB Get *sql.DB from registered database by db alias name.
// Use "default" as alias name if you not set.
func GetDB(aliasNames ...string) (*sql.DB, error) {
@@ -511,7 +424,8 @@ func GetDB(aliasNames ...string) (*sql.DB, error) {
}
type stmtDecorator struct {
- wg sync.WaitGroup
+ wg sync.WaitGroup
+ lastUse int64
stmt *sql.Stmt
}
@@ -519,19 +433,16 @@ func (s *stmtDecorator) getStmt() *sql.Stmt {
return s.stmt
}
-// acquire will add one
-// since this method will be used inside read lock scope,
-// so we can not do more things here
-// we should think about refactor this
func (s *stmtDecorator) acquire() {
s.wg.Add(1)
+ s.lastUse = time.Now().Unix()
}
func (s *stmtDecorator) release() {
s.wg.Done()
}
-// garbage recycle for stmt
+//garbage recycle for stmt
func (s *stmtDecorator) destroy() {
go func() {
s.wg.Wait()
@@ -542,45 +453,13 @@ func (s *stmtDecorator) destroy() {
func newStmtDecorator(sqlStmt *sql.Stmt) *stmtDecorator {
return &stmtDecorator{
stmt: sqlStmt,
+ lastUse: time.Now().Unix(),
}
}
-func newStmtDecoratorLruWithEvict(cacheSize int) (*lru.Cache, error) {
- cache, err := lru.NewWithEvict(cacheSize, func(key interface{}, value interface{}) {
+func newStmtDecoratorLruWithEvict() *lru.Cache {
+ cache, _ := lru.NewWithEvict(1000, func(key interface{}, value interface{}) {
value.(*stmtDecorator).destroy()
})
- if err != nil {
- return nil, err
- }
- return cache, nil
-}
-
-type DBOption func(al *alias)
-
-// MaxIdleConnections return a hint about MaxIdleConnections
-func MaxIdleConnections(maxIdleConn int) DBOption {
- return func(al *alias) {
- al.SetMaxIdleConns(maxIdleConn)
- }
-}
-
-// MaxOpenConnections return a hint about MaxOpenConnections
-func MaxOpenConnections(maxOpenConn int) DBOption {
- return func(al *alias) {
- al.SetMaxOpenConns(maxOpenConn)
- }
-}
-
-// ConnMaxLifetime return a hint about ConnMaxLifetime
-func ConnMaxLifetime(v time.Duration) DBOption {
- return func(al *alias) {
- al.SetConnMaxLifetime(v)
- }
-}
-
-// MaxStmtCacheSize return a hint about MaxStmtCacheSize
-func MaxStmtCacheSize(v int) DBOption {
- return func(al *alias) {
- al.StmtCacheSize = v
- }
+ return cache
}
diff --git a/client/orm/db_mysql.go b/orm/db_mysql.go
similarity index 79%
rename from client/orm/db_mysql.go
rename to orm/db_mysql.go
index f674ab2b..6e99058e 100644
--- a/client/orm/db_mysql.go
+++ b/orm/db_mysql.go
@@ -22,11 +22,10 @@ import (
// mysql operators.
var mysqlOperators = map[string]string{
- "exact": "= ?",
- "iexact": "LIKE ?",
- "strictexact": "= BINARY ?",
- "contains": "LIKE BINARY ?",
- "icontains": "LIKE ?",
+ "exact": "= ?",
+ "iexact": "LIKE ?",
+ "contains": "LIKE BINARY ?",
+ "icontains": "LIKE ?",
// "regex": "REGEXP BINARY ?",
// "iregex": "REGEXP ?",
"gt": "> ?",
@@ -43,25 +42,24 @@ var mysqlOperators = map[string]string{
// mysql column field types.
var mysqlTypes = map[string]string{
- "auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY",
- "pk": "NOT NULL PRIMARY KEY",
- "bool": "bool",
- "string": "varchar(%d)",
- "string-char": "char(%d)",
- "string-text": "longtext",
- "time.Time-date": "date",
- "time.Time": "datetime",
- "int8": "tinyint",
- "int16": "smallint",
- "int32": "integer",
- "int64": "bigint",
- "uint8": "tinyint unsigned",
- "uint16": "smallint unsigned",
- "uint32": "integer unsigned",
- "uint64": "bigint unsigned",
- "float64": "double precision",
- "float64-decimal": "numeric(%d, %d)",
- "time.Time-precision": "datetime(%d)",
+ "auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY",
+ "pk": "NOT NULL PRIMARY KEY",
+ "bool": "bool",
+ "string": "varchar(%d)",
+ "string-char": "char(%d)",
+ "string-text": "longtext",
+ "time.Time-date": "date",
+ "time.Time": "datetime",
+ "int8": "tinyint",
+ "int16": "smallint",
+ "int32": "integer",
+ "int64": "bigint",
+ "uint8": "tinyint unsigned",
+ "uint16": "smallint unsigned",
+ "uint32": "integer unsigned",
+ "uint64": "bigint unsigned",
+ "float64": "double precision",
+ "float64-decimal": "numeric(%d, %d)",
}
// mysql dbBaser implementation.
@@ -166,14 +164,7 @@ func (d *dbBaseMysql) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Val
if isMulti {
return res.RowsAffected()
}
-
- lastInsertId, err := res.LastInsertId()
- if err != nil {
- DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
- return lastInsertId, ErrLastInsertIdUnavailable
- } else {
- return lastInsertId, nil
- }
+ return res.LastInsertId()
}
return 0, err
}
diff --git a/client/orm/db_oracle.go b/orm/db_oracle.go
similarity index 67%
rename from client/orm/db_oracle.go
rename to orm/db_oracle.go
index cb0d5052..5d121f83 100644
--- a/client/orm/db_oracle.go
+++ b/orm/db_oracle.go
@@ -17,8 +17,6 @@ package orm
import (
"fmt"
"strings"
-
- "github.com/astaxie/beego/client/orm/hints"
)
// oracle operators.
@@ -33,24 +31,23 @@ var oracleOperators = map[string]string{
// oracle column field types.
var oracleTypes = map[string]string{
- "pk": "NOT NULL PRIMARY KEY",
- "bool": "bool",
- "string": "VARCHAR2(%d)",
- "string-char": "CHAR(%d)",
- "string-text": "VARCHAR2(%d)",
- "time.Time-date": "DATE",
- "time.Time": "TIMESTAMP",
- "int8": "INTEGER",
- "int16": "INTEGER",
- "int32": "INTEGER",
- "int64": "INTEGER",
- "uint8": "INTEGER",
- "uint16": "INTEGER",
- "uint32": "INTEGER",
- "uint64": "INTEGER",
- "float64": "NUMBER",
- "float64-decimal": "NUMBER(%d, %d)",
- "time.Time-precision": "TIMESTAMP(%d)",
+ "pk": "NOT NULL PRIMARY KEY",
+ "bool": "bool",
+ "string": "VARCHAR2(%d)",
+ "string-char": "CHAR(%d)",
+ "string-text": "VARCHAR2(%d)",
+ "time.Time-date": "DATE",
+ "time.Time": "TIMESTAMP",
+ "int8": "INTEGER",
+ "int16": "INTEGER",
+ "int32": "INTEGER",
+ "int64": "INTEGER",
+ "uint8": "INTEGER",
+ "uint16": "INTEGER",
+ "uint32": "INTEGER",
+ "uint64": "INTEGER",
+ "float64": "NUMBER",
+ "float64-decimal": "NUMBER(%d, %d)",
}
// oracle dbBaser
@@ -99,29 +96,6 @@ func (d *dbBaseOracle) IndexExists(db dbQuerier, table string, name string) bool
return cnt > 0
}
-func (d *dbBaseOracle) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string {
- var s []string
- Q := d.TableQuote()
- for _, index := range indexes {
- tmp := fmt.Sprintf(`%s%s%s`, Q, index, Q)
- s = append(s, tmp)
- }
-
- var hint string
-
- switch useIndex {
- case hints.KeyUseIndex, hints.KeyForceIndex:
- hint = `INDEX`
- case hints.KeyIgnoreIndex:
- hint = `NO_INDEX`
- default:
- DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored")
- return ``
- }
-
- return fmt.Sprintf(` /*+ %s(%s %s)*/ `, hint, tableName, strings.Join(s, `,`))
-}
-
// execute insert sql with given struct and given values.
// insert the given values, not the field values in struct.
func (d *dbBaseOracle) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) {
@@ -152,14 +126,7 @@ func (d *dbBaseOracle) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, nam
if isMulti {
return res.RowsAffected()
}
-
- lastInsertId, err := res.LastInsertId()
- if err != nil {
- DebugLog.Println(ErrLastInsertIdUnavailable, ':', err)
- return lastInsertId, ErrLastInsertIdUnavailable
- } else {
- return lastInsertId, nil
- }
+ return res.LastInsertId()
}
return 0, err
}
diff --git a/client/orm/db_postgres.go b/orm/db_postgres.go
similarity index 78%
rename from client/orm/db_postgres.go
rename to orm/db_postgres.go
index 12431d6e..c488fb38 100644
--- a/client/orm/db_postgres.go
+++ b/orm/db_postgres.go
@@ -39,27 +39,26 @@ var postgresOperators = map[string]string{
// postgresql column field types.
var postgresTypes = map[string]string{
- "auto": "serial NOT NULL PRIMARY KEY",
- "pk": "NOT NULL PRIMARY KEY",
- "bool": "bool",
- "string": "varchar(%d)",
- "string-char": "char(%d)",
- "string-text": "text",
- "time.Time-date": "date",
- "time.Time": "timestamp with time zone",
- "int8": `smallint CHECK("%COL%" >= -127 AND "%COL%" <= 128)`,
- "int16": "smallint",
- "int32": "integer",
- "int64": "bigint",
- "uint8": `smallint CHECK("%COL%" >= 0 AND "%COL%" <= 255)`,
- "uint16": `integer CHECK("%COL%" >= 0)`,
- "uint32": `bigint CHECK("%COL%" >= 0)`,
- "uint64": `bigint CHECK("%COL%" >= 0)`,
- "float64": "double precision",
- "float64-decimal": "numeric(%d, %d)",
- "json": "json",
- "jsonb": "jsonb",
- "time.Time-precision": "timestamp(%d) with time zone",
+ "auto": "serial NOT NULL PRIMARY KEY",
+ "pk": "NOT NULL PRIMARY KEY",
+ "bool": "bool",
+ "string": "varchar(%d)",
+ "string-char": "char(%d)",
+ "string-text": "text",
+ "time.Time-date": "date",
+ "time.Time": "timestamp with time zone",
+ "int8": `smallint CHECK("%COL%" >= -127 AND "%COL%" <= 128)`,
+ "int16": "smallint",
+ "int32": "integer",
+ "int64": "bigint",
+ "uint8": `smallint CHECK("%COL%" >= 0 AND "%COL%" <= 255)`,
+ "uint16": `integer CHECK("%COL%" >= 0)`,
+ "uint32": `bigint CHECK("%COL%" >= 0)`,
+ "uint64": `bigint CHECK("%COL%" >= 0)`,
+ "float64": "double precision",
+ "float64-decimal": "numeric(%d, %d)",
+ "json": "json",
+ "jsonb": "jsonb",
}
// postgresql dbBaser.
@@ -182,12 +181,6 @@ func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bo
return cnt > 0
}
-// GenerateSpecifyIndex return a specifying index clause
-func (d *dbBasePostgres) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string {
- DebugLog.Println("[WARN] Not support any specifying index action, so that action is ignored")
- return ``
-}
-
// create new postgresql dbBaser.
func newdbBasePostgres() dbBaser {
b := new(dbBasePostgres)
diff --git a/client/orm/db_sqlite.go b/orm/db_sqlite.go
similarity index 73%
rename from client/orm/db_sqlite.go
rename to orm/db_sqlite.go
index 961f2535..1d62ee34 100644
--- a/client/orm/db_sqlite.go
+++ b/orm/db_sqlite.go
@@ -18,10 +18,7 @@ import (
"database/sql"
"fmt"
"reflect"
- "strings"
"time"
-
- "github.com/astaxie/beego/client/orm/hints"
)
// sqlite operators.
@@ -44,25 +41,24 @@ var sqliteOperators = map[string]string{
// sqlite column types.
var sqliteTypes = map[string]string{
- "auto": "integer NOT NULL PRIMARY KEY AUTOINCREMENT",
- "pk": "NOT NULL PRIMARY KEY",
- "bool": "bool",
- "string": "varchar(%d)",
- "string-char": "character(%d)",
- "string-text": "text",
- "time.Time-date": "date",
- "time.Time": "datetime",
- "time.Time-precision": "datetime(%d)",
- "int8": "tinyint",
- "int16": "smallint",
- "int32": "integer",
- "int64": "bigint",
- "uint8": "tinyint unsigned",
- "uint16": "smallint unsigned",
- "uint32": "integer unsigned",
- "uint64": "bigint unsigned",
- "float64": "real",
- "float64-decimal": "decimal",
+ "auto": "integer NOT NULL PRIMARY KEY AUTOINCREMENT",
+ "pk": "NOT NULL PRIMARY KEY",
+ "bool": "bool",
+ "string": "varchar(%d)",
+ "string-char": "character(%d)",
+ "string-text": "text",
+ "time.Time-date": "date",
+ "time.Time": "datetime",
+ "int8": "tinyint",
+ "int16": "smallint",
+ "int32": "integer",
+ "int64": "bigint",
+ "uint8": "tinyint unsigned",
+ "uint16": "smallint unsigned",
+ "uint32": "integer unsigned",
+ "uint64": "bigint unsigned",
+ "float64": "real",
+ "float64-decimal": "decimal",
}
// sqlite dbBaser.
@@ -157,24 +153,6 @@ func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool
return false
}
-// GenerateSpecifyIndex return a specifying index clause
-func (d *dbBaseSqlite) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string {
- var s []string
- Q := d.TableQuote()
- for _, index := range indexes {
- tmp := fmt.Sprintf(`%s%s%s`, Q, index, Q)
- s = append(s, tmp)
- }
-
- switch useIndex {
- case hints.KeyUseIndex, hints.KeyForceIndex:
- return fmt.Sprintf(` INDEXED BY %s `, strings.Join(s, `,`))
- default:
- DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored")
- return ``
- }
-}
-
// create new sqlite dbBaser.
func newdbBaseSqlite() dbBaser {
b := new(dbBaseSqlite)
diff --git a/client/orm/db_tables.go b/orm/db_tables.go
similarity index 97%
rename from client/orm/db_tables.go
rename to orm/db_tables.go
index 5fd472d1..4b21a6fc 100644
--- a/client/orm/db_tables.go
+++ b/orm/db_tables.go
@@ -472,15 +472,6 @@ func (t *dbTables) getLimitSQL(mi *modelInfo, offset int64, limit int64) (limits
return
}
-// getIndexSql generate index sql.
-func (t *dbTables) getIndexSql(tableName string, useIndex int, indexes []string) (clause string) {
- if len(indexes) == 0 {
- return
- }
-
- return t.base.GenerateSpecifyIndex(tableName, useIndex, indexes)
-}
-
// crete new tables collection.
func newDbTables(mi *modelInfo, base dbBaser) *dbTables {
tables := &dbTables{}
diff --git a/client/orm/db_tidb.go b/orm/db_tidb.go
similarity index 100%
rename from client/orm/db_tidb.go
rename to orm/db_tidb.go
diff --git a/client/orm/db_utils.go b/orm/db_utils.go
similarity index 100%
rename from client/orm/db_utils.go
rename to orm/db_utils.go
diff --git a/orm/models.go b/orm/models.go
new file mode 100644
index 00000000..4776bcba
--- /dev/null
+++ b/orm/models.go
@@ -0,0 +1,99 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package orm
+
+import (
+ "sync"
+)
+
+const (
+ odCascade = "cascade"
+ odSetNULL = "set_null"
+ odSetDefault = "set_default"
+ odDoNothing = "do_nothing"
+ defaultStructTagName = "orm"
+ defaultStructTagDelim = ";"
+)
+
+var (
+ modelCache = &_modelCache{
+ cache: make(map[string]*modelInfo),
+ cacheByFullName: make(map[string]*modelInfo),
+ }
+)
+
+// model info collection
+type _modelCache struct {
+ sync.RWMutex // only used outsite for bootStrap
+ orders []string
+ cache map[string]*modelInfo
+ cacheByFullName map[string]*modelInfo
+ done bool
+}
+
+// get all model info
+func (mc *_modelCache) all() map[string]*modelInfo {
+ m := make(map[string]*modelInfo, len(mc.cache))
+ for k, v := range mc.cache {
+ m[k] = v
+ }
+ return m
+}
+
+// get ordered model info
+func (mc *_modelCache) allOrdered() []*modelInfo {
+ m := make([]*modelInfo, 0, len(mc.orders))
+ for _, table := range mc.orders {
+ m = append(m, mc.cache[table])
+ }
+ return m
+}
+
+// get model info by table name
+func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
+ mi, ok = mc.cache[table]
+ return
+}
+
+// get model info by full name
+func (mc *_modelCache) getByFullName(name string) (mi *modelInfo, ok bool) {
+ mi, ok = mc.cacheByFullName[name]
+ return
+}
+
+// set model info to collection
+func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
+ mii := mc.cache[table]
+ mc.cache[table] = mi
+ mc.cacheByFullName[mi.fullName] = mi
+ if mii == nil {
+ mc.orders = append(mc.orders, table)
+ }
+ return mii
+}
+
+// clean all model info.
+func (mc *_modelCache) clean() {
+ mc.orders = make([]string, 0)
+ mc.cache = make(map[string]*modelInfo)
+ mc.cacheByFullName = make(map[string]*modelInfo)
+ mc.done = false
+}
+
+// ResetModelCache Clean model cache. Then you can re-RegisterModel.
+// Common use this api for test case.
+func ResetModelCache() {
+ modelCache.clean()
+}
diff --git a/orm/models_boot.go b/orm/models_boot.go
new file mode 100644
index 00000000..8c56b3c4
--- /dev/null
+++ b/orm/models_boot.go
@@ -0,0 +1,347 @@
+// 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 orm
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "runtime/debug"
+ "strings"
+)
+
+// register models.
+// PrefixOrSuffix means table name prefix or suffix.
+// isPrefix whether the prefix is prefix or suffix
+func registerModel(PrefixOrSuffix string, model interface{}, isPrefix bool) {
+ val := reflect.ValueOf(model)
+ typ := reflect.Indirect(val).Type()
+
+ if val.Kind() != reflect.Ptr {
+ panic(fmt.Errorf(" cannot use non-ptr model struct `%s`", getFullName(typ)))
+ }
+ // For this case:
+ // u := &User{}
+ // registerModel(&u)
+ if typ.Kind() == reflect.Ptr {
+ panic(fmt.Errorf(" only allow ptr model struct, it looks you use two reference to the struct `%s`", typ))
+ }
+
+ table := getTableName(val)
+
+ if PrefixOrSuffix != "" {
+ if isPrefix {
+ table = PrefixOrSuffix + table
+ } else {
+ table = table + PrefixOrSuffix
+ }
+ }
+ // models's fullname is pkgpath + struct name
+ name := getFullName(typ)
+ if _, ok := modelCache.getByFullName(name); ok {
+ fmt.Printf(" model `%s` repeat register, must be unique\n", name)
+ os.Exit(2)
+ }
+
+ if _, ok := modelCache.get(table); ok {
+ fmt.Printf(" table name `%s` repeat register, must be unique\n", table)
+ os.Exit(2)
+ }
+
+ mi := newModelInfo(val)
+ if mi.fields.pk == nil {
+ outFor:
+ for _, fi := range mi.fields.fieldsDB {
+ if strings.ToLower(fi.name) == "id" {
+ switch fi.addrValue.Elem().Kind() {
+ case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64:
+ fi.auto = true
+ fi.pk = true
+ mi.fields.pk = fi
+ break outFor
+ }
+ }
+ }
+
+ if mi.fields.pk == nil {
+ fmt.Printf(" `%s` needs a primary key field, default is to use 'id' if not set\n", name)
+ os.Exit(2)
+ }
+
+ }
+
+ mi.table = table
+ mi.pkg = typ.PkgPath()
+ mi.model = model
+ mi.manual = true
+
+ modelCache.set(table, mi)
+}
+
+// bootstrap models
+func bootStrap() {
+ if modelCache.done {
+ return
+ }
+ var (
+ err error
+ models map[string]*modelInfo
+ )
+ if dataBaseCache.getDefault() == nil {
+ err = fmt.Errorf("must have one register DataBase alias named `default`")
+ goto end
+ }
+
+ // set rel and reverse model
+ // RelManyToMany set the relTable
+ models = modelCache.all()
+ for _, mi := range models {
+ for _, fi := range mi.fields.columns {
+ if fi.rel || fi.reverse {
+ elm := fi.addrValue.Type().Elem()
+ if fi.fieldType == RelReverseMany || fi.fieldType == RelManyToMany {
+ elm = elm.Elem()
+ }
+ // check the rel or reverse model already register
+ name := getFullName(elm)
+ mii, ok := modelCache.getByFullName(name)
+ if !ok || mii.pkg != elm.PkgPath() {
+ err = fmt.Errorf("can not find rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String())
+ goto end
+ }
+ fi.relModelInfo = mii
+
+ switch fi.fieldType {
+ case RelManyToMany:
+ if fi.relThrough != "" {
+ if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) {
+ pn := fi.relThrough[:i]
+ rmi, ok := modelCache.getByFullName(fi.relThrough)
+ if !ok || pn != rmi.pkg {
+ err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.fullName, fi.relThrough)
+ goto end
+ }
+ fi.relThroughModelInfo = rmi
+ fi.relTable = rmi.table
+ } else {
+ err = fmt.Errorf("field `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough)
+ goto end
+ }
+ } else {
+ i := newM2MModelInfo(mi, mii)
+ if fi.relTable != "" {
+ i.table = fi.relTable
+ }
+ if v := modelCache.set(i.table, i); v != nil {
+ err = fmt.Errorf("the rel table name `%s` already registered, cannot be use, please change one", fi.relTable)
+ goto end
+ }
+ fi.relTable = i.table
+ fi.relThroughModelInfo = i
+ }
+
+ fi.relThroughModelInfo.isThrough = true
+ }
+ }
+ }
+ }
+
+ // check the rel filed while the relModelInfo also has filed point to current model
+ // if not exist, add a new field to the relModelInfo
+ models = modelCache.all()
+ for _, mi := range models {
+ for _, fi := range mi.fields.fieldsRel {
+ switch fi.fieldType {
+ case RelForeignKey, RelOneToOne, RelManyToMany:
+ inModel := false
+ for _, ffi := range fi.relModelInfo.fields.fieldsReverse {
+ if ffi.relModelInfo == mi {
+ inModel = true
+ break
+ }
+ }
+ if !inModel {
+ rmi := fi.relModelInfo
+ ffi := new(fieldInfo)
+ ffi.name = mi.name
+ ffi.column = ffi.name
+ ffi.fullName = rmi.fullName + "." + ffi.name
+ ffi.reverse = true
+ ffi.relModelInfo = mi
+ ffi.mi = rmi
+ if fi.fieldType == RelOneToOne {
+ ffi.fieldType = RelReverseOne
+ } else {
+ ffi.fieldType = RelReverseMany
+ }
+ if !rmi.fields.Add(ffi) {
+ added := false
+ for cnt := 0; cnt < 5; cnt++ {
+ ffi.name = fmt.Sprintf("%s%d", mi.name, cnt)
+ ffi.column = ffi.name
+ ffi.fullName = rmi.fullName + "." + ffi.name
+ if added = rmi.fields.Add(ffi); added {
+ break
+ }
+ }
+ if !added {
+ panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName))
+ }
+ }
+ }
+ }
+ }
+ }
+
+ models = modelCache.all()
+ for _, mi := range models {
+ for _, fi := range mi.fields.fieldsRel {
+ switch fi.fieldType {
+ case RelManyToMany:
+ for _, ffi := range fi.relThroughModelInfo.fields.fieldsRel {
+ switch ffi.fieldType {
+ case RelOneToOne, RelForeignKey:
+ if ffi.relModelInfo == fi.relModelInfo {
+ fi.reverseFieldInfoTwo = ffi
+ }
+ if ffi.relModelInfo == mi {
+ fi.reverseField = ffi.name
+ fi.reverseFieldInfo = ffi
+ }
+ }
+ }
+ if fi.reverseFieldInfoTwo == nil {
+ err = fmt.Errorf("can not find m2m field for m2m model `%s`, ensure your m2m model defined correct",
+ fi.relThroughModelInfo.fullName)
+ goto end
+ }
+ }
+ }
+ }
+
+ models = modelCache.all()
+ for _, mi := range models {
+ for _, fi := range mi.fields.fieldsReverse {
+ switch fi.fieldType {
+ case RelReverseOne:
+ found := false
+ mForA:
+ for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelOneToOne] {
+ if ffi.relModelInfo == mi {
+ found = true
+ fi.reverseField = ffi.name
+ fi.reverseFieldInfo = ffi
+
+ ffi.reverseField = fi.name
+ ffi.reverseFieldInfo = fi
+ break mForA
+ }
+ }
+ if !found {
+ err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
+ goto end
+ }
+ case RelReverseMany:
+ found := false
+ mForB:
+ for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelForeignKey] {
+ if ffi.relModelInfo == mi {
+ found = true
+ fi.reverseField = ffi.name
+ fi.reverseFieldInfo = ffi
+
+ ffi.reverseField = fi.name
+ ffi.reverseFieldInfo = fi
+
+ break mForB
+ }
+ }
+ if !found {
+ mForC:
+ for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] {
+ conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough ||
+ fi.relTable != "" && fi.relTable == ffi.relTable ||
+ fi.relThrough == "" && fi.relTable == ""
+ if ffi.relModelInfo == mi && conditions {
+ found = true
+
+ fi.reverseField = ffi.reverseFieldInfoTwo.name
+ fi.reverseFieldInfo = ffi.reverseFieldInfoTwo
+ fi.relThroughModelInfo = ffi.relThroughModelInfo
+ fi.reverseFieldInfoTwo = ffi.reverseFieldInfo
+ fi.reverseFieldInfoM2M = ffi
+ ffi.reverseFieldInfoM2M = fi
+
+ break mForC
+ }
+ }
+ }
+ if !found {
+ err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
+ goto end
+ }
+ }
+ }
+ }
+
+end:
+ if err != nil {
+ fmt.Println(err)
+ debug.PrintStack()
+ os.Exit(2)
+ }
+}
+
+// RegisterModel register models
+func RegisterModel(models ...interface{}) {
+ if modelCache.done {
+ panic(fmt.Errorf("RegisterModel must be run before BootStrap"))
+ }
+ RegisterModelWithPrefix("", models...)
+}
+
+// RegisterModelWithPrefix register models with a prefix
+func RegisterModelWithPrefix(prefix string, models ...interface{}) {
+ if modelCache.done {
+ panic(fmt.Errorf("RegisterModelWithPrefix must be run before BootStrap"))
+ }
+
+ for _, model := range models {
+ registerModel(prefix, model, true)
+ }
+}
+
+// RegisterModelWithSuffix register models with a suffix
+func RegisterModelWithSuffix(suffix string, models ...interface{}) {
+ if modelCache.done {
+ panic(fmt.Errorf("RegisterModelWithSuffix must be run before BootStrap"))
+ }
+
+ for _, model := range models {
+ registerModel(suffix, model, false)
+ }
+}
+
+// BootStrap bootstrap models.
+// make all model parsed and can not add more models
+func BootStrap() {
+ modelCache.Lock()
+ defer modelCache.Unlock()
+ if modelCache.done {
+ return
+ }
+ bootStrap()
+ modelCache.done = true
+}
diff --git a/client/orm/models_fields.go b/orm/models_fields.go
similarity index 100%
rename from client/orm/models_fields.go
rename to orm/models_fields.go
diff --git a/client/orm/models_info_f.go b/orm/models_info_f.go
similarity index 97%
rename from client/orm/models_info_f.go
rename to orm/models_info_f.go
index 7152fada..7044b0bd 100644
--- a/client/orm/models_info_f.go
+++ b/orm/models_info_f.go
@@ -137,7 +137,6 @@ type fieldInfo struct {
isFielder bool // implement Fielder interface
onDelete string
description string
- timePrecision *int
}
// new field info
@@ -178,7 +177,7 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField, mN
decimals := tags["decimals"]
size := tags["size"]
onDelete := tags["on_delete"]
- precision := tags["precision"]
+
initial.Clear()
if v, ok := tags["default"]; ok {
initial.Set(v)
@@ -378,18 +377,6 @@ checkType:
fi.index = false
fi.unique = false
case TypeTimeField, TypeDateField, TypeDateTimeField:
- if fieldType == TypeDateTimeField {
- if precision != "" {
- v, e := StrTo(precision).Int()
- if e != nil {
- err = fmt.Errorf("convert %s to int error:%v", precision, e)
- } else {
- fi.timePrecision = &v
- }
- }
-
- }
-
if attrs["auto_now"] {
fi.autoNow = true
} else if attrs["auto_now_add"] {
diff --git a/client/orm/models_info_m.go b/orm/models_info_m.go
similarity index 98%
rename from client/orm/models_info_m.go
rename to orm/models_info_m.go
index c450239c..a4d733b6 100644
--- a/client/orm/models_info_m.go
+++ b/orm/models_info_m.go
@@ -29,7 +29,7 @@ type modelInfo struct {
model interface{}
fields *fields
manual bool
- addrField reflect.Value // store the original struct value
+ addrField reflect.Value //store the original struct value
uniques []string
isThrough bool
}
diff --git a/client/orm/models_test.go b/orm/models_test.go
similarity index 66%
rename from client/orm/models_test.go
rename to orm/models_test.go
index d5aa2fa0..e3a635f2 100644
--- a/client/orm/models_test.go
+++ b/orm/models_test.go
@@ -53,24 +53,18 @@ func (e *SliceStringField) FieldType() int {
}
func (e *SliceStringField) SetRaw(value interface{}) error {
- f := func(str string) {
- if len(str) > 0 {
- parts := strings.Split(str, ",")
+ switch d := value.(type) {
+ case []string:
+ e.Set(d)
+ case string:
+ if len(d) > 0 {
+ parts := strings.Split(d, ",")
v := make([]string, 0, len(parts))
for _, p := range parts {
v = append(v, strings.TrimSpace(p))
}
e.Set(v)
}
- }
-
- switch d := value.(type) {
- case []string:
- e.Set(d)
- case string:
- f(d)
- case []byte:
- f(string(d))
default:
return fmt.Errorf(" unknown value `%v`", value)
}
@@ -102,8 +96,6 @@ func (e *JSONFieldTest) SetRaw(value interface{}) error {
switch d := value.(type) {
case string:
return json.Unmarshal([]byte(d), e)
- case []byte:
- return json.Unmarshal(d, e)
default:
return fmt.Errorf(" unknown value `%v`", value)
}
@@ -143,56 +135,55 @@ type Data struct {
}
type DataNull struct {
- ID int `orm:"column(id)"`
- Boolean bool `orm:"null"`
- Char string `orm:"null;size(50)"`
- Text string `orm:"null;type(text)"`
- JSON string `orm:"type(json);null"`
- Jsonb string `orm:"type(jsonb);null"`
- Time time.Time `orm:"null;type(time)"`
- Date time.Time `orm:"null;type(date)"`
- DateTime time.Time `orm:"null;column(datetime)"`
- DateTimePrecision time.Time `orm:"null;type(datetime);precision(4)"`
- Byte byte `orm:"null"`
- Rune rune `orm:"null"`
- Int int `orm:"null"`
- Int8 int8 `orm:"null"`
- Int16 int16 `orm:"null"`
- Int32 int32 `orm:"null"`
- Int64 int64 `orm:"null"`
- Uint uint `orm:"null"`
- Uint8 uint8 `orm:"null"`
- Uint16 uint16 `orm:"null"`
- Uint32 uint32 `orm:"null"`
- Uint64 uint64 `orm:"null"`
- Float32 float32 `orm:"null"`
- Float64 float64 `orm:"null"`
- Decimal float64 `orm:"digits(8);decimals(4);null"`
- NullString sql.NullString `orm:"null"`
- NullBool sql.NullBool `orm:"null"`
- NullFloat64 sql.NullFloat64 `orm:"null"`
- NullInt64 sql.NullInt64 `orm:"null"`
- BooleanPtr *bool `orm:"null"`
- CharPtr *string `orm:"null;size(50)"`
- TextPtr *string `orm:"null;type(text)"`
- BytePtr *byte `orm:"null"`
- RunePtr *rune `orm:"null"`
- IntPtr *int `orm:"null"`
- Int8Ptr *int8 `orm:"null"`
- Int16Ptr *int16 `orm:"null"`
- Int32Ptr *int32 `orm:"null"`
- Int64Ptr *int64 `orm:"null"`
- UintPtr *uint `orm:"null"`
- Uint8Ptr *uint8 `orm:"null"`
- Uint16Ptr *uint16 `orm:"null"`
- Uint32Ptr *uint32 `orm:"null"`
- Uint64Ptr *uint64 `orm:"null"`
- Float32Ptr *float32 `orm:"null"`
- Float64Ptr *float64 `orm:"null"`
- DecimalPtr *float64 `orm:"digits(8);decimals(4);null"`
- TimePtr *time.Time `orm:"null;type(time)"`
- DatePtr *time.Time `orm:"null;type(date)"`
- DateTimePtr *time.Time `orm:"null"`
+ ID int `orm:"column(id)"`
+ Boolean bool `orm:"null"`
+ Char string `orm:"null;size(50)"`
+ Text string `orm:"null;type(text)"`
+ JSON string `orm:"type(json);null"`
+ Jsonb string `orm:"type(jsonb);null"`
+ Time time.Time `orm:"null;type(time)"`
+ Date time.Time `orm:"null;type(date)"`
+ DateTime time.Time `orm:"null;column(datetime)"`
+ Byte byte `orm:"null"`
+ Rune rune `orm:"null"`
+ Int int `orm:"null"`
+ Int8 int8 `orm:"null"`
+ Int16 int16 `orm:"null"`
+ Int32 int32 `orm:"null"`
+ Int64 int64 `orm:"null"`
+ Uint uint `orm:"null"`
+ Uint8 uint8 `orm:"null"`
+ Uint16 uint16 `orm:"null"`
+ Uint32 uint32 `orm:"null"`
+ Uint64 uint64 `orm:"null"`
+ Float32 float32 `orm:"null"`
+ Float64 float64 `orm:"null"`
+ Decimal float64 `orm:"digits(8);decimals(4);null"`
+ NullString sql.NullString `orm:"null"`
+ NullBool sql.NullBool `orm:"null"`
+ NullFloat64 sql.NullFloat64 `orm:"null"`
+ NullInt64 sql.NullInt64 `orm:"null"`
+ BooleanPtr *bool `orm:"null"`
+ CharPtr *string `orm:"null;size(50)"`
+ TextPtr *string `orm:"null;type(text)"`
+ BytePtr *byte `orm:"null"`
+ RunePtr *rune `orm:"null"`
+ IntPtr *int `orm:"null"`
+ Int8Ptr *int8 `orm:"null"`
+ Int16Ptr *int16 `orm:"null"`
+ Int32Ptr *int32 `orm:"null"`
+ Int64Ptr *int64 `orm:"null"`
+ UintPtr *uint `orm:"null"`
+ Uint8Ptr *uint8 `orm:"null"`
+ Uint16Ptr *uint16 `orm:"null"`
+ Uint32Ptr *uint32 `orm:"null"`
+ Uint64Ptr *uint64 `orm:"null"`
+ Float32Ptr *float32 `orm:"null"`
+ Float64Ptr *float64 `orm:"null"`
+ DecimalPtr *float64 `orm:"digits(8);decimals(4);null"`
+ TimePtr *time.Time `orm:"null;type(time)"`
+ DatePtr *time.Time `orm:"null;type(date)"`
+ DateTimePtr *time.Time `orm:"null"`
}
type String string
@@ -240,21 +231,6 @@ type UserBig struct {
Name string
}
-type TM struct {
- ID int `orm:"column(id)"`
- TMPrecision1 time.Time `orm:"type(datetime);precision(3)"`
- TMPrecision2 time.Time `orm:"auto_now_add;type(datetime);precision(4)"`
-}
-
-func (t *TM) TableName() string {
- return "tm"
-}
-
-func NewTM() *TM {
- obj := new(TM)
- return obj
-}
-
type User struct {
ID int `orm:"column(id)"`
UserName string `orm:"size(30);unique"`
@@ -311,14 +287,13 @@ func NewProfile() *Profile {
}
type Post struct {
- ID int `orm:"column(id)"`
- User *User `orm:"rel(fk)"`
- Title string `orm:"size(60)"`
- Content string `orm:"type(text)"`
- Created time.Time `orm:"auto_now_add"`
- Updated time.Time `orm:"auto_now"`
- UpdatedPrecision time.Time `orm:"auto_now;type(datetime);precision(4)"`
- Tags []*Tag `orm:"rel(m2m);rel_through(github.com/astaxie/beego/client/orm.PostTags)"`
+ ID int `orm:"column(id)"`
+ User *User `orm:"rel(fk)"`
+ Title string `orm:"size(60)"`
+ Content string `orm:"type(text)"`
+ Created time.Time `orm:"auto_now_add"`
+ Updated time.Time `orm:"auto_now"`
+ Tags []*Tag `orm:"rel(m2m);rel_through(github.com/astaxie/beego/orm.PostTags)"`
}
func (u *Post) TableIndex() [][]string {
@@ -376,7 +351,7 @@ type Group struct {
type Permission struct {
ID int `orm:"column(id)"`
Name string
- Groups []*Group `orm:"rel(m2m);rel_through(github.com/astaxie/beego/client/orm.GroupPermissions)"`
+ Groups []*Group `orm:"rel(m2m);rel_through(github.com/astaxie/beego/orm.GroupPermissions)"`
}
type GroupPermissions struct {
@@ -405,15 +380,6 @@ type InLine struct {
Email string
}
-type Index struct {
- // Common Fields
- Id int `orm:"column(id)"`
-
- // Other Fields
- F1 int `orm:"column(f1);index"`
- F2 int `orm:"column(f2);index"`
-}
-
func NewInLine() *InLine {
return new(InLine)
}
@@ -445,11 +411,6 @@ type PtrPk struct {
Positive bool
}
-type StrPk struct {
- Id string `orm:"column(id);size(64);pk"`
- Value string
-}
-
var DBARGS = struct {
Driver string
Source string
@@ -485,7 +446,7 @@ var (
usage:
- go get -u github.com/astaxie/beego/client/orm
+ go get -u github.com/astaxie/beego/orm
go get -u github.com/go-sql-driver/mysql
go get -u github.com/mattn/go-sqlite3
go get -u github.com/lib/pq
@@ -495,43 +456,38 @@ var (
mysql -u root -e 'create database orm_test;'
export ORM_DRIVER=mysql
export ORM_SOURCE="root:@/orm_test?charset=utf8"
- go test -v github.com/astaxie/beego/client/orm
+ go test -v github.com/astaxie/beego/orm
#### Sqlite3
export ORM_DRIVER=sqlite3
export ORM_SOURCE='file:memory_test?mode=memory'
- go test -v github.com/astaxie/beego/client/orm
+ go test -v github.com/astaxie/beego/orm
#### PostgreSQL
psql -c 'create database orm_test;' -U postgres
export ORM_DRIVER=postgres
export ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
- go test -v github.com/astaxie/beego/client/orm
+ go test -v github.com/astaxie/beego/orm
#### TiDB
export ORM_DRIVER=tidb
export ORM_SOURCE='memory://test/test'
- go test -v github.com/astaxie/beego/pgk/orm
+ go test -v github.com/astaxie/beego/orm
`
)
func init() {
- // Debug, _ = StrTo(DBARGS.Debug).Bool()
- Debug = true
+ Debug, _ = StrTo(DBARGS.Debug).Bool()
if DBARGS.Driver == "" || DBARGS.Source == "" {
fmt.Println(helpinfo)
os.Exit(2)
}
- err := RegisterDataBase("default", DBARGS.Driver, DBARGS.Source, MaxIdleConnections(20))
-
- if err != nil {
- panic(fmt.Sprintf("can not register database: %v", err))
- }
+ RegisterDataBase("default", DBARGS.Driver, DBARGS.Source, 20)
alias := getDbAlias("default")
if alias.Driver == DRMySQL {
diff --git a/client/orm/models_utils.go b/orm/models_utils.go
similarity index 93%
rename from client/orm/models_utils.go
rename to orm/models_utils.go
index 950ca243..71127a6b 100644
--- a/client/orm/models_utils.go
+++ b/orm/models_utils.go
@@ -45,7 +45,6 @@ var supportTag = map[string]int{
"on_delete": 2,
"type": 2,
"description": 2,
- "precision": 2,
}
// get reflect.Type name with package path.
@@ -107,18 +106,6 @@ func getTableUnique(val reflect.Value) [][]string {
return nil
}
-// get whether the table needs to be created for the database alias
-func isApplicableTableForDB(val reflect.Value, db string) bool {
- fun := val.MethodByName("IsApplicableTableForDB")
- if fun.IsValid() {
- vals := fun.Call([]reflect.Value{reflect.ValueOf(db)})
- if len(vals) > 0 && vals[0].Kind() == reflect.Bool {
- return vals[0].Bool()
- }
- }
- return true
-}
-
// get snaked column name
func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string {
column := col
diff --git a/client/orm/orm.go b/orm/orm.go
similarity index 57%
rename from client/orm/orm.go
rename to orm/orm.go
index a83faeb2..0551b1cd 100644
--- a/client/orm/orm.go
+++ b/orm/orm.go
@@ -21,7 +21,7 @@
//
// import (
// "fmt"
-// "github.com/astaxie/beego/client/orm"
+// "github.com/astaxie/beego/orm"
// _ "github.com/go-sql-driver/mysql" // import your used driver
// )
//
@@ -60,12 +60,8 @@ import (
"fmt"
"os"
"reflect"
+ "sync"
"time"
-
- "github.com/astaxie/beego/client/orm/hints"
- "github.com/astaxie/beego/core/utils"
-
- "github.com/astaxie/beego/core/logs"
)
// DebugQueries define the debug
@@ -80,14 +76,13 @@ var (
DefaultRowsLimit = -1
DefaultRelsDepth = 2
DefaultTimeLoc = time.Local
- ErrTxDone = errors.New(" transaction already done")
+ ErrTxHasBegan = errors.New(" transaction already begin")
+ ErrTxDone = errors.New(" transaction not begin")
ErrMultiRows = errors.New(" return multi rows")
ErrNoRows = errors.New(" no row found")
ErrStmtClosed = errors.New(" stmt already closed")
ErrArgs = errors.New(" args error may be empty")
ErrNotImplement = errors.New("have not implement")
-
- ErrLastInsertIdUnavailable = errors.New(" last insert id is unavailable")
)
// Params stores the Params
@@ -96,17 +91,16 @@ type Params map[string]interface{}
// ParamsList stores paramslist
type ParamsList []interface{}
-type ormBase struct {
+type orm struct {
alias *alias
db dbQuerier
+ isTx bool
}
-var _ DQL = new(ormBase)
-var _ DML = new(ormBase)
-var _ DriverGetter = new(ormBase)
+var _ Ormer = new(orm)
// get model info and model reflect value
-func (o *ormBase) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) {
+func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) {
val := reflect.ValueOf(md)
ind = reflect.Indirect(val)
typ := ind.Type()
@@ -121,7 +115,7 @@ func (o *ormBase) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind ref
}
// get field info from model info by given field name
-func (o *ormBase) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
+func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
fi, ok := mi.fields.GetByAny(name)
if !ok {
panic(fmt.Errorf(" cannot find field `%s` for model `%s`", name, mi.fullName))
@@ -130,42 +124,33 @@ func (o *ormBase) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
}
// read data to model
-func (o *ormBase) Read(md interface{}, cols ...string) error {
- return o.ReadWithCtx(context.Background(), md, cols...)
-}
-func (o *ormBase) ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error {
+func (o *orm) Read(md interface{}, cols ...string) error {
mi, ind := o.getMiInd(md, true)
return o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, false)
}
// read data to model, like Read(), but use "SELECT FOR UPDATE" form
-func (o *ormBase) ReadForUpdate(md interface{}, cols ...string) error {
- return o.ReadForUpdateWithCtx(context.Background(), md, cols...)
-}
-func (o *ormBase) ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error {
+func (o *orm) ReadForUpdate(md interface{}, cols ...string) error {
mi, ind := o.getMiInd(md, true)
return o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, true)
}
// Try to read a row from the database, or insert one if it doesn't exist
-func (o *ormBase) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
- return o.ReadOrCreateWithCtx(context.Background(), md, col1, cols...)
-}
-func (o *ormBase) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error) {
+func (o *orm) ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error) {
cols = append([]string{col1}, cols...)
mi, ind := o.getMiInd(md, true)
err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, false)
if err == ErrNoRows {
// Create
- id, err := o.InsertWithCtx(ctx, md)
- return err == nil, id, err
+ id, err := o.Insert(md)
+ return (err == nil), id, err
}
id, vid := int64(0), ind.FieldByIndex(mi.fields.pk.fieldIndex)
if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
id = int64(vid.Uint())
} else if mi.fields.pk.rel {
- return o.ReadOrCreateWithCtx(ctx, vid.Interface(), mi.fields.pk.relModelInfo.fields.pk.name)
+ return o.ReadOrCreate(vid.Interface(), mi.fields.pk.relModelInfo.fields.pk.name)
} else {
id = vid.Int()
}
@@ -174,10 +159,7 @@ func (o *ormBase) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1
}
// insert model data to database
-func (o *ormBase) Insert(md interface{}) (int64, error) {
- return o.InsertWithCtx(context.Background(), md)
-}
-func (o *ormBase) InsertWithCtx(ctx context.Context, md interface{}) (int64, error) {
+func (o *orm) Insert(md interface{}) (int64, error) {
mi, ind := o.getMiInd(md, true)
id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ)
if err != nil {
@@ -190,7 +172,7 @@ func (o *ormBase) InsertWithCtx(ctx context.Context, md interface{}) (int64, err
}
// set auto pk field
-func (o *ormBase) setPk(mi *modelInfo, ind reflect.Value, id int64) {
+func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) {
if mi.fields.pk.auto {
if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(uint64(id))
@@ -201,10 +183,7 @@ func (o *ormBase) setPk(mi *modelInfo, ind reflect.Value, id int64) {
}
// insert some models to database
-func (o *ormBase) InsertMulti(bulk int, mds interface{}) (int64, error) {
- return o.InsertMultiWithCtx(context.Background(), bulk, mds)
-}
-func (o *ormBase) InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error) {
+func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) {
var cnt int64
sind := reflect.Indirect(reflect.ValueOf(mds))
@@ -239,10 +218,7 @@ func (o *ormBase) InsertMultiWithCtx(ctx context.Context, bulk int, mds interfac
}
// InsertOrUpdate data to database
-func (o *ormBase) InsertOrUpdate(md interface{}, colConflictAndArgs ...string) (int64, error) {
- return o.InsertOrUpdateWithCtx(context.Background(), md, colConflictAndArgs...)
-}
-func (o *ormBase) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error) {
+func (o *orm) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error) {
mi, ind := o.getMiInd(md, true)
id, err := o.alias.DbBaser.InsertOrUpdate(o.db, mi, ind, o.alias, colConflitAndArgs...)
if err != nil {
@@ -256,20 +232,14 @@ func (o *ormBase) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, col
// update model to database.
// cols set the columns those want to update.
-func (o *ormBase) Update(md interface{}, cols ...string) (int64, error) {
- return o.UpdateWithCtx(context.Background(), md, cols...)
-}
-func (o *ormBase) UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
+func (o *orm) Update(md interface{}, cols ...string) (int64, error) {
mi, ind := o.getMiInd(md, true)
return o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols)
}
// delete model in database
// cols shows the delete conditions values read from. default is pk
-func (o *ormBase) Delete(md interface{}, cols ...string) (int64, error) {
- return o.DeleteWithCtx(context.Background(), md, cols...)
-}
-func (o *ormBase) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
+func (o *orm) Delete(md interface{}, cols ...string) (int64, error) {
mi, ind := o.getMiInd(md, true)
num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ, cols)
if err != nil {
@@ -282,10 +252,7 @@ func (o *ormBase) DeleteWithCtx(ctx context.Context, md interface{}, cols ...str
}
// create a models to models queryer
-func (o *ormBase) QueryM2M(md interface{}, name string) QueryM2Mer {
- return o.QueryM2MWithCtx(context.Background(), md, name)
-}
-func (o *ormBase) QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer {
+func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer {
mi, ind := o.getMiInd(md, true)
fi := o.getFieldInfo(mi, name)
@@ -307,38 +274,32 @@ func (o *ormBase) QueryM2MWithCtx(ctx context.Context, md interface{}, name stri
// for _,tag := range post.Tags{...}
//
// make sure the relation is defined in model struct tags.
-func (o *ormBase) LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error) {
- return o.LoadRelatedWithCtx(context.Background(), md, name, args...)
-}
-func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error) {
- _, fi, ind, qs := o.queryRelated(md, name)
+func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) {
+ _, fi, ind, qseter := o.queryRelated(md, name)
+
+ qs := qseter.(*querySet)
var relDepth int
var limit, offset int64
var order string
-
- kvs := utils.NewKVs(args...)
- kvs.IfContains(hints.KeyRelDepth, func(value interface{}) {
- if v, ok := value.(bool); ok {
- if v {
- relDepth = DefaultRelsDepth
+ for i, arg := range args {
+ switch i {
+ case 0:
+ if v, ok := arg.(bool); ok {
+ if v {
+ relDepth = DefaultRelsDepth
+ }
+ } else if v, ok := arg.(int); ok {
+ relDepth = v
}
- } else if v, ok := value.(int); ok {
- relDepth = v
+ case 1:
+ limit = ToInt64(arg)
+ case 2:
+ offset = ToInt64(arg)
+ case 3:
+ order, _ = arg.(string)
}
- }).IfContains(hints.KeyLimit, func(value interface{}) {
- if v, ok := value.(int64); ok {
- limit = v
- }
- }).IfContains(hints.KeyOffset, func(value interface{}) {
- if v, ok := value.(int64); ok {
- offset = v
- }
- }).IfContains(hints.KeyOrderBy, func(value interface{}) {
- if v, ok := value.(string); ok {
- order = v
- }
- })
+ }
switch fi.fieldType {
case RelOneToOne, RelForeignKey, RelReverseOne:
@@ -374,8 +335,20 @@ func (o *ormBase) LoadRelatedWithCtx(ctx context.Context, md interface{}, name s
return nums, err
}
+// return a QuerySeter for related models to md model.
+// it can do all, update, delete in QuerySeter.
+// example:
+// qs := orm.QueryRelated(post,"Tag")
+// qs.All(&[]*Tag{})
+//
+func (o *orm) QueryRelated(md interface{}, name string) QuerySeter {
+ // is this api needed ?
+ _, _, _, qs := o.queryRelated(md, name)
+ return qs
+}
+
// get QuerySeter for related models to md model
-func (o *ormBase) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, *querySet) {
+func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) {
mi, ind := o.getMiInd(md, true)
fi := o.getFieldInfo(mi, name)
@@ -407,7 +380,7 @@ func (o *ormBase) queryRelated(md interface{}, name string) (*modelInfo, *fieldI
}
// get reverse relation QuerySeter
-func (o *ormBase) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
+func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
switch fi.fieldType {
case RelReverseOne, RelReverseMany:
default:
@@ -428,7 +401,7 @@ func (o *ormBase) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *qu
}
// get relation QuerySeter
-func (o *ormBase) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
+func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
switch fi.fieldType {
case RelOneToOne, RelForeignKey, RelManyToMany:
default:
@@ -450,10 +423,7 @@ func (o *ormBase) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS
// return a QuerySeter for table operations.
// table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
-func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
- return o.QueryTableWithCtx(context.Background(), ptrStructOrTableName)
-}
-func (o *ormBase) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) (qs QuerySeter) {
+func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
var name string
if table, ok := ptrStructOrTableName.(string); ok {
name = nameStrategyMap[defaultNameStrategy](table)
@@ -472,21 +442,89 @@ func (o *ormBase) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName in
return
}
-// return a raw query seter for raw sql string.
-func (o *ormBase) Raw(query string, args ...interface{}) RawSeter {
- return o.RawWithCtx(context.Background(), query, args...)
+// switch to another registered database driver by given name.
+func (o *orm) Using(name string) error {
+ if o.isTx {
+ panic(fmt.Errorf(" transaction has been start, cannot change db"))
+ }
+ if al, ok := dataBaseCache.get(name); ok {
+ o.alias = al
+ if Debug {
+ o.db = newDbQueryLog(al, al.DB)
+ } else {
+ o.db = al.DB
+ }
+ } else {
+ return fmt.Errorf(" unknown db alias name `%s`", name)
+ }
+ return nil
}
-func (o *ormBase) RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter {
+
+// begin transaction
+func (o *orm) Begin() error {
+ return o.BeginTx(context.Background(), nil)
+}
+
+func (o *orm) BeginTx(ctx context.Context, opts *sql.TxOptions) error {
+ if o.isTx {
+ return ErrTxHasBegan
+ }
+ var tx *sql.Tx
+ tx, err := o.db.(txer).BeginTx(ctx, opts)
+ if err != nil {
+ return err
+ }
+ o.isTx = true
+ if Debug {
+ o.db.(*dbQueryLog).SetDB(tx)
+ } else {
+ o.db = tx
+ }
+ return nil
+}
+
+// commit transaction
+func (o *orm) Commit() error {
+ if !o.isTx {
+ return ErrTxDone
+ }
+ err := o.db.(txEnder).Commit()
+ if err == nil {
+ o.isTx = false
+ o.Using(o.alias.Name)
+ } else if err == sql.ErrTxDone {
+ return ErrTxDone
+ }
+ return err
+}
+
+// rollback transaction
+func (o *orm) Rollback() error {
+ if !o.isTx {
+ return ErrTxDone
+ }
+ err := o.db.(txEnder).Rollback()
+ if err == nil {
+ o.isTx = false
+ o.Using(o.alias.Name)
+ } else if err == sql.ErrTxDone {
+ return ErrTxDone
+ }
+ return err
+}
+
+// return a raw query seter for raw sql string.
+func (o *orm) Raw(query string, args ...interface{}) RawSeter {
return newRawSet(o, query, args)
}
// return current using database Driver
-func (o *ormBase) Driver() Driver {
+func (o *orm) Driver() Driver {
return driver(o.alias.Name)
}
// return sql.DBStats for current database
-func (o *ormBase) DBStats() *sql.DBStats {
+func (o *orm) DBStats() *sql.DBStats {
if o.alias != nil && o.alias.DB != nil {
stats := o.alias.DB.DB.Stats()
return &stats
@@ -494,134 +532,48 @@ func (o *ormBase) DBStats() *sql.DBStats {
return nil
}
-type orm struct {
- ormBase
-}
-
-var _ Ormer = new(orm)
-
-func (o *orm) Begin() (TxOrmer, error) {
- return o.BeginWithCtx(context.Background())
-}
-
-func (o *orm) BeginWithCtx(ctx context.Context) (TxOrmer, error) {
- return o.BeginWithCtxAndOpts(ctx, nil)
-}
-
-func (o *orm) BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error) {
- return o.BeginWithCtxAndOpts(context.Background(), opts)
-}
-
-func (o *orm) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error) {
- tx, err := o.db.(txer).BeginTx(ctx, opts)
- if err != nil {
- return nil, err
- }
-
- _txOrm := &txOrm{
- ormBase: ormBase{
- alias: o.alias,
- db: &TxDB{tx: tx},
- },
- }
-
- var taskTxOrm TxOrmer = _txOrm
- return taskTxOrm, nil
-}
-
-func (o *orm) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
- return o.DoTxWithCtx(context.Background(), task)
-}
-
-func (o *orm) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
- return o.DoTxWithCtxAndOpts(ctx, nil, task)
-}
-
-func (o *orm) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
- return o.DoTxWithCtxAndOpts(context.Background(), opts, task)
-}
-
-func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
- return doTxTemplate(o, ctx, opts, task)
-}
-
-func doTxTemplate(o TxBeginner, ctx context.Context, opts *sql.TxOptions,
- task func(ctx context.Context, txOrm TxOrmer) error) error {
- _txOrm, err := o.BeginWithCtxAndOpts(ctx, opts)
- if err != nil {
- return err
- }
- panicked := true
- defer func() {
- if panicked || err != nil {
- e := _txOrm.Rollback()
- if e != nil {
- logs.Error("rollback transaction failed: %v,%v", e, panicked)
- }
- } else {
- e := _txOrm.Commit()
- if e != nil {
- logs.Error("commit transaction failed: %v,%v", e, panicked)
- }
- }
- }()
- var taskTxOrm = _txOrm
- err = task(ctx, taskTxOrm)
- panicked = false
- return err
-}
-
-type txOrm struct {
- ormBase
-}
-
-var _ TxOrmer = new(txOrm)
-
-func (t *txOrm) Commit() error {
- return t.db.(txEnder).Commit()
-}
-
-func (t *txOrm) Rollback() error {
- return t.db.(txEnder).Rollback()
-}
-
// NewOrm create new orm
func NewOrm() Ormer {
BootStrap() // execute only once
- return NewOrmUsingDB(`default`)
-}
-// NewOrmUsingDB create new orm with the name
-func NewOrmUsingDB(aliasName string) Ormer {
- if al, ok := dataBaseCache.get(aliasName); ok {
- return newDBWithAlias(al)
- } else {
- panic(fmt.Errorf(" unknown db alias name `%s`", aliasName))
+ o := new(orm)
+ err := o.Using("default")
+ if err != nil {
+ panic(err)
}
+ return o
}
// NewOrmWithDB create a new ormer object with specify *sql.DB for query
-func NewOrmWithDB(driverName, aliasName string, db *sql.DB, params ...DBOption) (Ormer, error) {
- al, err := newAliasWithDb(aliasName, driverName, db, params...)
- if err != nil {
- return nil, err
+func NewOrmWithDB(driverName, aliasName string, db *sql.DB) (Ormer, error) {
+ var al *alias
+
+ if dr, ok := drivers[driverName]; ok {
+ al = new(alias)
+ al.DbBaser = dbBasers[dr]
+ al.Driver = dr
+ } else {
+ return nil, fmt.Errorf("driver name `%s` have not registered", driverName)
}
- return newDBWithAlias(al), nil
-}
+ al.Name = aliasName
+ al.DriverName = driverName
+ al.DB = &DB{
+ RWMutex: new(sync.RWMutex),
+ DB: db,
+ stmtDecorators: newStmtDecoratorLruWithEvict(),
+ }
+
+ detectTZ(al)
-func newDBWithAlias(al *alias) Ormer {
o := new(orm)
o.alias = al
if Debug {
- o.db = newDbQueryLog(al, al.DB)
+ o.db = newDbQueryLog(o.alias, db)
} else {
- o.db = al.DB
+ o.db = db
}
- if len(globalFilterChains) > 0 {
- return NewFilterOrmDecorator(o, globalFilterChains...)
- }
- return o
+ return o, nil
}
diff --git a/client/orm/orm_conds.go b/orm/orm_conds.go
similarity index 100%
rename from client/orm/orm_conds.go
rename to orm/orm_conds.go
diff --git a/client/orm/orm_log.go b/orm/orm_log.go
similarity index 88%
rename from client/orm/orm_log.go
rename to orm/orm_log.go
index d8df7e36..f107bb59 100644
--- a/client/orm/orm_log.go
+++ b/orm/orm_log.go
@@ -61,7 +61,7 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error
con += " - " + err.Error()
}
logMap["sql"] = fmt.Sprintf("%s-`%s`", query, strings.Join(cons, "`, `"))
- if LogFunc != nil {
+ if LogFunc != nil{
LogFunc(logMap)
}
DebugLog.Println(con)
@@ -127,7 +127,10 @@ var _ txer = new(dbQueryLog)
var _ txEnder = new(dbQueryLog)
func (d *dbQueryLog) Prepare(query string) (*sql.Stmt, error) {
- return d.PrepareContext(context.Background(), query)
+ a := time.Now()
+ stmt, err := d.db.Prepare(query)
+ debugLogQueies(d.alias, "db.Prepare", query, a, err)
+ return stmt, err
}
func (d *dbQueryLog) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) {
@@ -138,7 +141,10 @@ func (d *dbQueryLog) PrepareContext(ctx context.Context, query string) (*sql.Stm
}
func (d *dbQueryLog) Exec(query string, args ...interface{}) (sql.Result, error) {
- return d.ExecContext(context.Background(), query, args...)
+ a := time.Now()
+ res, err := d.db.Exec(query, args...)
+ debugLogQueies(d.alias, "db.Exec", query, a, err, args...)
+ return res, err
}
func (d *dbQueryLog) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
@@ -149,7 +155,10 @@ func (d *dbQueryLog) ExecContext(ctx context.Context, query string, args ...inte
}
func (d *dbQueryLog) Query(query string, args ...interface{}) (*sql.Rows, error) {
- return d.QueryContext(context.Background(), query, args...)
+ a := time.Now()
+ res, err := d.db.Query(query, args...)
+ debugLogQueies(d.alias, "db.Query", query, a, err, args...)
+ return res, err
}
func (d *dbQueryLog) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
@@ -160,7 +169,10 @@ func (d *dbQueryLog) QueryContext(ctx context.Context, query string, args ...int
}
func (d *dbQueryLog) QueryRow(query string, args ...interface{}) *sql.Row {
- return d.QueryRowContext(context.Background(), query, args...)
+ a := time.Now()
+ res := d.db.QueryRow(query, args...)
+ debugLogQueies(d.alias, "db.QueryRow", query, a, nil, args...)
+ return res
}
func (d *dbQueryLog) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
@@ -171,7 +183,10 @@ func (d *dbQueryLog) QueryRowContext(ctx context.Context, query string, args ...
}
func (d *dbQueryLog) Begin() (*sql.Tx, error) {
- return d.BeginTx(context.Background(), nil)
+ a := time.Now()
+ tx, err := d.db.(txer).Begin()
+ debugLogQueies(d.alias, "db.Begin", "START TRANSACTION", a, err)
+ return tx, err
}
func (d *dbQueryLog) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error) {
diff --git a/client/orm/orm_object.go b/orm/orm_object.go
similarity index 96%
rename from client/orm/orm_object.go
rename to orm/orm_object.go
index 6f9798d3..de3181ce 100644
--- a/client/orm/orm_object.go
+++ b/orm/orm_object.go
@@ -22,7 +22,7 @@ import (
// an insert queryer struct
type insertSet struct {
mi *modelInfo
- orm *ormBase
+ orm *orm
stmt stmtQuerier
closed bool
}
@@ -70,7 +70,7 @@ func (o *insertSet) Close() error {
}
// create new insert queryer.
-func newInsertSet(orm *ormBase, mi *modelInfo) (Inserter, error) {
+func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) {
bi := new(insertSet)
bi.orm = orm
bi.mi = mi
diff --git a/client/orm/orm_querym2m.go b/orm/orm_querym2m.go
similarity index 97%
rename from client/orm/orm_querym2m.go
rename to orm/orm_querym2m.go
index 17e1b5d1..6a270a0d 100644
--- a/client/orm/orm_querym2m.go
+++ b/orm/orm_querym2m.go
@@ -129,7 +129,7 @@ func (o *queryM2M) Count() (int64, error) {
var _ QueryM2Mer = new(queryM2M)
// create new M2M queryer.
-func newQueryM2M(md interface{}, o *ormBase, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer {
+func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer {
qm2m := new(queryM2M)
qm2m.md = md
qm2m.mi = mi
diff --git a/client/orm/orm_queryset.go b/orm/orm_queryset.go
similarity index 91%
rename from client/orm/orm_queryset.go
rename to orm/orm_queryset.go
index ed223e24..878b836b 100644
--- a/client/orm/orm_queryset.go
+++ b/orm/orm_queryset.go
@@ -17,8 +17,6 @@ package orm
import (
"context"
"fmt"
-
- "github.com/astaxie/beego/client/orm/hints"
)
type colValue struct {
@@ -73,10 +71,8 @@ type querySet struct {
groups []string
orders []string
distinct bool
- forUpdate bool
- useIndex int
- indexes []string
- orm *ormBase
+ forupdate bool
+ orm *orm
ctx context.Context
forContext bool
}
@@ -152,28 +148,7 @@ func (o querySet) Distinct() QuerySeter {
// add FOR UPDATE to SELECT
func (o querySet) ForUpdate() QuerySeter {
- o.forUpdate = true
- return &o
-}
-
-// ForceIndex force index for query
-func (o querySet) ForceIndex(indexes ...string) QuerySeter {
- o.useIndex = hints.KeyForceIndex
- o.indexes = indexes
- return &o
-}
-
-// UseIndex use index for query
-func (o querySet) UseIndex(indexes ...string) QuerySeter {
- o.useIndex = hints.KeyUseIndex
- o.indexes = indexes
- return &o
-}
-
-// IgnoreIndex ignore index for query
-func (o querySet) IgnoreIndex(indexes ...string) QuerySeter {
- o.useIndex = hints.KeyIgnoreIndex
- o.indexes = indexes
+ o.forupdate = true
return &o
}
@@ -317,7 +292,7 @@ func (o querySet) WithContext(ctx context.Context) QuerySeter {
}
// create new QuerySeter.
-func newQuerySet(orm *ormBase, mi *modelInfo) QuerySeter {
+func newQuerySet(orm *orm, mi *modelInfo) QuerySeter {
o := new(querySet)
o.mi = mi
o.orm = orm
diff --git a/client/orm/orm_raw.go b/orm/orm_raw.go
similarity index 91%
rename from client/orm/orm_raw.go
rename to orm/orm_raw.go
index e11e97fa..3325a7ea 100644
--- a/client/orm/orm_raw.go
+++ b/orm/orm_raw.go
@@ -19,8 +19,6 @@ import (
"fmt"
"reflect"
"time"
-
- "github.com/pkg/errors"
)
// raw sql string prepared statement
@@ -34,8 +32,7 @@ func (o *rawPrepare) Exec(args ...interface{}) (sql.Result, error) {
if o.closed {
return nil, ErrStmtClosed
}
- flatParams := getFlatParams(nil, args, o.rs.orm.alias.TZ)
- return o.stmt.Exec(flatParams...)
+ return o.stmt.Exec(args...)
}
func (o *rawPrepare) Close() error {
@@ -66,7 +63,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) {
type rawSet struct {
query string
args []interface{}
- orm *ormBase
+ orm *orm
}
var _ RawSeter = new(rawSet)
@@ -330,8 +327,6 @@ func (o *rawSet) QueryRow(containers ...interface{}) error {
return err
}
- structTagMap := make(map[reflect.StructTag]map[string]string)
-
defer rows.Close()
if rows.Next() {
@@ -373,50 +368,23 @@ func (o *rawSet) QueryRow(containers ...interface{}) error {
field.Set(mf)
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
}
- if fi.isFielder {
- fd := field.Addr().Interface().(Fielder)
- err := fd.SetRaw(value)
- if err != nil {
- return errors.Errorf("set raw error:%s", err)
- }
- } else {
- o.setFieldValue(field, value)
- }
+ o.setFieldValue(field, value)
}
}
} else {
- // define recursive function
- var recursiveSetField func(rv reflect.Value)
- recursiveSetField = func(rv reflect.Value) {
- for i := 0; i < rv.NumField(); i++ {
- f := rv.Field(i)
- fe := rv.Type().Field(i)
-
- // check if the field is a Struct
- // recursive the Struct type
- if fe.Type.Kind() == reflect.Struct {
- recursiveSetField(f)
- }
-
- // thanks @Gazeboxu.
- tags := structTagMap[fe.Tag]
- if tags == nil {
- _, tags = parseStructTag(fe.Tag.Get(defaultStructTagName))
- structTagMap[fe.Tag] = tags
- }
- var col string
- if col = tags["column"]; col == "" {
- col = nameStrategyMap[nameStrategy](fe.Name)
- }
- if v, ok := columnsMp[col]; ok {
- value := reflect.ValueOf(v).Elem().Interface()
- o.setFieldValue(f, value)
- }
+ for i := 0; i < ind.NumField(); i++ {
+ f := ind.Field(i)
+ fe := ind.Type().Field(i)
+ _, tags := parseStructTag(fe.Tag.Get(defaultStructTagName))
+ var col string
+ if col = tags["column"]; col == "" {
+ col = nameStrategyMap[nameStrategy](fe.Name)
+ }
+ if v, ok := columnsMp[col]; ok {
+ value := reflect.ValueOf(v).Elem().Interface()
+ o.setFieldValue(f, value)
}
}
-
- // init call the recursive function
- recursiveSetField(ind)
}
} else {
@@ -541,15 +509,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
field.Set(mf)
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
}
- if fi.isFielder {
- fd := field.Addr().Interface().(Fielder)
- err := fd.SetRaw(value)
- if err != nil {
- return 0, errors.Errorf("set raw error:%s", err)
- }
- } else {
- o.setFieldValue(field, value)
- }
+ o.setFieldValue(field, value)
}
}
} else {
@@ -898,7 +858,7 @@ func (o *rawSet) Prepare() (RawPreparer, error) {
return newRawPreparer(o)
}
-func newRawSet(orm *ormBase, query string, args []interface{}) RawSeter {
+func newRawSet(orm *orm, query string, args []interface{}) RawSeter {
o := new(rawSet)
o.query = query
o.args = args
diff --git a/client/orm/orm_test.go b/orm/orm_test.go
similarity index 89%
rename from client/orm/orm_test.go
rename to orm/orm_test.go
index 565f6c60..bdb430b6 100644
--- a/client/orm/orm_test.go
+++ b/orm/orm_test.go
@@ -30,10 +30,6 @@ import (
"strings"
"testing"
"time"
-
- "github.com/astaxie/beego/client/orm/hints"
-
- "github.com/stretchr/testify/assert"
)
var _ = os.PathSeparator
@@ -145,7 +141,6 @@ func getCaller(skip int) string {
return fmt.Sprintf("%s:%s:%d: \n%s", fn, funName, line, strings.Join(codes, "\n"))
}
-// Deprecated: Using stretchr/testify/assert
func throwFail(t *testing.T, err error, args ...interface{}) {
if err != nil {
con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2))
@@ -202,9 +197,6 @@ func TestSyncDb(t *testing.T) {
RegisterModel(new(IntegerPk))
RegisterModel(new(UintPk))
RegisterModel(new(PtrPk))
- RegisterModel(new(Index))
- RegisterModel(new(StrPk))
- RegisterModel(new(TM))
err := RunSyncdb("default", true, Debug)
throwFail(t, err)
@@ -229,9 +221,6 @@ func TestRegisterModels(t *testing.T) {
RegisterModel(new(IntegerPk))
RegisterModel(new(UintPk))
RegisterModel(new(PtrPk))
- RegisterModel(new(Index))
- RegisterModel(new(StrPk))
- RegisterModel(new(TM))
BootStrap()
@@ -305,34 +294,19 @@ func TestDataTypes(t *testing.T) {
vu := e.Interface()
switch name {
case "Date":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
case "DateTime":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
case "Time":
- assert.True(t, vu.(time.Time).In(DefaultTimeLoc).Sub(value.(time.Time).In(DefaultTimeLoc)) <= time.Second)
- break
- default:
- assert.Equal(t, value, vu)
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
}
+ throwFail(t, AssertIs(vu == value, true), value, vu)
}
}
-func TestTM(t *testing.T) {
- // The precision of sqlite is not implemented
- if dORM.Driver().Type() == 2 {
- return
- }
- var recTM TM
- tm := NewTM()
- tm.TMPrecision1 = time.Unix(1596766024, 123456789)
- tm.TMPrecision2 = time.Unix(1596766024, 123456789)
- _, err := dORM.Insert(tm)
- throwFail(t, err)
-
- err = dORM.QueryTable("tm").One(&recTM)
- throwFail(t, err)
- throwFail(t, AssertIs(recTM.TMPrecision1.String(), "2020-08-07 02:07:04.123 +0000 UTC"))
- throwFail(t, AssertIs(recTM.TMPrecision2.String(), "2020-08-07 02:07:04.1235 +0000 UTC"))
-}
-
func TestNullDataTypes(t *testing.T) {
d := DataNull{}
@@ -481,11 +455,9 @@ func TestNullDataTypes(t *testing.T) {
throwFail(t, AssertIs(*d.Float32Ptr, float32Ptr))
throwFail(t, AssertIs(*d.Float64Ptr, float64Ptr))
throwFail(t, AssertIs(*d.DecimalPtr, decimalPtr))
-
- // in mysql, there are some precision problem, (*d.TimePtr).UTC() != timePtr.UTC()
- assert.True(t, (*d.TimePtr).UTC().Sub(timePtr.UTC()) <= time.Second)
- assert.True(t, (*d.DatePtr).UTC().Sub(datePtr.UTC()) <= time.Second)
- assert.True(t, (*d.DateTimePtr).UTC().Sub(dateTimePtr.UTC()) <= time.Second)
+ 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
@@ -560,9 +532,8 @@ func TestCRUD(t *testing.T) {
throwFail(t, AssertIs(u.Status, 3))
throwFail(t, AssertIs(u.IsStaff, true))
throwFail(t, AssertIs(u.IsActive, true))
-
- assert.True(t, u.Created.In(DefaultTimeLoc).Sub(user.Created.In(DefaultTimeLoc)) <= time.Second)
- assert.True(t, u.Updated.In(DefaultTimeLoc).Sub(user.Updated.In(DefaultTimeLoc)) <= time.Second)
+ throwFail(t, AssertIs(u.Created.In(DefaultTimeLoc), user.Created.In(DefaultTimeLoc), testDate))
+ throwFail(t, AssertIs(u.Updated.In(DefaultTimeLoc), user.Updated.In(DefaultTimeLoc), testDateTime))
user.UserName = "astaxie"
user.Profile = profile
@@ -798,20 +769,6 @@ func TestCustomField(t *testing.T) {
throwFailNow(t, AssertIs(user.Extra.Name, "beego"))
throwFailNow(t, AssertIs(user.Extra.Data, "orm"))
-
- var users []User
- Q := dDbBaser.TableQuote()
- n, err := dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRows(&users)
- throwFailNow(t, err)
- throwFailNow(t, AssertIs(n, 1))
- throwFailNow(t, AssertIs(users[0].Extra.Name, "beego"))
- throwFailNow(t, AssertIs(users[0].Extra.Data, "orm"))
-
- user = User{}
- err = dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRow(&user)
- throwFailNow(t, err)
- throwFailNow(t, AssertIs(user.Extra.Name, "beego"))
- throwFailNow(t, AssertIs(user.Extra.Data, "orm"))
}
func TestExpr(t *testing.T) {
@@ -833,32 +790,6 @@ func TestExpr(t *testing.T) {
// throwFail(t, AssertIs(num, 3))
}
-func TestSpecifyIndex(t *testing.T) {
- var index *Index
- index = &Index{
- F1: 1,
- F2: 2,
- }
- _, _ = dORM.Insert(index)
- throwFailNow(t, AssertIs(index.Id, 1))
-
- index = &Index{
- F1: 3,
- F2: 4,
- }
- _, _ = dORM.Insert(index)
- throwFailNow(t, AssertIs(index.Id, 2))
-
- _ = dORM.QueryTable(&Index{}).Filter(`f1`, `1`).ForceIndex(`index_f1`).One(index)
- throwFailNow(t, AssertIs(index.F2, 2))
-
- _ = dORM.QueryTable(&Index{}).Filter(`f2`, `4`).UseIndex(`index_f2`).One(index)
- throwFailNow(t, AssertIs(index.F1, 3))
-
- _ = dORM.QueryTable(&Index{}).Filter(`f1`, `1`).IgnoreIndex(`index_f1`, `index_f2`).One(index)
- throwFailNow(t, AssertIs(index.F2, 2))
-}
-
func TestOperators(t *testing.T) {
qs := dORM.QueryTable("user")
num, err := qs.Filter("user_name", "slene").Count()
@@ -877,17 +808,6 @@ func TestOperators(t *testing.T) {
throwFail(t, err)
throwFail(t, AssertIs(num, 1))
- if IsMysql {
- // Now only mysql support `strictexact`
- num, err = qs.Filter("user_name__strictexact", "Slene").Count()
- throwFail(t, err)
- throwFail(t, AssertIs(num, 0))
-
- num, err = qs.Filter("user_name__strictexact", "slene").Count()
- throwFail(t, err)
- throwFail(t, AssertIs(num, 1))
- }
-
num, err = qs.Filter("user_name__contains", "e").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 2))
@@ -1356,32 +1276,24 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(len(user.Posts), 2))
throwFailNow(t, AssertIs(user.Posts[0].User.ID, 3))
- num, err = dORM.LoadRelated(&user, "Posts", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&user, "Posts", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 2))
throwFailNow(t, AssertIs(len(user.Posts), 2))
throwFailNow(t, AssertIs(user.Posts[0].User.UserName, "astaxie"))
- num, err = dORM.LoadRelated(&user, "Posts",
- hints.DefaultRelDepth(),
- hints.Limit(1))
+ num, err = dORM.LoadRelated(&user, "Posts", true, 1)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(len(user.Posts), 1))
- num, err = dORM.LoadRelated(&user, "Posts",
- hints.DefaultRelDepth(),
- hints.OrderBy("-Id"))
+ num, err = dORM.LoadRelated(&user, "Posts", true, 0, 0, "-Id")
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 2))
throwFailNow(t, AssertIs(len(user.Posts), 2))
throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting"))
- num, err = dORM.LoadRelated(&user, "Posts",
- hints.DefaultRelDepth(),
- hints.Limit(1),
- hints.Offset(1),
- hints.OrderBy("Id"))
+ num, err = dORM.LoadRelated(&user, "Posts", true, 1, 1, "Id")
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(len(user.Posts), 1))
@@ -1403,7 +1315,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(profile.User == nil, false))
throwFailNow(t, AssertIs(profile.User.UserName, "astaxie"))
- num, err = dORM.LoadRelated(&profile, "User", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&profile, "User", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(profile.User == nil, false))
@@ -1420,7 +1332,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(user.Profile == nil, false))
throwFailNow(t, AssertIs(user.Profile.Age, 30))
- num, err = dORM.LoadRelated(&user, "Profile", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&user, "Profile", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(user.Profile == nil, false))
@@ -1440,7 +1352,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(post.User == nil, false))
throwFailNow(t, AssertIs(post.User.UserName, "astaxie"))
- num, err = dORM.LoadRelated(&post, "User", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&post, "User", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(post.User == nil, false))
@@ -1460,7 +1372,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(len(post.Tags), 2))
throwFailNow(t, AssertIs(post.Tags[0].Name, "golang"))
- num, err = dORM.LoadRelated(&post, "Tags", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&post, "Tags", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 2))
throwFailNow(t, AssertIs(len(post.Tags), 2))
@@ -1481,7 +1393,7 @@ func TestLoadRelated(t *testing.T) {
throwFailNow(t, AssertIs(tag.Posts[0].User.ID, 2))
throwFailNow(t, AssertIs(tag.Posts[0].User.Profile == nil, true))
- num, err = dORM.LoadRelated(&tag, "Posts", hints.DefaultRelDepth())
+ num, err = dORM.LoadRelated(&tag, "Posts", true)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 3))
throwFailNow(t, AssertIs(tag.Posts[0].Title, "Introduction"))
@@ -1744,14 +1656,18 @@ func TestRawQueryRow(t *testing.T) {
switch col {
case "id":
throwFail(t, AssertIs(id, 1))
- break
case "time":
+ v = v.(time.Time).In(DefaultTimeLoc)
+ value := dataValues[col].(time.Time).In(DefaultTimeLoc)
+ throwFail(t, AssertIs(v, value, testTime))
case "date":
+ v = v.(time.Time).In(DefaultTimeLoc)
+ value := dataValues[col].(time.Time).In(DefaultTimeLoc)
+ throwFail(t, AssertIs(v, value, testDate))
case "datetime":
v = v.(time.Time).In(DefaultTimeLoc)
value := dataValues[col].(time.Time).In(DefaultTimeLoc)
- assert.True(t, v.(time.Time).Sub(value) <= time.Second)
- break
+ throwFail(t, AssertIs(v, value, testDateTime))
default:
throwFail(t, AssertIs(v, dataValues[col]))
}
@@ -1773,24 +1689,6 @@ func TestRawQueryRow(t *testing.T) {
throwFail(t, AssertIs(*status, 3))
throwFail(t, AssertIs(pid, nil))
- type Embeded struct {
- Email string
- }
- type queryRowNoModelTest struct {
- Id int
- EmbedField Embeded
- }
-
- cols = []string{
- "id", "email",
- }
- var row queryRowNoModelTest
- query = fmt.Sprintf("SELECT %s%s%s FROM %suser%s WHERE id = ?", Q, strings.Join(cols, sep), Q, Q, Q)
- err = dORM.Raw(query, 4).QueryRow(&row)
- throwFail(t, err)
- throwFail(t, AssertIs(row.Id, 4))
- throwFail(t, AssertIs(row.EmbedField.Email, "nobody@gmail.com"))
-
// test for sql.Null* fields
nData := &DataNull{
NullString: sql.NullString{String: "test sql.null", Valid: true},
@@ -1842,13 +1740,16 @@ func TestQueryRows(t *testing.T) {
vu := e.Interface()
switch name {
case "Time":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
case "Date":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
case "DateTime":
- assert.True(t, vu.(time.Time).In(DefaultTimeLoc).Sub(value.(time.Time).In(DefaultTimeLoc)) <= time.Second)
- break
- default:
- assert.Equal(t, value, vu)
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
}
+ throwFail(t, AssertIs(vu == value, true), value, vu)
}
var datas2 []Data
@@ -1866,14 +1767,16 @@ func TestQueryRows(t *testing.T) {
vu := e.Interface()
switch name {
case "Time":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testTime)
case "Date":
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDate)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDate)
case "DateTime":
- assert.True(t, vu.(time.Time).In(DefaultTimeLoc).Sub(value.(time.Time).In(DefaultTimeLoc)) <= time.Second)
- break
- default:
- assert.Equal(t, value, vu)
+ vu = vu.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
+ value = value.(time.Time).In(DefaultTimeLoc).Format(testDateTime)
}
-
+ throwFail(t, AssertIs(vu == value, true), value, vu)
}
var ids []int
@@ -1890,7 +1793,7 @@ func TestQueryRows(t *testing.T) {
throwFailNow(t, AssertIs(ids[2], 4))
throwFailNow(t, AssertIs(usernames[2], "nobody"))
- // test query rows by nested struct
+ //test query rows by nested struct
var l []userProfile
query = fmt.Sprintf("SELECT * FROM %suser_profile%s LEFT JOIN %suser%s ON %suser_profile%s.%sid%s = %suser%s.%sid%s", Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q)
num, err = dORM.Raw(query).QueryRows(&l)
@@ -2117,24 +2020,24 @@ func TestTransaction(t *testing.T) {
// this test worked when database support transaction
o := NewOrm()
- to, err := o.Begin()
+ err := o.Begin()
throwFail(t, err)
var names = []string{"1", "2", "3"}
var tag Tag
tag.Name = names[0]
- id, err := to.Insert(&tag)
+ id, err := o.Insert(&tag)
throwFail(t, err)
throwFail(t, AssertIs(id > 0, true))
- num, err := to.QueryTable("tag").Filter("name", "golang").Update(Params{"name": names[1]})
+ num, err := o.QueryTable("tag").Filter("name", "golang").Update(Params{"name": names[1]})
throwFail(t, err)
throwFail(t, AssertIs(num, 1))
switch {
case IsMysql || IsSqlite:
- res, err := to.Raw("INSERT INTO tag (name) VALUES (?)", names[2]).Exec()
+ res, err := o.Raw("INSERT INTO tag (name) VALUES (?)", names[2]).Exec()
throwFail(t, err)
if err == nil {
id, err = res.LastInsertId()
@@ -2143,22 +2046,22 @@ func TestTransaction(t *testing.T) {
}
}
- err = to.Rollback()
+ err = o.Rollback()
throwFail(t, err)
num, err = o.QueryTable("tag").Filter("name__in", names).Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 0))
- to, err = o.Begin()
+ err = o.Begin()
throwFail(t, err)
tag.Name = "commit"
- id, err = to.Insert(&tag)
+ id, err = o.Insert(&tag)
throwFail(t, err)
throwFail(t, AssertIs(id > 0, true))
- to.Commit()
+ o.Commit()
throwFail(t, err)
num, err = o.QueryTable("tag").Filter("name", "commit").Delete()
@@ -2177,33 +2080,33 @@ func TestTransactionIsolationLevel(t *testing.T) {
o2 := NewOrm()
// start two transaction with isolation level repeatable read
- to1, err := o1.BeginWithCtxAndOpts(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
+ err := o1.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
throwFail(t, err)
- to2, err := o2.BeginWithCtxAndOpts(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
+ err = o2.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
throwFail(t, err)
// o1 insert tag
var tag Tag
tag.Name = "test-transaction"
- id, err := to1.Insert(&tag)
+ id, err := o1.Insert(&tag)
throwFail(t, err)
throwFail(t, AssertIs(id > 0, true))
// o2 query tag table, no result
- num, err := to2.QueryTable("tag").Filter("name", "test-transaction").Count()
+ num, err := o2.QueryTable("tag").Filter("name", "test-transaction").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 0))
// o1 commit
- to1.Commit()
+ o1.Commit()
// o2 query tag table, still no result
- num, err = to2.QueryTable("tag").Filter("name", "test-transaction").Count()
+ num, err = o2.QueryTable("tag").Filter("name", "test-transaction").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 0))
// o2 commit and query tag table, get the result
- to2.Commit()
+ o2.Commit()
num, err = o2.QueryTable("tag").Filter("name", "test-transaction").Count()
throwFail(t, err)
throwFail(t, AssertIs(num, 1))
@@ -2216,14 +2119,14 @@ func TestTransactionIsolationLevel(t *testing.T) {
func TestBeginTxWithContextCanceled(t *testing.T) {
o := NewOrm()
ctx, cancel := context.WithCancel(context.Background())
- to, _ := o.BeginWithCtx(ctx)
- id, err := to.Insert(&Tag{Name: "test-context"})
+ o.BeginTx(ctx, nil)
+ id, err := o.Insert(&Tag{Name: "test-context"})
throwFail(t, err)
throwFail(t, AssertIs(id > 0, true))
// cancel the context before commit to make it error
cancel()
- err = to.Commit()
+ err = o.Commit()
throwFail(t, AssertIs(err, context.Canceled))
}
@@ -2284,8 +2187,8 @@ func TestInLine(t *testing.T) {
throwFail(t, AssertIs(il.Name, name))
throwFail(t, AssertIs(il.Email, email))
- assert.True(t, il.Created.In(DefaultTimeLoc).Sub(inline.Created.In(DefaultTimeLoc)) <= time.Second)
- assert.True(t, il.Updated.In(DefaultTimeLoc).Sub(inline.Updated.In(DefaultTimeLoc)) <= time.Second)
+ throwFail(t, AssertIs(il.Created.In(DefaultTimeLoc), inline.Created.In(DefaultTimeLoc), testDate))
+ throwFail(t, AssertIs(il.Updated.In(DefaultTimeLoc), inline.Updated.In(DefaultTimeLoc), testDateTime))
}
func TestInLineOneToOne(t *testing.T) {
@@ -2510,7 +2413,7 @@ func TestInsertOrUpdate(t *testing.T) {
fmt.Println("sqlite3 is nonsupport")
return
}
- // test1
+ //test1
_, err := dORM.InsertOrUpdate(&user1, "user_name")
if err != nil {
fmt.Println(err)
@@ -2522,7 +2425,7 @@ func TestInsertOrUpdate(t *testing.T) {
dORM.Read(&test, "user_name")
throwFailNow(t, AssertIs(user1.Status, test.Status))
}
- // test2
+ //test2
_, err = dORM.InsertOrUpdate(&user2, "user_name")
if err != nil {
fmt.Println(err)
@@ -2536,11 +2439,11 @@ func TestInsertOrUpdate(t *testing.T) {
throwFailNow(t, AssertIs(user2.Password, strings.TrimSpace(test.Password)))
}
- // postgres ON CONFLICT DO UPDATE SET can`t use colu=colu+values
+ //postgres ON CONFLICT DO UPDATE SET can`t use colu=colu+values
if IsPostgres {
return
}
- // test3 +
+ //test3 +
_, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status+1")
if err != nil {
fmt.Println(err)
@@ -2552,7 +2455,7 @@ func TestInsertOrUpdate(t *testing.T) {
dORM.Read(&test, "user_name")
throwFailNow(t, AssertIs(user2.Status+1, test.Status))
}
- // test4 -
+ //test4 -
_, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status-1")
if err != nil {
fmt.Println(err)
@@ -2564,7 +2467,7 @@ func TestInsertOrUpdate(t *testing.T) {
dORM.Read(&test, "user_name")
throwFailNow(t, AssertIs((user2.Status+1)-1, test.Status))
}
- // test5 *
+ //test5 *
_, err = dORM.InsertOrUpdate(&user2, "user_name", "status=status*3")
if err != nil {
fmt.Println(err)
@@ -2576,7 +2479,7 @@ func TestInsertOrUpdate(t *testing.T) {
dORM.Read(&test, "user_name")
throwFailNow(t, AssertIs(((user2.Status+1)-1)*3, test.Status))
}
- // test6 /
+ //test6 /
_, err = dORM.InsertOrUpdate(&user2, "user_name", "Status=Status/3")
if err != nil {
fmt.Println(err)
@@ -2589,82 +2492,3 @@ func TestInsertOrUpdate(t *testing.T) {
throwFailNow(t, AssertIs((((user2.Status+1)-1)*3)/3, test.Status))
}
}
-
-func TestStrPkInsert(t *testing.T) {
- RegisterModel(new(StrPk))
- pk := `1`
- value := `StrPkValues(*56`
- strPk := &StrPk{
- Id: pk,
- Value: value,
- }
-
- var err error
- _, err = dORM.Insert(strPk)
- if err != ErrLastInsertIdUnavailable {
- throwFailNow(t, AssertIs(err, nil))
- }
-
- var vForTesting StrPk
- err = dORM.QueryTable(new(StrPk)).Filter(`id`, pk).One(&vForTesting)
- throwFailNow(t, AssertIs(err, nil))
- throwFailNow(t, AssertIs(vForTesting.Value, value))
-
- value2 := `s8s5da7as`
- strPkForUpsert := &StrPk{
- Id: pk,
- Value: value2,
- }
-
- _, err = dORM.InsertOrUpdate(strPkForUpsert, `id`)
- if err != nil {
- fmt.Println(err)
- if err.Error() == "postgres version must 9.5 or higher" || err.Error() == "`sqlite3` nonsupport InsertOrUpdate in beego" {
- } else if err == ErrLastInsertIdUnavailable {
- } else {
- throwFailNow(t, err)
- }
- } else {
- var vForTesting2 StrPk
- err = dORM.QueryTable(new(StrPk)).Filter(`id`, pk).One(&vForTesting2)
- throwFailNow(t, AssertIs(err, nil))
- throwFailNow(t, AssertIs(vForTesting2.Value, value2))
- }
-}
-
-func TestPSQueryBuilder(t *testing.T) {
- // only test postgres
- if dORM.Driver().Type() != 4 {
- return
- }
-
- var user User
- var l []userProfile
- o := NewOrm()
-
- qb, err := NewQueryBuilder("postgres")
- if err != nil {
- throwFailNow(t, err)
- }
- qb.Select("user.id", "user.user_name").
- From("user").Where("id = ?").OrderBy("user_name").
- Desc().Limit(1).Offset(0)
- sql := qb.String()
- err = o.Raw(sql, 2).QueryRow(&user)
- if err != nil {
- throwFailNow(t, err)
- }
- throwFail(t, AssertIs(user.UserName, "slene"))
-
- qb.Select("*").
- From("user_profile").InnerJoin("user").
- On("user_profile.id = user.id")
- sql = qb.String()
- num, err := o.Raw(sql).QueryRows(&l)
- if err != nil {
- throwFailNow(t, err)
- }
- throwFailNow(t, AssertIs(num, 1))
- throwFailNow(t, AssertIs(l[0].UserName, "astaxie"))
- throwFailNow(t, AssertIs(l[0].Age, 30))
-}
diff --git a/client/orm/qb.go b/orm/qb.go
similarity index 96%
rename from client/orm/qb.go
rename to orm/qb.go
index c82d2255..e0655a17 100644
--- a/client/orm/qb.go
+++ b/orm/qb.go
@@ -52,7 +52,7 @@ func NewQueryBuilder(driver string) (qb QueryBuilder, err error) {
} else if driver == "tidb" {
qb = new(TiDBQueryBuilder)
} else if driver == "postgres" {
- qb = new(PostgresQueryBuilder)
+ err = errors.New("postgres query builder is not supported yet")
} else if driver == "sqlite" {
err = errors.New("sqlite query builder is not supported yet")
} else {
diff --git a/client/orm/qb_mysql.go b/orm/qb_mysql.go
similarity index 71%
rename from client/orm/qb_mysql.go
rename to orm/qb_mysql.go
index 19130496..23bdc9ee 100644
--- a/client/orm/qb_mysql.go
+++ b/orm/qb_mysql.go
@@ -25,144 +25,144 @@ const CommaSpace = ", "
// MySQLQueryBuilder is the SQL build
type MySQLQueryBuilder struct {
- tokens []string
+ Tokens []string
}
// Select will join the fields
func (qb *MySQLQueryBuilder) Select(fields ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "SELECT", strings.Join(fields, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "SELECT", strings.Join(fields, CommaSpace))
return qb
}
// ForUpdate add the FOR UPDATE clause
func (qb *MySQLQueryBuilder) ForUpdate() QueryBuilder {
- qb.tokens = append(qb.tokens, "FOR UPDATE")
+ qb.Tokens = append(qb.Tokens, "FOR UPDATE")
return qb
}
// From join the tables
func (qb *MySQLQueryBuilder) From(tables ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "FROM", strings.Join(tables, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
return qb
}
// InnerJoin INNER JOIN the table
func (qb *MySQLQueryBuilder) InnerJoin(table string) QueryBuilder {
- qb.tokens = append(qb.tokens, "INNER JOIN", table)
+ qb.Tokens = append(qb.Tokens, "INNER JOIN", table)
return qb
}
// LeftJoin LEFT JOIN the table
func (qb *MySQLQueryBuilder) LeftJoin(table string) QueryBuilder {
- qb.tokens = append(qb.tokens, "LEFT JOIN", table)
+ qb.Tokens = append(qb.Tokens, "LEFT JOIN", table)
return qb
}
// RightJoin RIGHT JOIN the table
func (qb *MySQLQueryBuilder) RightJoin(table string) QueryBuilder {
- qb.tokens = append(qb.tokens, "RIGHT JOIN", table)
+ qb.Tokens = append(qb.Tokens, "RIGHT JOIN", table)
return qb
}
// On join with on cond
func (qb *MySQLQueryBuilder) On(cond string) QueryBuilder {
- qb.tokens = append(qb.tokens, "ON", cond)
+ qb.Tokens = append(qb.Tokens, "ON", cond)
return qb
}
// Where join the Where cond
func (qb *MySQLQueryBuilder) Where(cond string) QueryBuilder {
- qb.tokens = append(qb.tokens, "WHERE", cond)
+ qb.Tokens = append(qb.Tokens, "WHERE", cond)
return qb
}
// And join the and cond
func (qb *MySQLQueryBuilder) And(cond string) QueryBuilder {
- qb.tokens = append(qb.tokens, "AND", cond)
+ qb.Tokens = append(qb.Tokens, "AND", cond)
return qb
}
// Or join the or cond
func (qb *MySQLQueryBuilder) Or(cond string) QueryBuilder {
- qb.tokens = append(qb.tokens, "OR", cond)
+ qb.Tokens = append(qb.Tokens, "OR", cond)
return qb
}
// In join the IN (vals)
func (qb *MySQLQueryBuilder) In(vals ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "IN", "(", strings.Join(vals, CommaSpace), ")")
+ qb.Tokens = append(qb.Tokens, "IN", "(", strings.Join(vals, CommaSpace), ")")
return qb
}
// OrderBy join the Order by fields
func (qb *MySQLQueryBuilder) OrderBy(fields ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "ORDER BY", strings.Join(fields, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "ORDER BY", strings.Join(fields, CommaSpace))
return qb
}
// Asc join the asc
func (qb *MySQLQueryBuilder) Asc() QueryBuilder {
- qb.tokens = append(qb.tokens, "ASC")
+ qb.Tokens = append(qb.Tokens, "ASC")
return qb
}
// Desc join the desc
func (qb *MySQLQueryBuilder) Desc() QueryBuilder {
- qb.tokens = append(qb.tokens, "DESC")
+ qb.Tokens = append(qb.Tokens, "DESC")
return qb
}
// Limit join the limit num
func (qb *MySQLQueryBuilder) Limit(limit int) QueryBuilder {
- qb.tokens = append(qb.tokens, "LIMIT", strconv.Itoa(limit))
+ qb.Tokens = append(qb.Tokens, "LIMIT", strconv.Itoa(limit))
return qb
}
// Offset join the offset num
func (qb *MySQLQueryBuilder) Offset(offset int) QueryBuilder {
- qb.tokens = append(qb.tokens, "OFFSET", strconv.Itoa(offset))
+ qb.Tokens = append(qb.Tokens, "OFFSET", strconv.Itoa(offset))
return qb
}
// GroupBy join the Group by fields
func (qb *MySQLQueryBuilder) GroupBy(fields ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "GROUP BY", strings.Join(fields, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "GROUP BY", strings.Join(fields, CommaSpace))
return qb
}
// Having join the Having cond
func (qb *MySQLQueryBuilder) Having(cond string) QueryBuilder {
- qb.tokens = append(qb.tokens, "HAVING", cond)
+ qb.Tokens = append(qb.Tokens, "HAVING", cond)
return qb
}
// Update join the update table
func (qb *MySQLQueryBuilder) Update(tables ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "UPDATE", strings.Join(tables, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "UPDATE", strings.Join(tables, CommaSpace))
return qb
}
// Set join the set kv
func (qb *MySQLQueryBuilder) Set(kv ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "SET", strings.Join(kv, CommaSpace))
+ qb.Tokens = append(qb.Tokens, "SET", strings.Join(kv, CommaSpace))
return qb
}
// Delete join the Delete tables
func (qb *MySQLQueryBuilder) Delete(tables ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "DELETE")
+ qb.Tokens = append(qb.Tokens, "DELETE")
if len(tables) != 0 {
- qb.tokens = append(qb.tokens, strings.Join(tables, CommaSpace))
+ qb.Tokens = append(qb.Tokens, strings.Join(tables, CommaSpace))
}
return qb
}
// InsertInto join the insert SQL
func (qb *MySQLQueryBuilder) InsertInto(table string, fields ...string) QueryBuilder {
- qb.tokens = append(qb.tokens, "INSERT INTO", table)
+ qb.Tokens = append(qb.Tokens, "INSERT INTO", table)
if len(fields) != 0 {
fieldsStr := strings.Join(fields, CommaSpace)
- qb.tokens = append(qb.tokens, "(", fieldsStr, ")")
+ qb.Tokens = append(qb.Tokens, "(", fieldsStr, ")")
}
return qb
}
@@ -170,7 +170,7 @@ func (qb *MySQLQueryBuilder) InsertInto(table string, fields ...string) QueryBui
// Values join the Values(vals)
func (qb *MySQLQueryBuilder) Values(vals ...string) QueryBuilder {
valsStr := strings.Join(vals, CommaSpace)
- qb.tokens = append(qb.tokens, "VALUES", "(", valsStr, ")")
+ qb.Tokens = append(qb.Tokens, "VALUES", "(", valsStr, ")")
return qb
}
@@ -179,9 +179,7 @@ func (qb *MySQLQueryBuilder) Subquery(sub string, alias string) string {
return fmt.Sprintf("(%s) AS %s", sub, alias)
}
-// String join all tokens
+// String join all Tokens
func (qb *MySQLQueryBuilder) String() string {
- s := strings.Join(qb.tokens, " ")
- qb.tokens = qb.tokens[:0]
- return s
+ return strings.Join(qb.Tokens, " ")
}
diff --git a/adapter/orm/qb_tidb.go b/orm/qb_tidb.go
similarity index 60%
rename from adapter/orm/qb_tidb.go
rename to orm/qb_tidb.go
index 18631ef0..87b3ae84 100644
--- a/adapter/orm/qb_tidb.go
+++ b/orm/qb_tidb.go
@@ -15,133 +15,168 @@
package orm
import (
- "github.com/astaxie/beego/client/orm"
+ "fmt"
+ "strconv"
+ "strings"
)
// TiDBQueryBuilder is the SQL build
-type TiDBQueryBuilder orm.TiDBQueryBuilder
+type TiDBQueryBuilder struct {
+ Tokens []string
+}
// Select will join the fields
func (qb *TiDBQueryBuilder) Select(fields ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Select(fields...)
+ qb.Tokens = append(qb.Tokens, "SELECT", strings.Join(fields, CommaSpace))
+ return qb
}
// ForUpdate add the FOR UPDATE clause
func (qb *TiDBQueryBuilder) ForUpdate() QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).ForUpdate()
+ qb.Tokens = append(qb.Tokens, "FOR UPDATE")
+ return qb
}
// From join the tables
func (qb *TiDBQueryBuilder) From(tables ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).From(tables...)
+ qb.Tokens = append(qb.Tokens, "FROM", strings.Join(tables, CommaSpace))
+ return qb
}
// InnerJoin INNER JOIN the table
func (qb *TiDBQueryBuilder) InnerJoin(table string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).InnerJoin(table)
+ qb.Tokens = append(qb.Tokens, "INNER JOIN", table)
+ return qb
}
// LeftJoin LEFT JOIN the table
func (qb *TiDBQueryBuilder) LeftJoin(table string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).LeftJoin(table)
+ qb.Tokens = append(qb.Tokens, "LEFT JOIN", table)
+ return qb
}
// RightJoin RIGHT JOIN the table
func (qb *TiDBQueryBuilder) RightJoin(table string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).RightJoin(table)
+ qb.Tokens = append(qb.Tokens, "RIGHT JOIN", table)
+ return qb
}
// On join with on cond
func (qb *TiDBQueryBuilder) On(cond string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).On(cond)
+ qb.Tokens = append(qb.Tokens, "ON", cond)
+ return qb
}
// Where join the Where cond
func (qb *TiDBQueryBuilder) Where(cond string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Where(cond)
+ qb.Tokens = append(qb.Tokens, "WHERE", cond)
+ return qb
}
// And join the and cond
func (qb *TiDBQueryBuilder) And(cond string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).And(cond)
+ qb.Tokens = append(qb.Tokens, "AND", cond)
+ return qb
}
// Or join the or cond
func (qb *TiDBQueryBuilder) Or(cond string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Or(cond)
+ qb.Tokens = append(qb.Tokens, "OR", cond)
+ return qb
}
// In join the IN (vals)
func (qb *TiDBQueryBuilder) In(vals ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).In(vals...)
+ qb.Tokens = append(qb.Tokens, "IN", "(", strings.Join(vals, CommaSpace), ")")
+ return qb
}
// OrderBy join the Order by fields
func (qb *TiDBQueryBuilder) OrderBy(fields ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).OrderBy(fields...)
+ qb.Tokens = append(qb.Tokens, "ORDER BY", strings.Join(fields, CommaSpace))
+ return qb
}
// Asc join the asc
func (qb *TiDBQueryBuilder) Asc() QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Asc()
+ qb.Tokens = append(qb.Tokens, "ASC")
+ return qb
}
// Desc join the desc
func (qb *TiDBQueryBuilder) Desc() QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Desc()
+ qb.Tokens = append(qb.Tokens, "DESC")
+ return qb
}
// Limit join the limit num
func (qb *TiDBQueryBuilder) Limit(limit int) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Limit(limit)
+ qb.Tokens = append(qb.Tokens, "LIMIT", strconv.Itoa(limit))
+ return qb
}
// Offset join the offset num
func (qb *TiDBQueryBuilder) Offset(offset int) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Offset(offset)
+ qb.Tokens = append(qb.Tokens, "OFFSET", strconv.Itoa(offset))
+ return qb
}
// GroupBy join the Group by fields
func (qb *TiDBQueryBuilder) GroupBy(fields ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).GroupBy(fields...)
+ qb.Tokens = append(qb.Tokens, "GROUP BY", strings.Join(fields, CommaSpace))
+ return qb
}
// Having join the Having cond
func (qb *TiDBQueryBuilder) Having(cond string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Having(cond)
+ qb.Tokens = append(qb.Tokens, "HAVING", cond)
+ return qb
}
// Update join the update table
func (qb *TiDBQueryBuilder) Update(tables ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Update(tables...)
+ qb.Tokens = append(qb.Tokens, "UPDATE", strings.Join(tables, CommaSpace))
+ return qb
}
// Set join the set kv
func (qb *TiDBQueryBuilder) Set(kv ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Set(kv...)
+ qb.Tokens = append(qb.Tokens, "SET", strings.Join(kv, CommaSpace))
+ return qb
}
// Delete join the Delete tables
func (qb *TiDBQueryBuilder) Delete(tables ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Delete(tables...)
+ qb.Tokens = append(qb.Tokens, "DELETE")
+ if len(tables) != 0 {
+ qb.Tokens = append(qb.Tokens, strings.Join(tables, CommaSpace))
+ }
+ return qb
}
// InsertInto join the insert SQL
func (qb *TiDBQueryBuilder) InsertInto(table string, fields ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).InsertInto(table, fields...)
+ qb.Tokens = append(qb.Tokens, "INSERT INTO", table)
+ if len(fields) != 0 {
+ fieldsStr := strings.Join(fields, CommaSpace)
+ qb.Tokens = append(qb.Tokens, "(", fieldsStr, ")")
+ }
+ return qb
}
// Values join the Values(vals)
func (qb *TiDBQueryBuilder) Values(vals ...string) QueryBuilder {
- return (*orm.TiDBQueryBuilder)(qb).Values(vals...)
+ valsStr := strings.Join(vals, CommaSpace)
+ qb.Tokens = append(qb.Tokens, "VALUES", "(", valsStr, ")")
+ return qb
}
// Subquery join the sub as alias
func (qb *TiDBQueryBuilder) Subquery(sub string, alias string) string {
- return (*orm.TiDBQueryBuilder)(qb).Subquery(sub, alias)
+ return fmt.Sprintf("(%s) AS %s", sub, alias)
}
// String join all Tokens
func (qb *TiDBQueryBuilder) String() string {
- return (*orm.TiDBQueryBuilder)(qb).String()
+ return strings.Join(qb.Tokens, " ")
}
diff --git a/client/orm/types.go b/orm/types.go
similarity index 77%
rename from client/orm/types.go
rename to orm/types.go
index 34c61d51..2fd10774 100644
--- a/client/orm/types.go
+++ b/orm/types.go
@@ -19,67 +19,8 @@ import (
"database/sql"
"reflect"
"time"
-
- "github.com/astaxie/beego/core/utils"
)
-// TableNaming is usually used by model
-// when you custom your table name, please implement this interfaces
-// for example:
-// type User struct {
-// ...
-// }
-// func (u *User) TableName() string {
-// return "USER_TABLE"
-// }
-type TableNameI interface {
- TableName() string
-}
-
-// TableEngineI is usually used by model
-// when you want to use specific engine, like myisam, you can implement this interface
-// for example:
-// type User struct {
-// ...
-// }
-// func (u *User) TableEngine() string {
-// return "myisam"
-// }
-type TableEngineI interface {
- TableEngine() string
-}
-
-// TableIndexI is usually used by model
-// when you want to create indexes, you can implement this interface
-// for example:
-// type User struct {
-// ...
-// }
-// func (u *User) TableIndex() [][]string {
-// return [][]string{{"Name"}}
-// }
-type TableIndexI interface {
- TableIndex() [][]string
-}
-
-// TableUniqueI is usually used by model
-// when you want to create unique indexes, you can implement this interface
-// for example:
-// type User struct {
-// ...
-// }
-// func (u *User) TableUnique() [][]string {
-// return [][]string{{"Email"}}
-// }
-type TableUniqueI interface {
- TableUnique() [][]string
-}
-
-// IsApplicableTableForDB if return false, we won't create table to this db
-type IsApplicableTableForDB interface {
- IsApplicableTableForDB(db string) bool
-}
-
// Driver define database driver
type Driver interface {
Name() string
@@ -94,43 +35,35 @@ type Fielder interface {
RawValue() interface{}
}
-type TxBeginner interface {
- //self control transaction
- Begin() (TxOrmer, error)
- BeginWithCtx(ctx context.Context) (TxOrmer, error)
- BeginWithOpts(opts *sql.TxOptions) (TxOrmer, error)
- BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error)
-
- //closure control transaction
- DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error
- DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error
- DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
- DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
-}
-
-type TxCommitter interface {
- Commit() error
- Rollback() error
-}
-
-//Data Manipulation Language
-type DML interface {
+// Ormer define the orm interface
+type Ormer interface {
+ // read data to model
+ // for example:
+ // this will find User by Id field
+ // u = &User{Id: user.Id}
+ // err = Ormer.Read(u)
+ // this will find User by UserName field
+ // u = &User{UserName: "astaxie", Password: "pass"}
+ // err = Ormer.Read(u, "UserName")
+ Read(md interface{}, cols ...string) error
+ // Like Read(), but with "FOR UPDATE" clause, useful in transaction.
+ // Some databases are not support this feature.
+ ReadForUpdate(md interface{}, cols ...string) error
+ // Try to read a row from the database, or insert one if it doesn't exist
+ ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
// insert model data to database
// for example:
// user := new(User)
// id, err = Ormer.Insert(user)
// user must be a pointer and Insert will set user's pk field
- Insert(md interface{}) (int64, error)
- InsertWithCtx(ctx context.Context, md interface{}) (int64, error)
+ Insert(interface{}) (int64, error)
// mysql:InsertOrUpdate(model) or InsertOrUpdate(model,"colu=colu+value")
// if colu type is integer : can use(+-*/), string : convert(colu,"value")
// postgres: InsertOrUpdate(model,"conflictColumnName") or InsertOrUpdate(model,"conflictColumnName","colu=colu+value")
// if colu type is integer : can use(+-*/), string : colu || "value"
InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
- InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error)
// insert some models to database
InsertMulti(bulk int, mds interface{}) (int64, error)
- InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)
// update model to database.
// cols set the columns those want to update.
// find model by Id(pk) field and update columns specified by fields, if cols is null then update all columns
@@ -141,90 +74,61 @@ type DML interface {
// user.Extra.Data = "orm"
// num, err = Ormer.Update(&user, "Langs", "Extra")
Update(md interface{}, cols ...string) (int64, error)
- UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
// delete model in database
Delete(md interface{}, cols ...string) (int64, error)
- DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
-
- // return a raw query seter for raw sql string.
- // for example:
- // ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
- // // update user testing's name to slene
- Raw(query string, args ...interface{}) RawSeter
- RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter
-}
-
-// Data Query Language
-type DQL interface {
- // read data to model
- // for example:
- // this will find User by Id field
- // u = &User{Id: user.Id}
- // err = Ormer.Read(u)
- // this will find User by UserName field
- // u = &User{UserName: "astaxie", Password: "pass"}
- // err = Ormer.Read(u, "UserName")
- Read(md interface{}, cols ...string) error
- ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error
-
- // Like Read(), but with "FOR UPDATE" clause, useful in transaction.
- // Some databases are not support this feature.
- ReadForUpdate(md interface{}, cols ...string) error
- ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error
-
- // Try to read a row from the database, or insert one if it doesn't exist
- ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
- ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error)
-
// load related models to md model.
// args are limit, offset int and order string.
//
// example:
// Ormer.LoadRelated(post,"Tags")
// for _,tag := range post.Tags{...}
- // hints.DefaultRelDepth useDefaultRelsDepth ; or depth 0
- // hints.RelDepth loadRelationDepth
- // hints.Limit limit default limit 1000
- // hints.Offset int offset default offset 0
- // hints.OrderBy string order for example : "-Id"
+ //args[0] bool true useDefaultRelsDepth ; false depth 0
+ //args[0] int loadRelationDepth
+ //args[1] int limit default limit 1000
+ //args[2] int offset default offset 0
+ //args[3] string order for example : "-Id"
// make sure the relation is defined in model struct tags.
- LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error)
- LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error)
-
+ LoadRelated(md interface{}, name string, args ...interface{}) (int64, error)
// create a models to models queryer
// for example:
// post := Post{Id: 4}
// m2m := Ormer.QueryM2M(&post, "Tags")
QueryM2M(md interface{}, name string) QueryM2Mer
- QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer
-
// return a QuerySeter for table operations.
// table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
QueryTable(ptrStructOrTableName interface{}) QuerySeter
- QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter
-
- DBStats() *sql.DBStats
-}
-
-type DriverGetter interface {
+ // switch to another registered database driver by given name.
+ Using(name string) error
+ // begin transaction
+ // for example:
+ // o := NewOrm()
+ // err := o.Begin()
+ // ...
+ // err = o.Rollback()
+ Begin() error
+ // begin transaction with provided context and option
+ // the provided context is used until the transaction is committed or rolled back.
+ // if the context is canceled, the transaction will be rolled back.
+ // the provided TxOptions is optional and may be nil if defaults should be used.
+ // if a non-default isolation level is used that the driver doesn't support, an error will be returned.
+ // for example:
+ // o := NewOrm()
+ // err := o.BeginTx(context.Background(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead})
+ // ...
+ // err = o.Rollback()
+ BeginTx(ctx context.Context, opts *sql.TxOptions) error
+ // commit transaction
+ Commit() error
+ // rollback transaction
+ Rollback() error
+ // return a raw query seter for raw sql string.
+ // for example:
+ // ormer.Raw("UPDATE `user` SET `user_name` = ? WHERE `user_name` = ?", "slene", "testing").Exec()
+ // // update user testing's name to slene
+ Raw(query string, args ...interface{}) RawSeter
Driver() Driver
-}
-
-type ormer interface {
- DQL
- DML
- DriverGetter
-}
-
-type Ormer interface {
- ormer
- TxBeginner
-}
-
-type TxOrmer interface {
- ormer
- TxCommitter
+ DBStats() *sql.DBStats
}
// Inserter insert prepared statement
@@ -289,21 +193,6 @@ type QuerySeter interface {
// for example:
// qs.OrderBy("-status")
OrderBy(exprs ...string) QuerySeter
- // add FORCE INDEX expression.
- // for example:
- // qs.ForceIndex(`idx_name1`,`idx_name2`)
- // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
- ForceIndex(indexes ...string) QuerySeter
- // add USE INDEX expression.
- // for example:
- // qs.UseIndex(`idx_name1`,`idx_name2`)
- // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
- UseIndex(indexes ...string) QuerySeter
- // add IGNORE INDEX expression.
- // for example:
- // qs.IgnoreIndex(`idx_name1`,`idx_name2`)
- // ForceIndex, UseIndex , IgnoreIndex are mutually exclusive
- IgnoreIndex(indexes ...string) QuerySeter
// set relation model to query together.
// it will query relation models and assign to parent model.
// for example:
@@ -340,7 +229,7 @@ type QuerySeter interface {
// }) // user slene's name will change to slene2
Update(values Params) (int64, error)
// delete from table
- // for example:
+ //for example:
// num ,err = qs.Filter("user_name__in", "testing1", "testing2").Delete()
// //delete two user who's name is testing1 or testing2
Delete() (int64, error)
@@ -425,8 +314,8 @@ type QueryM2Mer interface {
// remove models following the origin model relationship
// only delete rows from m2m table
// for example:
- // tag3 := &Tag{Id:5,Name: "TestTag3"}
- // num, err = m2m.Remove(tag3)
+ //tag3 := &Tag{Id:5,Name: "TestTag3"}
+ //num, err = m2m.Remove(tag3)
Remove(...interface{}) (int64, error)
// check model is existed in relationship of origin model
Exist(interface{}) bool
@@ -448,10 +337,10 @@ type RawPreparer interface {
// sql := fmt.Sprintf("SELECT %sid%s,%sname%s FROM %suser%s WHERE id = ?",Q,Q,Q,Q,Q,Q)
// rs := Ormer.Raw(sql, 1)
type RawSeter interface {
- // execute sql and get result
+ //execute sql and get result
Exec() (sql.Result, error)
- // query data and map to container
- // for example:
+ //query data and map to container
+ //for example:
// var name string
// var id int
// rs.QueryRow(&id,&name) // id==2 name=="slene"
@@ -507,11 +396,11 @@ type RawSeter interface {
type stmtQuerier interface {
Close() error
Exec(args ...interface{}) (sql.Result, error)
- // ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
+ //ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
Query(args ...interface{}) (*sql.Rows, error)
- // QueryContext(args ...interface{}) (*sql.Rows, error)
+ //QueryContext(args ...interface{}) (*sql.Rows, error)
QueryRow(args ...interface{}) *sql.Row
- // QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
+ //QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
}
// db querier
@@ -549,27 +438,24 @@ type txEnder interface {
// base database struct
type dbBaser interface {
Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string, bool) error
- ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location, []string) (int64, error)
- Count(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
- ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
-
Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *alias, ...string) (int64, error)
InsertMulti(dbQuerier, *modelInfo, reflect.Value, int, *time.Location) (int64, error)
InsertValue(dbQuerier, *modelInfo, bool, []string, []interface{}) (int64, error)
InsertStmt(stmtQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
-
Update(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
- UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error)
-
Delete(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) (int64, error)
- DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
-
+ ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location, []string) (int64, error)
SupportUpdateJoin() bool
+ UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error)
+ DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
+ Count(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
OperatorSQL(string) string
GenerateOperatorSQL(*modelInfo, *fieldInfo, string, []interface{}, *time.Location) (string, []interface{})
GenerateOperatorLeftCol(*fieldInfo, string, *string)
PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error)
+ ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
+ RowsTo(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, string, string, *time.Location) (int64, error)
MaxLimit() uint64
TableQuote() string
ReplaceMarks(*string)
@@ -584,6 +470,4 @@ type dbBaser interface {
IndexExists(dbQuerier, string, string) bool
collectFieldValue(*modelInfo, *fieldInfo, reflect.Value, bool, *time.Location) (interface{}, error)
setval(dbQuerier, *modelInfo, []string) error
-
- GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string
}
diff --git a/client/orm/utils.go b/orm/utils.go
similarity index 100%
rename from client/orm/utils.go
rename to orm/utils.go
diff --git a/adapter/orm/utils_test.go b/orm/utils_test.go
similarity index 100%
rename from adapter/orm/utils_test.go
rename to orm/utils_test.go
diff --git a/server/web/parser.go b/parser.go
similarity index 93%
rename from server/web/parser.go
rename to parser.go
index c3434501..3a311894 100644
--- a/server/web/parser.go
+++ b/parser.go
@@ -12,13 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"encoding/json"
"errors"
"fmt"
"go/ast"
+ "go/parser"
+ "go/token"
"io/ioutil"
"os"
"path/filepath"
@@ -28,19 +30,16 @@ import (
"strings"
"unicode"
- "golang.org/x/tools/go/packages"
-
- "github.com/astaxie/beego/core/logs"
-
- "github.com/astaxie/beego/core/utils"
- "github.com/astaxie/beego/server/web/context/param"
+ "github.com/astaxie/beego/context/param"
+ "github.com/astaxie/beego/logs"
+ "github.com/astaxie/beego/utils"
)
var globalRouterTemplate = `package {{.routersDir}}
import (
- beego "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context/param"{{.globalimport}}
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context/param"{{.globalimport}}
)
func init() {
@@ -77,7 +76,7 @@ func init() {
pkgLastupdate = make(map[string]int64)
}
-func parserPkg(pkgRealpath string) error {
+func parserPkg(pkgRealpath, pkgpath string) error {
rep := strings.NewReplacer("\\", "_", "/", "_", ".", "_")
commentFilename, _ = filepath.Rel(AppPath, pkgRealpath)
commentFilename = commentPrefix + rep.Replace(commentFilename) + ".go"
@@ -86,23 +85,24 @@ func parserPkg(pkgRealpath string) error {
return nil
}
genInfoList = make(map[string][]ControllerComments)
- pkgs, err := packages.Load(&packages.Config{
- Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedSyntax,
- Dir: pkgRealpath,
- }, "./...")
+ fileSet := token.NewFileSet()
+ astPkgs, err := parser.ParseDir(fileSet, pkgRealpath, func(info os.FileInfo) bool {
+ name := info.Name()
+ return !info.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+ }, parser.ParseComments)
if err != nil {
return err
}
- for _, pkg := range pkgs {
- for _, fl := range pkg.Syntax {
+ for _, pkg := range astPkgs {
+ for _, fl := range pkg.Files {
for _, d := range fl.Decls {
switch specDecl := d.(type) {
case *ast.FuncDecl:
if specDecl.Recv != nil {
exp, ok := specDecl.Recv.List[0].Type.(*ast.StarExpr) // Check that the type is correct first beforing throwing to parser
if ok {
- parserComments(specDecl, fmt.Sprint(exp.X), pkg.PkgPath)
+ parserComments(specDecl, fmt.Sprint(exp.X), pkgpath)
}
}
}
@@ -221,7 +221,7 @@ func buildMethodParams(funcParams []*ast.Field, pc *parsedComment) []*param.Meth
func buildMethodParam(fparam *ast.Field, name string, pc *parsedComment) *param.MethodParam {
options := []param.MethodParamOption{}
if cparam, ok := pc.params[name]; ok {
- // Build param from comment info
+ //Build param from comment info
name = cparam.name
if cparam.required {
options = append(options, param.IsRequired)
@@ -358,10 +358,10 @@ filterLoop:
methods := matches[2]
if methods == "" {
pc.methods = []string{"get"}
- // pc.hasGet = true
+ //pc.hasGet = true
} else {
pc.methods = strings.Split(methods, ",")
- // pc.hasGet = strings.Contains(methods, "get")
+ //pc.hasGet = strings.Contains(methods, "get")
}
pcs = append(pcs, pc)
} else {
@@ -566,17 +566,8 @@ func getpathTime(pkgRealpath string) (lastupdate int64, err error) {
return lastupdate, err
}
for _, f := range fl {
- var t int64
- if f.IsDir() {
- t, err = getpathTime(filepath.Join(pkgRealpath, f.Name()))
- if err != nil {
- return lastupdate, err
- }
- } else {
- t = f.ModTime().UnixNano()
- }
- if lastupdate < t {
- lastupdate = t
+ if lastupdate < f.ModTime().UnixNano() {
+ lastupdate = f.ModTime().UnixNano()
}
}
return lastupdate, nil
diff --git a/server/web/filter/apiauth/apiauth.go b/plugins/apiauth/apiauth.go
similarity index 77%
rename from server/web/filter/apiauth/apiauth.go
rename to plugins/apiauth/apiauth.go
index 58153f1d..10e25f3f 100644
--- a/server/web/filter/apiauth/apiauth.go
+++ b/plugins/apiauth/apiauth.go
@@ -65,15 +65,15 @@ import (
"sort"
"time"
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
)
-// AppIDToAppSecret gets appsecret through appid
+// AppIDToAppSecret is used to get appsecret throw appid
type AppIDToAppSecret func(string) string
-// APIBasicAuth uses the basic appid/appkey as the AppIdToAppSecret
-func APIBasicAuth(appid, appkey string) web.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,53 +83,56 @@ func APIBasicAuth(appid, appkey string) web.FilterFunc {
return APISecretAuth(ft, 300)
}
-// APISecretAuth uses AppIdToAppSecret verify and
-func APISecretAuth(f AppIDToAppSecret, timeout int) web.FilterFunc {
+// APIBaiscAuth calls APIBasicAuth for previous callers
+func APIBaiscAuth(appid, appkey string) beego.FilterFunc {
+ return APIBasicAuth(appid, appkey)
+}
+
+// APISecretAuth use AppIdToAppSecret verify and
+func APISecretAuth(f AppIDToAppSecret, timeout int) beego.FilterFunc {
return func(ctx *context.Context) {
if ctx.Input.Query("appid") == "" {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("missing query parameter: appid")
+ ctx.WriteString("miss query param: appid")
return
}
appsecret := f(ctx.Input.Query("appid"))
if appsecret == "" {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("appid query parameter missing")
+ ctx.WriteString("not exist this appid")
return
}
if ctx.Input.Query("signature") == "" {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("missing query parameter: signature")
-
+ ctx.WriteString("miss query param: signature")
return
}
if ctx.Input.Query("timestamp") == "" {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("missing query parameter: timestamp")
+ ctx.WriteString("miss query param: timestamp")
return
}
u, err := time.Parse("2006-01-02 15:04:05", ctx.Input.Query("timestamp"))
if err != nil {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("incorrect timestamp format. Should be in the form 2006-01-02 15:04:05")
-
+ ctx.WriteString("timestamp format is error, should 2006-01-02 15:04:05")
return
}
t := time.Now()
if t.Sub(u).Seconds() > float64(timeout) {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("request timer timeout exceeded. Please try again")
+ ctx.WriteString("timeout! the request time is long ago, please try again")
return
}
if ctx.Input.Query("signature") !=
Signature(appsecret, ctx.Input.Method(), ctx.Request.Form, ctx.Input.URL()) {
ctx.ResponseWriter.WriteHeader(403)
- ctx.WriteString("authentication failed")
+ ctx.WriteString("auth failed")
}
}
}
-// Signature generates signature with appsecret/method/params/RequestURI
+// Signature used to generate signature with the appsecret/method/params/RequestURI
func Signature(appsecret, method string, params url.Values, RequestURL string) (result string) {
var b bytes.Buffer
keys := make([]string, len(params))
diff --git a/adapter/plugins/apiauth/apiauth_test.go b/plugins/apiauth/apiauth_test.go
similarity index 100%
rename from adapter/plugins/apiauth/apiauth_test.go
rename to plugins/apiauth/apiauth_test.go
diff --git a/server/web/filter/auth/basic.go b/plugins/auth/basic.go
similarity index 94%
rename from server/web/filter/auth/basic.go
rename to plugins/auth/basic.go
index ee6af6c3..c478044a 100644
--- a/server/web/filter/auth/basic.go
+++ b/plugins/auth/basic.go
@@ -40,14 +40,14 @@ import (
"net/http"
"strings"
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
)
var defaultRealm = "Authorization Required"
// Basic is the http basic auth
-func Basic(username string, password string) web.FilterFunc {
+func Basic(username string, password string) beego.FilterFunc {
secrets := func(user, pass string) bool {
return user == username && pass == password
}
@@ -55,7 +55,7 @@ func Basic(username string, password string) web.FilterFunc {
}
// NewBasicAuthenticator return the BasicAuth
-func NewBasicAuthenticator(secrets SecretProvider, Realm string) web.FilterFunc {
+func NewBasicAuthenticator(secrets SecretProvider, Realm string) beego.FilterFunc {
return func(ctx *context.Context) {
a := &BasicAuth{Secrets: secrets, Realm: Realm}
if username := a.CheckAuth(ctx.Request); username == "" {
diff --git a/server/web/filter/authz/authz.go b/plugins/authz/authz.go
similarity index 94%
rename from server/web/filter/authz/authz.go
rename to plugins/authz/authz.go
index 857c52f2..9dc0db76 100644
--- a/server/web/filter/authz/authz.go
+++ b/plugins/authz/authz.go
@@ -40,17 +40,15 @@
package authz
import (
- "net/http"
-
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
"github.com/casbin/casbin"
-
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
+ "net/http"
)
// NewAuthorizer returns the authorizer.
// Use a casbin enforcer as input
-func NewAuthorizer(e *casbin.Enforcer) web.FilterFunc {
+func NewAuthorizer(e *casbin.Enforcer) beego.FilterFunc {
return func(ctx *context.Context) {
a := &BasicAuthorizer{enforcer: e}
diff --git a/adapter/plugins/authz/authz_model.conf b/plugins/authz/authz_model.conf
similarity index 100%
rename from adapter/plugins/authz/authz_model.conf
rename to plugins/authz/authz_model.conf
diff --git a/adapter/plugins/authz/authz_policy.csv b/plugins/authz/authz_policy.csv
similarity index 100%
rename from adapter/plugins/authz/authz_policy.csv
rename to plugins/authz/authz_policy.csv
diff --git a/adapter/plugins/authz/authz_test.go b/plugins/authz/authz_test.go
similarity index 96%
rename from adapter/plugins/authz/authz_test.go
rename to plugins/authz/authz_test.go
index 9b4f21c2..49aed84c 100644
--- a/adapter/plugins/authz/authz_test.go
+++ b/plugins/authz/authz_test.go
@@ -15,14 +15,13 @@
package authz
import (
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/plugins/auth"
+ "github.com/casbin/casbin"
"net/http"
"net/http/httptest"
"testing"
-
- beego "github.com/astaxie/beego/adapter"
- "github.com/astaxie/beego/adapter/context"
- "github.com/astaxie/beego/adapter/plugins/auth"
- "github.com/casbin/casbin"
)
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {
diff --git a/server/web/filter/cors/cors.go b/plugins/cors/cors.go
similarity index 98%
rename from server/web/filter/cors/cors.go
rename to plugins/cors/cors.go
index 3a6905ea..45c327ab 100644
--- a/server/web/filter/cors/cors.go
+++ b/plugins/cors/cors.go
@@ -42,8 +42,8 @@ import (
"strings"
"time"
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
)
const (
@@ -187,7 +187,7 @@ func (o *Options) IsOriginAllowed(origin string) (allowed bool) {
}
// Allow enables CORS for requests those match the provided options.
-func Allow(opts *Options) web.FilterFunc {
+func Allow(opts *Options) beego.FilterFunc {
// Allow default headers if nothing is specified.
if len(opts.AllowHeaders) == 0 {
opts.AllowHeaders = defaultAllowHeaders
diff --git a/server/web/filter/cors/cors_test.go b/plugins/cors/cors_test.go
similarity index 88%
rename from server/web/filter/cors/cors_test.go
rename to plugins/cors/cors_test.go
index 7649de25..34039143 100644
--- a/server/web/filter/cors/cors_test.go
+++ b/plugins/cors/cors_test.go
@@ -21,8 +21,8 @@ import (
"testing"
"time"
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
)
// HTTPHeaderGuardRecorder is httptest.ResponseRecorder with own http.Header
@@ -55,8 +55,8 @@ func (gr *HTTPHeaderGuardRecorder) Header() http.Header {
func Test_AllowAll(t *testing.T) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
}))
handler.Any("/foo", func(ctx *context.Context) {
@@ -72,8 +72,8 @@ func Test_AllowAll(t *testing.T) {
func Test_AllowRegexMatch(t *testing.T) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowOrigins: []string{"https://aaa.com", "https://*.foo.com"},
}))
handler.Any("/foo", func(ctx *context.Context) {
@@ -92,8 +92,8 @@ func Test_AllowRegexMatch(t *testing.T) {
func Test_AllowRegexNoMatch(t *testing.T) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowOrigins: []string{"https://*.foo.com"},
}))
handler.Any("/foo", func(ctx *context.Context) {
@@ -112,8 +112,8 @@ func Test_AllowRegexNoMatch(t *testing.T) {
func Test_OtherHeaders(t *testing.T) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
AllowCredentials: true,
AllowMethods: []string{"PATCH", "GET"},
@@ -156,8 +156,8 @@ func Test_OtherHeaders(t *testing.T) {
func Test_DefaultAllowHeaders(t *testing.T) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
}))
handler.Any("/foo", func(ctx *context.Context) {
@@ -175,8 +175,8 @@ func Test_DefaultAllowHeaders(t *testing.T) {
func Test_Preflight(t *testing.T) {
recorder := NewRecorder()
- handler := web.NewControllerRegister()
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
AllowMethods: []string{"PUT", "PATCH"},
AllowHeaders: []string{"Origin", "X-whatever", "X-CaseSensitive"},
@@ -219,8 +219,8 @@ func Test_Preflight(t *testing.T) {
func Benchmark_WithoutCORS(b *testing.B) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- web.BConfig.RunMode = web.PROD
+ handler := beego.NewControllerRegister()
+ beego.BConfig.RunMode = beego.PROD
handler.Any("/foo", func(ctx *context.Context) {
ctx.Output.SetStatus(500)
})
@@ -233,9 +233,9 @@ func Benchmark_WithoutCORS(b *testing.B) {
func Benchmark_WithCORS(b *testing.B) {
recorder := httptest.NewRecorder()
- handler := web.NewControllerRegister()
- web.BConfig.RunMode = web.PROD
- handler.InsertFilter("*", web.BeforeRouter, Allow(&Options{
+ handler := beego.NewControllerRegister()
+ beego.BConfig.RunMode = beego.PROD
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
AllowAllOrigins: true,
AllowCredentials: true,
AllowMethods: []string{"PATCH", "GET"},
diff --git a/server/web/policy.go b/policy.go
similarity index 97%
rename from server/web/policy.go
rename to policy.go
index 14673422..ab23f927 100644
--- a/server/web/policy.go
+++ b/policy.go
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"strings"
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
)
// PolicyFunc defines a policy function which is invoked before the controller handler is executed.
diff --git a/server/web/router.go b/router.go
similarity index 79%
rename from server/web/router.go
rename to router.go
index 7bb89d82..b19a199d 100644
--- a/server/web/router.go
+++ b/router.go
@@ -12,24 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"errors"
"fmt"
"net/http"
+ "os"
"path"
+ "path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"time"
- "github.com/astaxie/beego/core/logs"
-
- "github.com/astaxie/beego/core/utils"
- beecontext "github.com/astaxie/beego/server/web/context"
- "github.com/astaxie/beego/server/web/context/param"
+ beecontext "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/context/param"
+ "github.com/astaxie/beego/logs"
+ "github.com/astaxie/beego/toolbox"
+ "github.com/astaxie/beego/utils"
)
// default filter execution points
@@ -132,22 +134,11 @@ type ControllerRegister struct {
enableFilter bool
filters [FinishRouter + 1][]*FilterRouter
pool sync.Pool
-
- // the filter created by FilterChain
- chainRoot *FilterRouter
-
- cfg *Config
}
// NewControllerRegister returns a new ControllerRegister.
-// Usually you should not use this method
-// please use NewControllerRegisterWithCfg
func NewControllerRegister() *ControllerRegister {
- return NewControllerRegisterWithCfg(BeeApp.Cfg)
-}
-
-func NewControllerRegisterWithCfg(cfg *Config) *ControllerRegister {
- res := &ControllerRegister{
+ return &ControllerRegister{
routers: make(map[string]*Tree),
policies: make(map[string]*Tree),
pool: sync.Pool{
@@ -155,10 +146,7 @@ func NewControllerRegisterWithCfg(cfg *Config) *ControllerRegister {
return beecontext.NewContext()
},
},
- cfg: cfg,
}
- res.chainRoot = newFilterRouter("/*", res.serveHttp, WithCaseSensitive(false))
- return res
}
// Add controller handler and pattern rules to ControllerRegister.
@@ -249,7 +237,7 @@ func (p *ControllerRegister) addWithMethodParams(pattern string, c ControllerInt
}
func (p *ControllerRegister) addToRouter(method, pattern string, r *ControllerInfo) {
- if !p.cfg.RouterCaseSensitive {
+ if !BConfig.RouterCaseSensitive {
pattern = strings.ToLower(pattern)
}
if t, ok := p.routers[method]; ok {
@@ -264,6 +252,45 @@ func (p *ControllerRegister) addToRouter(method, pattern string, r *ControllerIn
// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller
// Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
func (p *ControllerRegister) Include(cList ...ControllerInterface) {
+ if BConfig.RunMode == DEV {
+ skip := make(map[string]bool, 10)
+ wgopath := utils.GetGOPATHs()
+ go111module := os.Getenv(`GO111MODULE`)
+ for _, c := range cList {
+ reflectVal := reflect.ValueOf(c)
+ t := reflect.Indirect(reflectVal).Type()
+ // for go modules
+ if go111module == `on` {
+ pkgpath := filepath.Join(WorkPath, "..", t.PkgPath())
+ if utils.FileExists(pkgpath) {
+ if pkgpath != "" {
+ if _, ok := skip[pkgpath]; !ok {
+ skip[pkgpath] = true
+ parserPkg(pkgpath, t.PkgPath())
+ }
+ }
+ }
+ } else {
+ if len(wgopath) == 0 {
+ panic("you are in dev mode. So please set gopath")
+ }
+ pkgpath := ""
+ for _, wg := range wgopath {
+ wg, _ = filepath.EvalSymlinks(filepath.Join(wg, "src", t.PkgPath()))
+ if utils.FileExists(wg) {
+ pkgpath = wg
+ break
+ }
+ }
+ if pkgpath != "" {
+ if _, ok := skip[pkgpath]; !ok {
+ skip[pkgpath] = true
+ parserPkg(pkgpath, t.PkgPath())
+ }
+ }
+ }
+ }
+ }
for _, c := range cList {
reflectVal := reflect.ValueOf(c)
t := reflect.Indirect(reflectVal).Type()
@@ -271,7 +298,7 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) {
if comm, ok := GlobalControllerRouter[key]; ok {
for _, a := range comm {
for _, f := range a.Filters {
- p.InsertFilter(f.Pattern, f.Pos, f.Filter, WithReturnOnOutput(f.ReturnOnOutput), WithResetParams(f.ResetParams))
+ p.InsertFilter(f.Pattern, f.Pos, f.Filter, f.ReturnOnOutput, f.ResetParams)
}
p.addWithMethodParams(a.Router, c, a.MethodParams, strings.Join(a.AllowHTTPMethods, ",")+":"+a.Method)
@@ -461,32 +488,28 @@ func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface)
// params is for:
// 1. setting the returnOnOutput value (false allows multiple filters to execute)
// 2. determining whether or not params need to be reset.
-func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, opts ...FilterOpt) error {
- opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive))
- mr := newFilterRouter(pattern, filter, opts...)
+func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error {
+ mr := &FilterRouter{
+ tree: NewTree(),
+ pattern: pattern,
+ filterFunc: filter,
+ returnOnOutput: true,
+ }
+ if !BConfig.RouterCaseSensitive {
+ mr.pattern = strings.ToLower(pattern)
+ }
+
+ paramsLen := len(params)
+ if paramsLen > 0 {
+ mr.returnOnOutput = params[0]
+ }
+ if paramsLen > 1 {
+ mr.resetParams = params[1]
+ }
+ mr.tree.AddRouter(pattern, true)
return p.insertFilterRouter(pos, mr)
}
-// InsertFilterChain is similar to InsertFilter,
-// but it will using chainRoot.filterFunc as input to build a new filterFunc
-// for example, assume that chainRoot is funcA
-// and we add new FilterChain
-// fc := func(next) {
-// return func(ctx) {
-// // do something
-// next(ctx)
-// // do something
-// }
-// }
-func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, opts ...FilterOpt) {
- root := p.chainRoot
- filterFunc := chain(root.filterFunc)
- opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive))
- p.chainRoot = newFilterRouter(pattern, filterFunc, opts...)
- p.chainRoot.next = root
-
-}
-
// add Filter into
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) {
if pos < BeforeStatic || pos > FinishRouter {
@@ -645,9 +668,23 @@ func (p *ControllerRegister) getURL(t *Tree, url, controllerName, methodName str
func (p *ControllerRegister) execFilter(context *beecontext.Context, urlPath string, pos int) (started bool) {
var preFilterParams map[string]string
for _, filterR := range p.filters[pos] {
- b, done := filterR.filter(context, urlPath, preFilterParams)
- if done {
- return b
+ if filterR.returnOnOutput && context.ResponseWriter.Started {
+ return true
+ }
+ if filterR.resetParams {
+ preFilterParams = context.Input.Params()
+ }
+ if ok := filterR.ValidRouter(urlPath, context); ok {
+ filterR.filterFunc(context)
+ if filterR.resetParams {
+ context.Input.ResetParams()
+ for k, v := range preFilterParams {
+ context.Input.SetParam(k, v)
+ }
+ }
+ }
+ if filterR.returnOnOutput && context.ResponseWriter.Started {
+ return true
}
}
return false
@@ -655,21 +692,7 @@ func (p *ControllerRegister) execFilter(context *beecontext.Context, urlPath str
// Implement http.Handler interface.
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
-
- ctx := p.GetContext()
-
- ctx.Reset(rw, r)
- defer p.GiveBackContext(ctx)
-
- var preFilterParams map[string]string
- p.chainRoot.filter(ctx, p.getUrlPath(ctx), preFilterParams)
-}
-
-func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
- var err error
startTime := time.Now()
- r := ctx.Request
- rw := ctx.ResponseWriter.ResponseWriter
var (
runRouter reflect.Type
findRouter bool
@@ -678,118 +701,102 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
routerInfo *ControllerInfo
isRunnable bool
)
+ context := p.GetContext()
- if p.cfg.RecoverFunc != nil {
- defer p.cfg.RecoverFunc(ctx, p.cfg)
+ context.Reset(rw, r)
+
+ defer p.GiveBackContext(context)
+ if BConfig.RecoverFunc != nil {
+ defer BConfig.RecoverFunc(context)
}
- ctx.Output.EnableGzip = p.cfg.EnableGzip
+ context.Output.EnableGzip = BConfig.EnableGzip
- if p.cfg.RunMode == DEV {
- ctx.Output.Header("Server", p.cfg.ServerName)
+ if BConfig.RunMode == DEV {
+ context.Output.Header("Server", BConfig.ServerName)
}
- urlPath := p.getUrlPath(ctx)
+ var urlPath = r.URL.Path
+
+ if !BConfig.RouterCaseSensitive {
+ urlPath = strings.ToLower(urlPath)
+ }
// filter wrong http method
if !HTTPMETHOD[r.Method] {
- exception("405", ctx)
+ exception("405", context)
goto Admin
}
// filter for static file
- if len(p.filters[BeforeStatic]) > 0 && p.execFilter(ctx, urlPath, BeforeStatic) {
+ if len(p.filters[BeforeStatic]) > 0 && p.execFilter(context, urlPath, BeforeStatic) {
goto Admin
}
- serverStaticRouter(ctx)
+ serverStaticRouter(context)
- if ctx.ResponseWriter.Started {
+ if context.ResponseWriter.Started {
findRouter = true
goto Admin
}
if r.Method != http.MethodGet && r.Method != http.MethodHead {
-
- if ctx.Input.IsUpload() {
- ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter,
- ctx.Input.Context.Request.Body,
- p.cfg.MaxUploadSize)
- } else if p.cfg.CopyRequestBody {
- // connection will close if the incoming data are larger (RFC 7231, 6.5.11)
- if r.ContentLength > p.cfg.MaxMemory {
- logs.Error(errors.New("payload too large"))
- exception("413", ctx)
- goto Admin
- }
- ctx.Input.CopyBody(p.cfg.MaxMemory)
- } else {
- ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter,
- ctx.Input.Context.Request.Body,
- p.cfg.MaxMemory)
- }
-
- err = ctx.Input.ParseFormOrMultiForm(p.cfg.MaxMemory)
- if err != nil {
- logs.Error(err)
- if strings.Contains(err.Error(), `http: request body too large`) {
- exception("413", ctx)
- } else {
- exception("500", ctx)
- }
- goto Admin
+ if BConfig.CopyRequestBody && !context.Input.IsUpload() {
+ context.Input.CopyBody(BConfig.MaxMemory)
}
+ context.Input.ParseFormOrMulitForm(BConfig.MaxMemory)
}
// session init
- if p.cfg.WebConfig.Session.SessionOn {
- ctx.Input.CruSession, err = GlobalSessions.SessionStart(rw, r)
+ if BConfig.WebConfig.Session.SessionOn {
+ var err error
+ context.Input.CruSession, err = GlobalSessions.SessionStart(rw, r)
if err != nil {
logs.Error(err)
- exception("503", ctx)
+ exception("503", context)
goto Admin
}
defer func() {
- if ctx.Input.CruSession != nil {
- ctx.Input.CruSession.SessionRelease(nil, rw)
+ if context.Input.CruSession != nil {
+ context.Input.CruSession.SessionRelease(rw)
}
}()
}
- if len(p.filters[BeforeRouter]) > 0 && p.execFilter(ctx, urlPath, BeforeRouter) {
+ if len(p.filters[BeforeRouter]) > 0 && p.execFilter(context, urlPath, BeforeRouter) {
goto Admin
}
// User can define RunController and RunMethod in filter
- if ctx.Input.RunController != nil && ctx.Input.RunMethod != "" {
+ if context.Input.RunController != nil && context.Input.RunMethod != "" {
findRouter = true
- runMethod = ctx.Input.RunMethod
- runRouter = ctx.Input.RunController
+ runMethod = context.Input.RunMethod
+ runRouter = context.Input.RunController
} else {
- routerInfo, findRouter = p.FindRouter(ctx)
+ routerInfo, findRouter = p.FindRouter(context)
}
// if no matches to url, throw a not found exception
if !findRouter {
- exception("404", ctx)
+ exception("404", context)
goto Admin
}
- if splat := ctx.Input.Param(":splat"); splat != "" {
+ if splat := context.Input.Param(":splat"); splat != "" {
for k, v := range strings.Split(splat, "/") {
- ctx.Input.SetParam(strconv.Itoa(k), v)
+ context.Input.SetParam(strconv.Itoa(k), v)
}
}
if routerInfo != nil {
// store router pattern into context
- ctx.Input.SetData("RouterPattern", routerInfo.pattern)
+ context.Input.SetData("RouterPattern", routerInfo.pattern)
}
// execute middleware filters
- if len(p.filters[BeforeExec]) > 0 && p.execFilter(ctx, urlPath, BeforeExec) {
+ if len(p.filters[BeforeExec]) > 0 && p.execFilter(context, urlPath, BeforeExec) {
goto Admin
}
// check policies
- if p.execPolicy(ctx, urlPath) {
+ if p.execPolicy(context, urlPath) {
goto Admin
}
@@ -797,22 +804,22 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
if routerInfo.routerType == routerTypeRESTFul {
if _, ok := routerInfo.methods[r.Method]; ok {
isRunnable = true
- routerInfo.runFunction(ctx)
+ routerInfo.runFunction(context)
} else {
- exception("405", ctx)
+ exception("405", context)
goto Admin
}
} else if routerInfo.routerType == routerTypeHandler {
isRunnable = true
- routerInfo.handler.ServeHTTP(ctx.ResponseWriter, ctx.Request)
+ routerInfo.handler.ServeHTTP(context.ResponseWriter, context.Request)
} else {
runRouter = routerInfo.controllerType
methodParams = routerInfo.methodParams
method := r.Method
- if r.Method == http.MethodPost && ctx.Input.Query("_method") == http.MethodPut {
+ if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodPut {
method = http.MethodPut
}
- if r.Method == http.MethodPost && ctx.Input.Query("_method") == http.MethodDelete {
+ if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodDelete {
method = http.MethodDelete
}
if m, ok := routerInfo.methods[method]; ok {
@@ -841,23 +848,23 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
}
// call the controller init function
- execController.Init(ctx, runRouter.Name(), runMethod, execController)
+ execController.Init(context, runRouter.Name(), runMethod, execController)
// call prepare function
execController.Prepare()
// if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
- if p.cfg.WebConfig.EnableXSRF {
+ if BConfig.WebConfig.EnableXSRF {
execController.XSRFToken()
if r.Method == http.MethodPost || r.Method == http.MethodDelete || r.Method == http.MethodPut ||
- (r.Method == http.MethodPost && (ctx.Input.Query("_method") == http.MethodDelete || ctx.Input.Query("_method") == http.MethodPut)) {
+ (r.Method == http.MethodPost && (context.Input.Query("_method") == http.MethodDelete || context.Input.Query("_method") == http.MethodPut)) {
execController.CheckXSRFCookie()
}
}
execController.URLMapping()
- if !ctx.ResponseWriter.Started {
+ if !context.ResponseWriter.Started {
// exec main logic
switch runMethod {
case http.MethodGet:
@@ -880,19 +887,19 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
if !execController.HandlerFunc(runMethod) {
vc := reflect.ValueOf(execController)
method := vc.MethodByName(runMethod)
- in := param.ConvertParams(methodParams, method.Type(), ctx)
+ in := param.ConvertParams(methodParams, method.Type(), context)
out := method.Call(in)
// For backward compatibility we only handle response if we had incoming methodParams
if methodParams != nil {
- p.handleParamResponse(ctx, execController, out)
+ p.handleParamResponse(context, execController, out)
}
}
}
// render template
- if !ctx.ResponseWriter.Started && ctx.Output.Status == 0 {
- if p.cfg.WebConfig.AutoRender {
+ if !context.ResponseWriter.Started && context.Output.Status == 0 {
+ if BConfig.WebConfig.AutoRender {
if err := execController.Render(); err != nil {
logs.Error(err)
}
@@ -905,27 +912,27 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) {
}
// execute middleware filters
- if len(p.filters[AfterExec]) > 0 && p.execFilter(ctx, urlPath, AfterExec) {
+ if len(p.filters[AfterExec]) > 0 && p.execFilter(context, urlPath, AfterExec) {
goto Admin
}
- if len(p.filters[FinishRouter]) > 0 && p.execFilter(ctx, urlPath, FinishRouter) {
+ if len(p.filters[FinishRouter]) > 0 && p.execFilter(context, urlPath, FinishRouter) {
goto Admin
}
Admin:
// admin module record QPS
- statusCode := ctx.ResponseWriter.Status
+ statusCode := context.ResponseWriter.Status
if statusCode == 0 {
statusCode = 200
}
- LogAccess(ctx, &startTime, statusCode)
+ LogAccess(context, &startTime, statusCode)
timeDur := time.Since(startTime)
- ctx.ResponseWriter.Elapsed = timeDur
- if p.cfg.Listen.EnableAdmin {
+ context.ResponseWriter.Elapsed = timeDur
+ if BConfig.Listen.EnableAdmin {
pattern := ""
if routerInfo != nil {
pattern = routerInfo.pattern
@@ -936,14 +943,14 @@ Admin:
if runRouter != nil {
routerName = runRouter.Name()
}
- go StatisticsMap.AddStatistics(r.Method, r.URL.Path, routerName, timeDur)
+ go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, routerName, timeDur)
}
}
- if p.cfg.RunMode == DEV && !p.cfg.Log.AccessLogs {
+ if BConfig.RunMode == DEV && !BConfig.Log.AccessLogs {
match := map[bool]string{true: "match", false: "nomatch"}
devInfo := fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s",
- ctx.Input.IP(),
+ context.Input.IP(),
logs.ColorByStatus(statusCode), statusCode, logs.ResetColor(),
timeDur.String(),
match[findRouter],
@@ -956,19 +963,11 @@ Admin:
logs.Debug(devInfo)
}
// Call WriteHeader if status code has been set changed
- if ctx.Output.Status != 0 {
- ctx.ResponseWriter.WriteHeader(ctx.Output.Status)
+ if context.Output.Status != 0 {
+ context.ResponseWriter.WriteHeader(context.Output.Status)
}
}
-func (p *ControllerRegister) getUrlPath(ctx *beecontext.Context) string {
- urlPath := ctx.Request.URL.Path
- if !p.cfg.RouterCaseSensitive {
- urlPath = strings.ToLower(urlPath)
- }
- return urlPath
-}
-
func (p *ControllerRegister) handleParamResponse(context *beecontext.Context, execController ControllerInterface, results []reflect.Value) {
// looping in reverse order for the case when both error and value are returned and error sets the response status code
for i := len(results) - 1; i >= 0; i-- {
@@ -986,7 +985,7 @@ func (p *ControllerRegister) handleParamResponse(context *beecontext.Context, ex
// FindRouter Find Router info for URL
func (p *ControllerRegister) FindRouter(context *beecontext.Context) (routerInfo *ControllerInfo, isFind bool) {
var urlPath = context.Input.URL()
- if !p.cfg.RouterCaseSensitive {
+ if !BConfig.RouterCaseSensitive {
urlPath = strings.ToLower(urlPath)
}
httpMethod := context.Input.Method()
@@ -1012,5 +1011,36 @@ func toURL(params map[string]string) string {
// LogAccess logging info HTTP Access
func LogAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) {
- BeeApp.LogAccess(ctx, startTime, statusCode)
+ // Skip logging if AccessLogs config is false
+ if !BConfig.Log.AccessLogs {
+ return
+ }
+ // Skip logging static requests unless EnableStaticLogs config is true
+ if !BConfig.Log.EnableStaticLogs && DefaultAccessLogFilter.Filter(ctx) {
+ return
+ }
+ var (
+ requestTime time.Time
+ elapsedTime time.Duration
+ r = ctx.Request
+ )
+ if startTime != nil {
+ requestTime = *startTime
+ elapsedTime = time.Since(*startTime)
+ }
+ record := &logs.AccessLogRecord{
+ RemoteAddr: ctx.Input.IP(),
+ RequestTime: requestTime,
+ RequestMethod: r.Method,
+ Request: fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto),
+ ServerProtocol: r.Proto,
+ Host: r.Host,
+ Status: statusCode,
+ ElapsedTime: elapsedTime,
+ HTTPReferrer: r.Header.Get("Referer"),
+ HTTPUserAgent: r.Header.Get("User-Agent"),
+ RemoteUser: r.Header.Get("Remote-User"),
+ BodyBytesSent: 0, // @todo this one is missing!
+ }
+ logs.AccessLog(record, BConfig.Log.AccessLogsFormat)
}
diff --git a/server/web/router_test.go b/router_test.go
similarity index 88%
rename from server/web/router_test.go
rename to router_test.go
index 59ccd1fc..2797b33a 100644
--- a/server/web/router_test.go
+++ b/router_test.go
@@ -12,18 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
- "bytes"
"net/http"
"net/http/httptest"
"strings"
"testing"
- "github.com/astaxie/beego/core/logs"
-
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/logs"
)
type TestController struct {
@@ -73,6 +71,7 @@ func (tc *TestController) GetEmptyBody() {
tc.Ctx.Output.Body(res)
}
+
type JSONController struct {
Controller
}
@@ -212,23 +211,6 @@ func TestAutoExtFunc(t *testing.T) {
}
}
-func TestEscape(t *testing.T) {
-
- r, _ := http.NewRequest("GET", "/search/%E4%BD%A0%E5%A5%BD", nil)
- w := httptest.NewRecorder()
-
- handler := NewControllerRegister()
- handler.Get("/search/:keyword(.+)", func(ctx *context.Context) {
- value := ctx.Input.Param(":keyword")
- ctx.Output.Body([]byte(value))
- })
- handler.ServeHTTP(w, r)
- str := w.Body.String()
- if str != "你好" {
- t.Errorf("incorrect, %s", str)
- }
-}
-
func TestRouteOk(t *testing.T) {
r, _ := http.NewRequest("GET", "/person/anderson/thomas?learn=kungfu", nil)
@@ -381,7 +363,7 @@ func TestRouterHandlerAll(t *testing.T) {
}
//
-// Benchmarks NewHttpSever:
+// Benchmarks NewApp:
//
func beegoFilterFunc(ctx *context.Context) {
@@ -440,7 +422,7 @@ func TestInsertFilter(t *testing.T) {
testName := "TestInsertFilter"
mux := NewControllerRegister()
- mux.InsertFilter("*", BeforeRouter, func(*context.Context) {}, WithReturnOnOutput(true))
+ mux.InsertFilter("*", BeforeRouter, func(*context.Context) {})
if !mux.filters[BeforeRouter][0].returnOnOutput {
t.Errorf(
"%s: passing no variadic params should set returnOnOutput to true",
@@ -453,7 +435,7 @@ func TestInsertFilter(t *testing.T) {
}
mux = NewControllerRegister()
- mux.InsertFilter("*", BeforeRouter, func(*context.Context) {}, WithReturnOnOutput(false))
+ mux.InsertFilter("*", BeforeRouter, func(*context.Context) {}, false)
if mux.filters[BeforeRouter][0].returnOnOutput {
t.Errorf(
"%s: passing false as 1st variadic param should set returnOnOutput to false",
@@ -461,7 +443,7 @@ func TestInsertFilter(t *testing.T) {
}
mux = NewControllerRegister()
- mux.InsertFilter("*", BeforeRouter, func(*context.Context) {}, WithReturnOnOutput(true), WithResetParams(true))
+ mux.InsertFilter("*", BeforeRouter, func(*context.Context) {}, true, true)
if !mux.filters[BeforeRouter][0].resetParams {
t.Errorf(
"%s: passing true as 2nd variadic param should set resetParams to true",
@@ -478,7 +460,7 @@ func TestParamResetFilter(t *testing.T) {
mux := NewControllerRegister()
- mux.InsertFilter("*", BeforeExec, beegoResetParams, WithReturnOnOutput(true), WithResetParams(true))
+ mux.InsertFilter("*", BeforeExec, beegoResetParams, true, true)
mux.Get(route, beegoHandleResetParams)
@@ -531,8 +513,8 @@ func TestFilterBeforeExec(t *testing.T) {
url := "/beforeExec"
mux := NewControllerRegister()
- mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput, WithReturnOnOutput(true))
- mux.InsertFilter(url, BeforeExec, beegoBeforeExec1, WithReturnOnOutput(true))
+ mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput)
+ mux.InsertFilter(url, BeforeExec, beegoBeforeExec1)
mux.Get(url, beegoFilterFunc)
@@ -559,7 +541,7 @@ func TestFilterAfterExec(t *testing.T) {
mux := NewControllerRegister()
mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput)
mux.InsertFilter(url, BeforeExec, beegoFilterNoOutput)
- mux.InsertFilter(url, AfterExec, beegoAfterExec1, WithReturnOnOutput(false))
+ mux.InsertFilter(url, AfterExec, beegoAfterExec1, false)
mux.Get(url, beegoFilterFunc)
@@ -587,10 +569,10 @@ func TestFilterFinishRouter(t *testing.T) {
url := "/finishRouter"
mux := NewControllerRegister()
- mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput, WithReturnOnOutput(true))
- mux.InsertFilter(url, BeforeExec, beegoFilterNoOutput, WithReturnOnOutput(true))
- mux.InsertFilter(url, AfterExec, beegoFilterNoOutput, WithReturnOnOutput(true))
- mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, WithReturnOnOutput(true))
+ mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput)
+ mux.InsertFilter(url, BeforeExec, beegoFilterNoOutput)
+ mux.InsertFilter(url, AfterExec, beegoFilterNoOutput)
+ mux.InsertFilter(url, FinishRouter, beegoFinishRouter1)
mux.Get(url, beegoFilterFunc)
@@ -621,7 +603,7 @@ func TestFilterFinishRouterMultiFirstOnly(t *testing.T) {
url := "/finishRouterMultiFirstOnly"
mux := NewControllerRegister()
- mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, WithReturnOnOutput(false))
+ mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, false)
mux.InsertFilter(url, FinishRouter, beegoFinishRouter2)
mux.Get(url, beegoFilterFunc)
@@ -648,8 +630,8 @@ func TestFilterFinishRouterMulti(t *testing.T) {
url := "/finishRouterMulti"
mux := NewControllerRegister()
- mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, WithReturnOnOutput(false))
- mux.InsertFilter(url, FinishRouter, beegoFinishRouter2, WithReturnOnOutput(false))
+ mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, false)
+ mux.InsertFilter(url, FinishRouter, beegoFinishRouter2, false)
mux.Get(url, beegoFilterFunc)
@@ -674,14 +656,17 @@ func beegoBeforeRouter1(ctx *context.Context) {
ctx.WriteString("|BeforeRouter1")
}
+
func beegoBeforeExec1(ctx *context.Context) {
ctx.WriteString("|BeforeExec1")
}
+
func beegoAfterExec1(ctx *context.Context) {
ctx.WriteString("|AfterExec1")
}
+
func beegoFinishRouter1(ctx *context.Context) {
ctx.WriteString("|FinishRouter1")
}
@@ -724,29 +709,3 @@ func TestYAMLPrepare(t *testing.T) {
t.Errorf(w.Body.String())
}
}
-
-func TestRouterEntityTooLargeCopyBody(t *testing.T) {
- _MaxMemory := BConfig.MaxMemory
- _CopyRequestBody := BConfig.CopyRequestBody
- BConfig.CopyRequestBody = true
- BConfig.MaxMemory = 20
-
- BeeApp.Cfg.CopyRequestBody = true
- BeeApp.Cfg.MaxMemory = 20
- b := bytes.NewBuffer([]byte("barbarbarbarbarbarbarbarbarbar"))
- r, _ := http.NewRequest("POST", "/user/123", b)
- w := httptest.NewRecorder()
-
- handler := NewControllerRegister()
- handler.Post("/user/:id", func(ctx *context.Context) {
- ctx.Output.Body([]byte(ctx.Input.Param(":id")))
- })
- handler.ServeHTTP(w, r)
-
- BConfig.CopyRequestBody = _CopyRequestBody
- BConfig.MaxMemory = _MaxMemory
-
- if w.Code != http.StatusRequestEntityTooLarge {
- t.Errorf("TestRouterRequestEntityTooLarge can't run")
- }
-}
diff --git a/scripts/gobuild.sh b/scripts/gobuild.sh
new file mode 100755
index 00000000..031eafc2
--- /dev/null
+++ b/scripts/gobuild.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a change, please go to the
+# common-files repo, make the change there and check it in. Then come back to this repo and run
+# "make update-common".
+
+# Copyright Istio Authors. 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.
+
+# This script builds and version stamps the output
+
+# adatp to beego
+
+VERBOSE=${VERBOSE:-"0"}
+V=""
+if [[ "${VERBOSE}" == "1" ]];then
+ V="-x"
+ set -x
+fi
+
+SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+OUT=${1:?"output path"}
+shift
+
+set -e
+
+BUILD_GOOS=${GOOS:-linux}
+BUILD_GOARCH=${GOARCH:-amd64}
+GOBINARY=${GOBINARY:-go}
+GOPKG="$GOPATH/pkg"
+BUILDINFO=${BUILDINFO:-""}
+STATIC=${STATIC:-1}
+LDFLAGS=${LDFLAGS:--extldflags -static}
+GOBUILDFLAGS=${GOBUILDFLAGS:-""}
+# Split GOBUILDFLAGS by spaces into an array called GOBUILDFLAGS_ARRAY.
+IFS=' ' read -r -a GOBUILDFLAGS_ARRAY <<< "$GOBUILDFLAGS"
+
+GCFLAGS=${GCFLAGS:-}
+export CGO_ENABLED=0
+
+if [[ "${STATIC}" != "1" ]];then
+ LDFLAGS=""
+fi
+
+# gather buildinfo if not already provided
+# For a release build BUILDINFO should be produced
+# at the beginning of the build and used throughout
+if [[ -z ${BUILDINFO} ]];then
+ BUILDINFO=$(mktemp)
+ "${SCRIPTPATH}/report_build_info.sh" > "${BUILDINFO}"
+fi
+
+
+# BUILD LD_EXTRAFLAGS
+LD_EXTRAFLAGS=""
+
+while read -r line; do
+ LD_EXTRAFLAGS="${LD_EXTRAFLAGS} -X ${line}"
+done < "${BUILDINFO}"
+
+# verify go version before build
+# NB. this was copied verbatim from Kubernetes hack
+minimum_go_version=go1.13 # supported patterns: go1.x, go1.x.x (x should be a number)
+IFS=" " read -ra go_version <<< "$(${GOBINARY} version)"
+if [[ "${minimum_go_version}" != $(echo -e "${minimum_go_version}\n${go_version[2]}" | sort -s -t. -k 1,1 -k 2,2n -k 3,3n | head -n1) && "${go_version[2]}" != "devel" ]]; then
+ echo "Warning: Detected that you are using an older version of the Go compiler. Beego requires ${minimum_go_version} or greater."
+fi
+
+CURRENT_BRANCH=$(git branch | grep '*')
+CURRENT_BRANCH=${CURRENT_BRANCH:2}
+
+BUILD_TIME=$(date +%Y-%m-%d--%T)
+
+LD_EXTRAFLAGS="${LD_EXTRAFLAGS} -X github.com/astaxie/beego.GoVersion=${go_version[2]:2}"
+LD_EXTRAFLAGS="${LD_EXTRAFLAGS} -X github.com/astaxie/beego.GitBranch=${CURRENT_BRANCH}"
+LD_EXTRAFLAGS="${LD_EXTRAFLAGS} -X github.com/astaxie/beego.BuildTime=$BUILD_TIME"
+
+OPTIMIZATION_FLAGS="-trimpath"
+if [ "${DEBUG}" == "1" ]; then
+ OPTIMIZATION_FLAGS=""
+fi
+
+
+
+echo "BUILD_GOARCH: $BUILD_GOARCH"
+echo "GOPKG: $GOPKG"
+echo "LD_EXTRAFLAGS: $LD_EXTRAFLAGS"
+echo "GO_VERSION: ${go_version[2]}"
+echo "BRANCH: $CURRENT_BRANCH"
+echo "BUILD_TIME: $BUILD_TIME"
+
+time GOOS=${BUILD_GOOS} GOARCH=${BUILD_GOARCH} ${GOBINARY} build \
+ ${V} "${GOBUILDFLAGS_ARRAY[@]}" ${GCFLAGS:+-gcflags "${GCFLAGS}"} \
+ -o "${OUT}" \
+ ${OPTIMIZATION_FLAGS} \
+ -pkgdir="${GOPKG}/${BUILD_GOOS}_${BUILD_GOARCH}" \
+ -ldflags "${LDFLAGS} ${LD_EXTRAFLAGS}" "${@}"
\ No newline at end of file
diff --git a/scripts/report_build_info.sh b/scripts/report_build_info.sh
new file mode 100755
index 00000000..65ba3748
--- /dev/null
+++ b/scripts/report_build_info.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a change, please go to the
+# common-files repo, make the change there and check it in. Then come back to this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# 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.
+
+# adapt to beego
+
+if BUILD_GIT_REVISION=$(git rev-parse HEAD 2> /dev/null); then
+ if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
+ BUILD_GIT_REVISION=${BUILD_GIT_REVISION}"-dirty"
+ fi
+else
+ BUILD_GIT_REVISION=unknown
+fi
+
+# Check for local changes
+if git diff-index --quiet HEAD --; then
+ tree_status="Clean"
+else
+ tree_status="Modified"
+fi
+
+# security wanted VERSION='unknown'
+VERSION="${BUILD_GIT_REVISION}"
+if [[ -n ${BEEGO_VERSION} ]]; then
+ VERSION="${BEEGO_VERSION}"
+fi
+
+GIT_DESCRIBE_TAG=$(git describe --tags)
+
+echo "github.com/astaxie/beego.BuildVersion=${VERSION}"
+echo "github.com/astaxie/beego.BuildGitRevision=${BUILD_GIT_REVISION}"
+echo "github.com/astaxie/beego.BuildStatus=${tree_status}"
+echo "github.com/astaxie/beego.BuildTag=${GIT_DESCRIBE_TAG}"
\ No newline at end of file
diff --git a/server/web/LICENSE b/server/web/LICENSE
deleted file mode 100644
index 5dbd4243..00000000
--- a/server/web/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2014 astaxie
-
-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.
\ No newline at end of file
diff --git a/server/web/admin.go b/server/web/admin.go
deleted file mode 100644
index 1b06f486..00000000
--- a/server/web/admin.go
+++ /dev/null
@@ -1,126 +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 web
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "time"
-
- "github.com/astaxie/beego/core/logs"
-)
-
-// BeeAdminApp is the default adminApp used by admin module.
-var beeAdminApp *adminApp
-
-// FilterMonitorFunc is default monitor filter when admin module is enable.
-// if this func returns, admin module records qps for this request by condition of this function logic.
-// usage:
-// func MyFilterMonitor(method, requestPath string, t time.Duration, pattern string, statusCode int) bool {
-// if method == "POST" {
-// return false
-// }
-// if t.Nanoseconds() < 100 {
-// return false
-// }
-// if strings.HasPrefix(requestPath, "/astaxie") {
-// return false
-// }
-// return true
-// }
-// beego.FilterMonitorFunc = MyFilterMonitor.
-var FilterMonitorFunc func(string, string, time.Duration, string, int) bool
-
-func init() {
-
- FilterMonitorFunc = func(string, string, time.Duration, string, int) bool { return true }
-
-}
-
-func list(root string, p interface{}, m M) {
- pt := reflect.TypeOf(p)
- pv := reflect.ValueOf(p)
- if pt.Kind() == reflect.Ptr {
- pt = pt.Elem()
- pv = pv.Elem()
- }
- for i := 0; i < pv.NumField(); i++ {
- var key string
- if root == "" {
- key = pt.Field(i).Name
- } else {
- key = root + "." + pt.Field(i).Name
- }
- if pv.Field(i).Kind() == reflect.Struct {
- list(key, pv.Field(i).Interface(), m)
- } else {
- m[key] = pv.Field(i).Interface()
- }
- }
-}
-
-func writeJSON(rw http.ResponseWriter, jsonData []byte) {
- rw.Header().Set("Content-Type", "application/json")
- rw.Write(jsonData)
-}
-
-// adminApp is an http.HandlerFunc map used as beeAdminApp.
-type adminApp struct {
- *HttpServer
-}
-
-// Route adds http.HandlerFunc to adminApp with url pattern.
-func (admin *adminApp) Run() {
-
- // if len(task.AdminTaskList) > 0 {
- // task.StartTask()
- // }
- logs.Warning("now we don't start tasks here, if you use task module," +
- " please invoke task.StartTask, or task will not be executed")
-
- addr := BConfig.Listen.AdminAddr
-
- if BConfig.Listen.AdminPort != 0 {
- addr = fmt.Sprintf("%s:%d", BConfig.Listen.AdminAddr, BConfig.Listen.AdminPort)
- }
-
- logs.Info("Admin server Running on %s", addr)
-
- admin.HttpServer.Run(addr)
-}
-
-func registerAdmin() error {
- if BConfig.Listen.EnableAdmin {
-
- c := &adminController{
- servers: make([]*HttpServer, 0, 2),
- }
- beeAdminApp = &adminApp{
- HttpServer: NewHttpServerWithCfg(BConfig),
- }
- // keep in mind that all data should be html escaped to avoid XSS attack
- beeAdminApp.Router("/", c, "get:AdminIndex")
- beeAdminApp.Router("/qps", c, "get:QpsIndex")
- beeAdminApp.Router("/prof", c, "get:ProfIndex")
- beeAdminApp.Router("/healthcheck", c, "get:Healthcheck")
- beeAdminApp.Router("/task", c, "get:TaskStatus")
- beeAdminApp.Router("/listconf", c, "get:ListConf")
- beeAdminApp.Router("/metrics", c, "get:PrometheusMetrics")
-
- go beeAdminApp.Run()
- }
- return nil
-}
diff --git a/server/web/admin_controller.go b/server/web/admin_controller.go
deleted file mode 100644
index 2998c8d4..00000000
--- a/server/web/admin_controller.go
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package web
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "strconv"
- "text/template"
-
- "github.com/prometheus/client_golang/prometheus/promhttp"
-
- "github.com/astaxie/beego/core/governor"
-)
-
-type adminController struct {
- Controller
- servers []*HttpServer
-}
-
-func (a *adminController) registerHttpServer(svr *HttpServer) {
- a.servers = append(a.servers, svr)
-}
-
-// ProfIndex is a http.Handler for showing profile command.
-// it's in url pattern "/prof" in admin module.
-func (a *adminController) ProfIndex() {
- rw, r := a.Ctx.ResponseWriter, a.Ctx.Request
- r.ParseForm()
- command := r.Form.Get("command")
- if command == "" {
- return
- }
-
- var (
- format = r.Form.Get("format")
- data = make(map[interface{}]interface{})
- result bytes.Buffer
- )
- governor.ProcessInput(command, &result)
- data["Content"] = template.HTMLEscapeString(result.String())
-
- if format == "json" && command == "gc summary" {
- dataJSON, err := json.Marshal(data)
- if err != nil {
- http.Error(rw, err.Error(), http.StatusInternalServerError)
- return
- }
- writeJSON(rw, dataJSON)
- return
- }
-
- data["Title"] = template.HTMLEscapeString(command)
- defaultTpl := defaultScriptsTpl
- if command == "gc summary" {
- defaultTpl = gcAjaxTpl
- }
- writeTemplate(rw, data, profillingTpl, defaultTpl)
-}
-
-func (a *adminController) PrometheusMetrics() {
- promhttp.Handler().ServeHTTP(a.Ctx.ResponseWriter, a.Ctx.Request)
-}
-
-// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
-// it's in "/task" pattern in admin module.
-func (a *adminController) TaskStatus() {
-
- rw, req := a.Ctx.ResponseWriter, a.Ctx.Request
-
- data := make(map[interface{}]interface{})
-
- // Run Task
- req.ParseForm()
- taskname := req.Form.Get("taskname")
- if taskname != "" {
- cmd := governor.GetCommand("task", "run")
- res := cmd.Execute(taskname)
- if res.IsSuccess() {
-
- data["Message"] = []string{"success",
- template.HTMLEscapeString(fmt.Sprintf("%s run success,Now the Status is %s",
- taskname, res.Content.(string)))}
-
- } else {
- data["Message"] = []string{"error", template.HTMLEscapeString(fmt.Sprintf("%s", res.Error))}
- }
- }
-
- // List Tasks
- content := make(M)
- resultList := governor.GetCommand("task", "list").Execute().Content.([][]string)
- var fields = []string{
- "Task Name",
- "Task Spec",
- "Task Status",
- "Last Time",
- "",
- }
-
- content["Fields"] = fields
- content["Data"] = resultList
- data["Content"] = content
- data["Title"] = "Tasks"
- writeTemplate(rw, data, tasksTpl, defaultScriptsTpl)
-}
-
-func (a *adminController) AdminIndex() {
- // AdminIndex is the default http.Handler for admin module.
- // it matches url pattern "/".
- writeTemplate(a.Ctx.ResponseWriter, map[interface{}]interface{}{}, indexTpl, defaultScriptsTpl)
-}
-
-// Healthcheck is a http.Handler calling health checking and showing the result.
-// it's in "/healthcheck" pattern in admin module.
-func (a *adminController) Healthcheck() {
- heathCheck(a.Ctx.ResponseWriter, a.Ctx.Request)
-}
-
-func heathCheck(rw http.ResponseWriter, r *http.Request) {
- var (
- result []string
- data = make(map[interface{}]interface{})
- resultList = new([][]string)
- content = M{
- "Fields": []string{"Name", "Message", "Status"},
- }
- )
-
- for name, h := range governor.AdminCheckList {
- if err := h.Check(); err != nil {
- result = []string{
- "error",
- template.HTMLEscapeString(name),
- template.HTMLEscapeString(err.Error()),
- }
- } else {
- result = []string{
- "success",
- template.HTMLEscapeString(name),
- "OK",
- }
- }
- *resultList = append(*resultList, result)
- }
-
- queryParams := r.URL.Query()
- jsonFlag := queryParams.Get("json")
- shouldReturnJSON, _ := strconv.ParseBool(jsonFlag)
-
- if shouldReturnJSON {
- response := buildHealthCheckResponseList(resultList)
- jsonResponse, err := json.Marshal(response)
-
- if err != nil {
- http.Error(rw, err.Error(), http.StatusInternalServerError)
- } else {
- writeJSON(rw, jsonResponse)
- }
- return
- }
-
- content["Data"] = resultList
- data["Content"] = content
- data["Title"] = "Health Check"
-
- writeTemplate(rw, data, healthCheckTpl, defaultScriptsTpl)
-}
-
-// QpsIndex is the http.Handler for writing qps statistics map result info in http.ResponseWriter.
-// it's registered with url pattern "/qps" in admin module.
-func (a *adminController) QpsIndex() {
- data := make(map[interface{}]interface{})
- data["Content"] = StatisticsMap.GetMap()
-
- // do html escape before display path, avoid xss
- if content, ok := (data["Content"]).(M); ok {
- if resultLists, ok := (content["Data"]).([][]string); ok {
- for i := range resultLists {
- if len(resultLists[i]) > 0 {
- resultLists[i][0] = template.HTMLEscapeString(resultLists[i][0])
- }
- }
- }
- }
- writeTemplate(a.Ctx.ResponseWriter, data, qpsTpl, defaultScriptsTpl)
-}
-
-// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
-// it's registered with url pattern "/listconf" in admin module.
-func (a *adminController) ListConf() {
- rw := a.Ctx.ResponseWriter
- r := a.Ctx.Request
- r.ParseForm()
- command := r.Form.Get("command")
- if command == "" {
- rw.Write([]byte("command not support"))
- return
- }
-
- data := make(map[interface{}]interface{})
- switch command {
- case "conf":
- m := make(M)
- list("BConfig", BConfig, m)
- m["appConfigPath"] = template.HTMLEscapeString(appConfigPath)
- m["appConfigProvider"] = template.HTMLEscapeString(appConfigProvider)
- tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
- tmpl = template.Must(tmpl.Parse(configTpl))
- tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
-
- data["Content"] = m
-
- tmpl.Execute(rw, data)
-
- case "router":
- content := BeeApp.PrintTree()
- content["Fields"] = []string{
- "Router Pattern",
- "Methods",
- "Controller",
- }
- data["Content"] = content
- data["Title"] = "Routers"
- writeTemplate(rw, data, routerAndFilterTpl, defaultScriptsTpl)
- case "filter":
- var (
- content = M{
- "Fields": []string{
- "Router Pattern",
- "Filter Function",
- },
- }
- )
-
- filterTypeData := BeeApp.reportFilter()
-
- filterTypes := make([]string, 0, len(filterTypeData))
- for k, _ := range filterTypeData {
- filterTypes = append(filterTypes, k)
- }
-
- content["Data"] = filterTypeData
- content["Methods"] = filterTypes
-
- data["Content"] = content
- data["Title"] = "Filters"
- writeTemplate(rw, data, routerAndFilterTpl, defaultScriptsTpl)
- default:
- rw.Write([]byte("command not support"))
- }
-}
-
-func writeTemplate(rw http.ResponseWriter, data map[interface{}]interface{}, tpls ...string) {
- tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
- for _, tpl := range tpls {
- tmpl = template.Must(tmpl.Parse(tpl))
- }
- tmpl.Execute(rw, data)
-}
-
-func buildHealthCheckResponseList(healthCheckResults *[][]string) []map[string]interface{} {
- response := make([]map[string]interface{}, len(*healthCheckResults))
-
- for i, healthCheckResult := range *healthCheckResults {
- currentResultMap := make(map[string]interface{})
-
- currentResultMap["name"] = healthCheckResult[0]
- currentResultMap["message"] = healthCheckResult[1]
- currentResultMap["status"] = healthCheckResult[2]
-
- response[i] = currentResultMap
- }
-
- return response
-
-}
-
-// PrintTree print all routers
-// Deprecated using BeeApp directly
-func PrintTree() M {
- return BeeApp.PrintTree()
-}
diff --git a/server/web/admin_test.go b/server/web/admin_test.go
deleted file mode 100644
index 5ef57323..00000000
--- a/server/web/admin_test.go
+++ /dev/null
@@ -1,249 +0,0 @@
-package web
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/core/governor"
-)
-
-type SampleDatabaseCheck struct {
-}
-
-type SampleCacheCheck struct {
-}
-
-func (dc *SampleDatabaseCheck) Check() error {
- return nil
-}
-
-func (cc *SampleCacheCheck) Check() error {
- return errors.New("no cache detected")
-}
-
-func TestList_01(t *testing.T) {
- m := make(M)
- list("BConfig", BConfig, m)
- t.Log(m)
- om := oldMap()
- for k, v := range om {
- if fmt.Sprint(m[k]) != fmt.Sprint(v) {
- t.Log(k, "old-key", v, "new-key", m[k])
- t.FailNow()
- }
- }
-}
-
-func oldMap() M {
- m := make(M)
- m["BConfig.AppName"] = BConfig.AppName
- m["BConfig.RunMode"] = BConfig.RunMode
- m["BConfig.RouterCaseSensitive"] = BConfig.RouterCaseSensitive
- m["BConfig.ServerName"] = BConfig.ServerName
- m["BConfig.RecoverPanic"] = BConfig.RecoverPanic
- m["BConfig.CopyRequestBody"] = BConfig.CopyRequestBody
- m["BConfig.EnableGzip"] = BConfig.EnableGzip
- m["BConfig.MaxMemory"] = BConfig.MaxMemory
- m["BConfig.EnableErrorsShow"] = BConfig.EnableErrorsShow
- m["BConfig.Listen.Graceful"] = BConfig.Listen.Graceful
- m["BConfig.Listen.ServerTimeOut"] = BConfig.Listen.ServerTimeOut
- m["BConfig.Listen.ListenTCP4"] = BConfig.Listen.ListenTCP4
- m["BConfig.Listen.EnableHTTP"] = BConfig.Listen.EnableHTTP
- m["BConfig.Listen.HTTPAddr"] = BConfig.Listen.HTTPAddr
- m["BConfig.Listen.HTTPPort"] = BConfig.Listen.HTTPPort
- m["BConfig.Listen.EnableHTTPS"] = BConfig.Listen.EnableHTTPS
- m["BConfig.Listen.HTTPSAddr"] = BConfig.Listen.HTTPSAddr
- m["BConfig.Listen.HTTPSPort"] = BConfig.Listen.HTTPSPort
- m["BConfig.Listen.HTTPSCertFile"] = BConfig.Listen.HTTPSCertFile
- m["BConfig.Listen.HTTPSKeyFile"] = BConfig.Listen.HTTPSKeyFile
- m["BConfig.Listen.EnableAdmin"] = BConfig.Listen.EnableAdmin
- m["BConfig.Listen.AdminAddr"] = BConfig.Listen.AdminAddr
- m["BConfig.Listen.AdminPort"] = BConfig.Listen.AdminPort
- m["BConfig.Listen.EnableFcgi"] = BConfig.Listen.EnableFcgi
- m["BConfig.Listen.EnableStdIo"] = BConfig.Listen.EnableStdIo
- m["BConfig.WebConfig.AutoRender"] = BConfig.WebConfig.AutoRender
- m["BConfig.WebConfig.EnableDocs"] = BConfig.WebConfig.EnableDocs
- m["BConfig.WebConfig.FlashName"] = BConfig.WebConfig.FlashName
- m["BConfig.WebConfig.FlashSeparator"] = BConfig.WebConfig.FlashSeparator
- m["BConfig.WebConfig.DirectoryIndex"] = BConfig.WebConfig.DirectoryIndex
- m["BConfig.WebConfig.StaticDir"] = BConfig.WebConfig.StaticDir
- m["BConfig.WebConfig.StaticExtensionsToGzip"] = BConfig.WebConfig.StaticExtensionsToGzip
- m["BConfig.WebConfig.StaticCacheFileSize"] = BConfig.WebConfig.StaticCacheFileSize
- m["BConfig.WebConfig.StaticCacheFileNum"] = BConfig.WebConfig.StaticCacheFileNum
- m["BConfig.WebConfig.TemplateLeft"] = BConfig.WebConfig.TemplateLeft
- m["BConfig.WebConfig.TemplateRight"] = BConfig.WebConfig.TemplateRight
- m["BConfig.WebConfig.ViewsPath"] = BConfig.WebConfig.ViewsPath
- m["BConfig.WebConfig.EnableXSRF"] = BConfig.WebConfig.EnableXSRF
- m["BConfig.WebConfig.XSRFExpire"] = BConfig.WebConfig.XSRFExpire
- m["BConfig.WebConfig.Session.SessionOn"] = BConfig.WebConfig.Session.SessionOn
- m["BConfig.WebConfig.Session.SessionProvider"] = BConfig.WebConfig.Session.SessionProvider
- m["BConfig.WebConfig.Session.SessionName"] = BConfig.WebConfig.Session.SessionName
- m["BConfig.WebConfig.Session.SessionGCMaxLifetime"] = BConfig.WebConfig.Session.SessionGCMaxLifetime
- m["BConfig.WebConfig.Session.SessionProviderConfig"] = BConfig.WebConfig.Session.SessionProviderConfig
- m["BConfig.WebConfig.Session.SessionCookieLifeTime"] = BConfig.WebConfig.Session.SessionCookieLifeTime
- m["BConfig.WebConfig.Session.SessionAutoSetCookie"] = BConfig.WebConfig.Session.SessionAutoSetCookie
- m["BConfig.WebConfig.Session.SessionDomain"] = BConfig.WebConfig.Session.SessionDomain
- m["BConfig.WebConfig.Session.SessionDisableHTTPOnly"] = BConfig.WebConfig.Session.SessionDisableHTTPOnly
- m["BConfig.Log.AccessLogs"] = BConfig.Log.AccessLogs
- m["BConfig.Log.EnableStaticLogs"] = BConfig.Log.EnableStaticLogs
- m["BConfig.Log.AccessLogsFormat"] = BConfig.Log.AccessLogsFormat
- m["BConfig.Log.FileLineNum"] = BConfig.Log.FileLineNum
- m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
- return m
-}
-
-func TestWriteJSON(t *testing.T) {
- t.Log("Testing the adding of JSON to the response")
-
- w := httptest.NewRecorder()
- originalBody := []int{1, 2, 3}
-
- res, _ := json.Marshal(originalBody)
-
- writeJSON(w, res)
-
- decodedBody := []int{}
- err := json.NewDecoder(w.Body).Decode(&decodedBody)
-
- if err != nil {
- t.Fatal("Could not decode response body into slice.")
- }
-
- for i := range decodedBody {
- if decodedBody[i] != originalBody[i] {
- t.Fatalf("Expected %d but got %d in decoded body slice", originalBody[i], decodedBody[i])
- }
- }
-}
-
-func TestHealthCheckHandlerDefault(t *testing.T) {
- endpointPath := "/healthcheck"
-
- governor.AddHealthCheck("database", &SampleDatabaseCheck{})
- governor.AddHealthCheck("cache", &SampleCacheCheck{})
-
- req, err := http.NewRequest("GET", endpointPath, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- w := httptest.NewRecorder()
-
- handler := http.HandlerFunc(heathCheck)
-
- handler.ServeHTTP(w, req)
-
- if status := w.Code; status != http.StatusOK {
- t.Errorf("handler returned wrong status code: got %v want %v",
- status, http.StatusOK)
- }
- if !strings.Contains(w.Body.String(), "database") {
- t.Errorf("Expected 'database' in generated template.")
- }
-
-}
-
-func TestBuildHealthCheckResponseList(t *testing.T) {
- healthCheckResults := [][]string{
- []string{
- "error",
- "Database",
- "Error occured whie starting the db",
- },
- []string{
- "success",
- "Cache",
- "Cache started successfully",
- },
- }
-
- responseList := buildHealthCheckResponseList(&healthCheckResults)
-
- if len(responseList) != len(healthCheckResults) {
- t.Errorf("invalid response map length: got %d want %d",
- len(responseList), len(healthCheckResults))
- }
-
- responseFields := []string{"name", "message", "status"}
-
- for _, response := range responseList {
- for _, field := range responseFields {
- _, ok := response[field]
- if !ok {
- t.Errorf("expected %s to be in the response %v", field, response)
- }
- }
-
- }
-
-}
-
-func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
-
- governor.AddHealthCheck("database", &SampleDatabaseCheck{})
- governor.AddHealthCheck("cache", &SampleCacheCheck{})
-
- req, err := http.NewRequest("GET", "/healthcheck?json=true", nil)
- if err != nil {
- t.Fatal(err)
- }
-
- w := httptest.NewRecorder()
-
- handler := http.HandlerFunc(heathCheck)
-
- handler.ServeHTTP(w, req)
- if status := w.Code; status != http.StatusOK {
- t.Errorf("handler returned wrong status code: got %v want %v",
- status, http.StatusOK)
- }
-
- decodedResponseBody := []map[string]interface{}{}
- expectedResponseBody := []map[string]interface{}{}
-
- expectedJSONString := []byte(`
- [
- {
- "message":"database",
- "name":"success",
- "status":"OK"
- },
- {
- "message":"cache",
- "name":"error",
- "status":"no cache detected"
- }
- ]
- `)
-
- json.Unmarshal(expectedJSONString, &expectedResponseBody)
-
- json.Unmarshal(w.Body.Bytes(), &decodedResponseBody)
-
- if len(expectedResponseBody) != len(decodedResponseBody) {
- t.Errorf("invalid response map length: got %d want %d",
- len(decodedResponseBody), len(expectedResponseBody))
- }
- assert.Equal(t, len(expectedResponseBody), len(decodedResponseBody))
- assert.Equal(t, 2, len(decodedResponseBody))
-
- var database, cache map[string]interface{}
- if decodedResponseBody[0]["message"] == "database" {
- database = decodedResponseBody[0]
- cache = decodedResponseBody[1]
- } else {
- database = decodedResponseBody[1]
- cache = decodedResponseBody[0]
- }
-
- assert.Equal(t, expectedResponseBody[0], database)
- assert.Equal(t, expectedResponseBody[1], cache)
-
-}
diff --git a/server/web/captcha/LICENSE b/server/web/captcha/LICENSE
deleted file mode 100644
index 0ad73ae0..00000000
--- a/server/web/captcha/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011-2014 Dmitry Chestnykh
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/server/web/captcha/README.md b/server/web/captcha/README.md
deleted file mode 100644
index dbc2026b..00000000
--- a/server/web/captcha/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# Captcha
-
-an example for use captcha
-
-```
-package controllers
-
-import (
- "github.com/astaxie/beego"
- "github.com/astaxie/beego/cache"
- "github.com/astaxie/beego/utils/captcha"
-)
-
-var cpt *captcha.Captcha
-
-func init() {
- // use beego cache system store the captcha data
- store := cache.NewMemoryCache()
- cpt = captcha.NewWithFilter("/captcha/", store)
-}
-
-type MainController struct {
- beego.Controller
-}
-
-func (this *MainController) Get() {
- this.TplName = "index.tpl"
-}
-
-func (this *MainController) Post() {
- this.TplName = "index.tpl"
-
- this.Data["Success"] = cpt.VerifyReq(this.Ctx.Request)
-}
-```
-
-template usage
-
-```
-{{.Success}}
-
-```
diff --git a/server/web/context/response.go b/server/web/context/response.go
deleted file mode 100644
index 7bd9a7e8..00000000
--- a/server/web/context/response.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package context
-
-import (
- "net/http"
- "strconv"
-)
-
-const (
- //BadRequest indicates HTTP error 400
- BadRequest StatusCode = http.StatusBadRequest
-
- //NotFound indicates HTTP error 404
- NotFound StatusCode = http.StatusNotFound
-)
-
-// StatusCode sets the HTTP response status code
-type StatusCode int
-
-func (s StatusCode) Error() string {
- return strconv.Itoa(int(s))
-}
-
-// Render sets the HTTP status code
-func (s StatusCode) Render(ctx *Context) {
- ctx.Output.SetStatus(int(s))
-}
diff --git a/server/web/doc.go b/server/web/doc.go
deleted file mode 100644
index a32bc576..00000000
--- a/server/web/doc.go
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-Package beego provide a MVC framework
-beego: an open-source, high-performance, modular, full-stack web framework
-
-It is used for rapid development of RESTful APIs, web apps and backend services in Go.
-beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding.
-
- package main
- import "github.com/astaxie/beego"
-
- func main() {
- beego.Run()
- }
-
-more information: http://beego.me
-*/
-package web
diff --git a/server/web/filter.go b/server/web/filter.go
deleted file mode 100644
index 967de8c9..00000000
--- a/server/web/filter.go
+++ /dev/null
@@ -1,134 +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 web
-
-import (
- "strings"
-
- "github.com/astaxie/beego/server/web/context"
-)
-
-// FilterChain is different from pure FilterFunc
-// when you use this, you must invoke next(ctx) inside the FilterFunc which is returned
-// And all those FilterChain will be invoked before other FilterFunc
-type FilterChain func(next FilterFunc) FilterFunc
-
-// FilterFunc defines a filter function which is invoked before the controller handler is executed.
-type FilterFunc func(ctx *context.Context)
-
-// FilterRouter defines a filter operation which is invoked before the controller handler is executed.
-// It can match the URL against a pattern, and execute a filter function
-// when a request with a matching URL arrives.
-type FilterRouter struct {
- filterFunc FilterFunc
- next *FilterRouter
- tree *Tree
- pattern string
- returnOnOutput bool
- resetParams bool
-}
-
-// params is for:
-// 1. setting the returnOnOutput value (false allows multiple filters to execute)
-// 2. determining whether or not params need to be reset.
-func newFilterRouter(pattern string, filter FilterFunc, opts ...FilterOpt) *FilterRouter {
- mr := &FilterRouter{
- tree: NewTree(),
- pattern: pattern,
- filterFunc: filter,
- }
-
- fos := &filterOpts{
- returnOnOutput: true,
- }
-
- for _, o := range opts {
- o(fos)
- }
-
- if !fos.routerCaseSensitive {
- mr.pattern = strings.ToLower(pattern)
- }
-
- mr.returnOnOutput = fos.returnOnOutput
- mr.resetParams = fos.resetParams
- mr.tree.AddRouter(pattern, true)
- return mr
-}
-
-// filter will check whether we need to execute the filter logic
-// return (started, done)
-func (f *FilterRouter) filter(ctx *context.Context, urlPath string, preFilterParams map[string]string) (bool, bool) {
- if f.returnOnOutput && ctx.ResponseWriter.Started {
- return true, true
- }
- if f.resetParams {
- preFilterParams = ctx.Input.Params()
- }
- if ok := f.ValidRouter(urlPath, ctx); ok {
- f.filterFunc(ctx)
- if f.resetParams {
- ctx.Input.ResetParams()
- for k, v := range preFilterParams {
- ctx.Input.SetParam(k, v)
- }
- }
- } else if f.next != nil {
- return f.next.filter(ctx, urlPath, preFilterParams)
- }
- if f.returnOnOutput && ctx.ResponseWriter.Started {
- return true, true
- }
- return false, false
-}
-
-// ValidRouter checks if the current request is matched by this filter.
-// If the request is matched, the values of the URL parameters defined
-// by the filter pattern are also returned.
-func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool {
- isOk := f.tree.Match(url, ctx)
- if isOk != nil {
- if b, ok := isOk.(bool); ok {
- return b
- }
- }
- return false
-}
-
-type filterOpts struct {
- returnOnOutput bool
- resetParams bool
- routerCaseSensitive bool
-}
-
-type FilterOpt func(opts *filterOpts)
-
-func WithReturnOnOutput(ret bool) FilterOpt {
- return func(opts *filterOpts) {
- opts.returnOnOutput = ret
- }
-}
-
-func WithResetParams(reset bool) FilterOpt {
- return func(opts *filterOpts) {
- opts.resetParams = reset
- }
-}
-
-func WithCaseSensitive(sensitive bool) FilterOpt {
- return func(opts *filterOpts) {
- opts.routerCaseSensitive = sensitive
- }
-}
diff --git a/server/web/filter/apiauth/apiauth_test.go b/server/web/filter/apiauth/apiauth_test.go
deleted file mode 100644
index 1f56cb0f..00000000
--- a/server/web/filter/apiauth/apiauth_test.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package apiauth
-
-import (
- "net/url"
- "testing"
-)
-
-func TestSignature(t *testing.T) {
- appsecret := "beego secret"
- method := "GET"
- RequestURL := "http://localhost/test/url"
- params := make(url.Values)
- params.Add("arg1", "hello")
- params.Add("arg2", "beego")
-
- signature := "mFdpvLh48ca4mDVEItE9++AKKQ/IVca7O/ZyyB8hR58="
- if Signature(appsecret, method, params, RequestURL) != signature {
- t.Error("Signature error")
- }
-}
diff --git a/server/web/filter/authz/authz_model.conf b/server/web/filter/authz/authz_model.conf
deleted file mode 100644
index d1b3dbd7..00000000
--- a/server/web/filter/authz/authz_model.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-[request_definition]
-r = sub, obj, act
-
-[policy_definition]
-p = sub, obj, act
-
-[role_definition]
-g = _, _
-
-[policy_effect]
-e = some(where (p.eft == allow))
-
-[matchers]
-m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
\ No newline at end of file
diff --git a/server/web/filter/authz/authz_policy.csv b/server/web/filter/authz/authz_policy.csv
deleted file mode 100644
index c062dd3e..00000000
--- a/server/web/filter/authz/authz_policy.csv
+++ /dev/null
@@ -1,7 +0,0 @@
-p, alice, /dataset1/*, GET
-p, alice, /dataset1/resource1, POST
-p, bob, /dataset2/resource1, *
-p, bob, /dataset2/resource2, GET
-p, bob, /dataset2/folder1/*, POST
-p, dataset1_admin, /dataset1/*, *
-g, cathy, dataset1_admin
\ No newline at end of file
diff --git a/server/web/filter/authz/authz_test.go b/server/web/filter/authz/authz_test.go
deleted file mode 100644
index c0d0dde5..00000000
--- a/server/web/filter/authz/authz_test.go
+++ /dev/null
@@ -1,109 +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 authz
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/casbin/casbin"
-
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
- "github.com/astaxie/beego/server/web/filter/auth"
-)
-
-func testRequest(t *testing.T, handler *web.ControllerRegister, user string, path string, method string, code int) {
- r, _ := http.NewRequest(method, path, nil)
- r.SetBasicAuth(user, "123")
- w := httptest.NewRecorder()
- handler.ServeHTTP(w, r)
-
- if w.Code != code {
- t.Errorf("%s, %s, %s: %d, supposed to be %d", user, path, method, w.Code, code)
- }
-}
-
-func TestBasic(t *testing.T) {
- handler := web.NewControllerRegister()
-
- handler.InsertFilter("*", web.BeforeRouter, auth.Basic("alice", "123"))
- handler.InsertFilter("*", web.BeforeRouter, NewAuthorizer(casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")))
-
- handler.Any("*", func(ctx *context.Context) {
- ctx.Output.SetStatus(200)
- })
-
- testRequest(t, handler, "alice", "/dataset1/resource1", "GET", 200)
- testRequest(t, handler, "alice", "/dataset1/resource1", "POST", 200)
- testRequest(t, handler, "alice", "/dataset1/resource2", "GET", 200)
- testRequest(t, handler, "alice", "/dataset1/resource2", "POST", 403)
-}
-
-func TestPathWildcard(t *testing.T) {
- handler := web.NewControllerRegister()
-
- handler.InsertFilter("*", web.BeforeRouter, auth.Basic("bob", "123"))
- handler.InsertFilter("*", web.BeforeRouter, NewAuthorizer(casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")))
-
- handler.Any("*", func(ctx *context.Context) {
- ctx.Output.SetStatus(200)
- })
-
- testRequest(t, handler, "bob", "/dataset2/resource1", "GET", 200)
- testRequest(t, handler, "bob", "/dataset2/resource1", "POST", 200)
- testRequest(t, handler, "bob", "/dataset2/resource1", "DELETE", 200)
- testRequest(t, handler, "bob", "/dataset2/resource2", "GET", 200)
- testRequest(t, handler, "bob", "/dataset2/resource2", "POST", 403)
- testRequest(t, handler, "bob", "/dataset2/resource2", "DELETE", 403)
-
- testRequest(t, handler, "bob", "/dataset2/folder1/item1", "GET", 403)
- testRequest(t, handler, "bob", "/dataset2/folder1/item1", "POST", 200)
- testRequest(t, handler, "bob", "/dataset2/folder1/item1", "DELETE", 403)
- testRequest(t, handler, "bob", "/dataset2/folder1/item2", "GET", 403)
- testRequest(t, handler, "bob", "/dataset2/folder1/item2", "POST", 200)
- testRequest(t, handler, "bob", "/dataset2/folder1/item2", "DELETE", 403)
-}
-
-func TestRBAC(t *testing.T) {
- handler := web.NewControllerRegister()
-
- handler.InsertFilter("*", web.BeforeRouter, auth.Basic("cathy", "123"))
- e := casbin.NewEnforcer("authz_model.conf", "authz_policy.csv")
- handler.InsertFilter("*", web.BeforeRouter, NewAuthorizer(e))
-
- handler.Any("*", func(ctx *context.Context) {
- ctx.Output.SetStatus(200)
- })
-
- // cathy can access all /dataset1/* resources via all methods because it has the dataset1_admin role.
- testRequest(t, handler, "cathy", "/dataset1/item", "GET", 200)
- testRequest(t, handler, "cathy", "/dataset1/item", "POST", 200)
- testRequest(t, handler, "cathy", "/dataset1/item", "DELETE", 200)
- testRequest(t, handler, "cathy", "/dataset2/item", "GET", 403)
- testRequest(t, handler, "cathy", "/dataset2/item", "POST", 403)
- testRequest(t, handler, "cathy", "/dataset2/item", "DELETE", 403)
-
- // delete all roles on user cathy, so cathy cannot access any resources now.
- e.DeleteRolesForUser("cathy")
-
- testRequest(t, handler, "cathy", "/dataset1/item", "GET", 403)
- testRequest(t, handler, "cathy", "/dataset1/item", "POST", 403)
- testRequest(t, handler, "cathy", "/dataset1/item", "DELETE", 403)
- testRequest(t, handler, "cathy", "/dataset2/item", "GET", 403)
- testRequest(t, handler, "cathy", "/dataset2/item", "POST", 403)
- testRequest(t, handler, "cathy", "/dataset2/item", "DELETE", 403)
-}
diff --git a/server/web/filter/opentracing/filter.go b/server/web/filter/opentracing/filter.go
deleted file mode 100644
index c2defa18..00000000
--- a/server/web/filter/opentracing/filter.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2020 beego
-//
-// 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 opentracing
-
-import (
- "context"
-
- "github.com/astaxie/beego/server/web"
- beegoCtx "github.com/astaxie/beego/server/web/context"
- logKit "github.com/go-kit/kit/log"
- opentracingKit "github.com/go-kit/kit/tracing/opentracing"
- "github.com/opentracing/opentracing-go"
-)
-
-// FilterChainBuilder provides an extension point that we can support more configurations if necessary
-type FilterChainBuilder struct {
- // CustomSpanFunc makes users to custom the span.
- CustomSpanFunc func(span opentracing.Span, ctx *beegoCtx.Context)
-}
-
-func (builder *FilterChainBuilder) FilterChain(next web.FilterFunc) web.FilterFunc {
- return func(ctx *beegoCtx.Context) {
- var (
- spanCtx context.Context
- span opentracing.Span
- )
- operationName := builder.operationName(ctx)
-
- if preSpan := opentracing.SpanFromContext(ctx.Request.Context()); preSpan == nil {
- inject := opentracingKit.HTTPToContext(opentracing.GlobalTracer(), operationName, logKit.NewNopLogger())
- spanCtx = inject(ctx.Request.Context(), ctx.Request)
- span = opentracing.SpanFromContext(spanCtx)
- } else {
- span, spanCtx = opentracing.StartSpanFromContext(ctx.Request.Context(), operationName)
- }
-
- defer span.Finish()
-
- newReq := ctx.Request.Clone(spanCtx)
- ctx.Reset(ctx.ResponseWriter.ResponseWriter, newReq)
-
- next(ctx)
- // if you think we need to do more things, feel free to create an issue to tell us
- span.SetTag("http.status_code", ctx.ResponseWriter.Status)
- span.SetTag("http.method", ctx.Input.Method())
- span.SetTag("peer.hostname", ctx.Request.Host)
- span.SetTag("http.url", ctx.Request.URL.String())
- span.SetTag("http.scheme", ctx.Request.URL.Scheme)
- span.SetTag("span.kind", "server")
- span.SetTag("component", "beego")
- if ctx.Output.IsServerError() || ctx.Output.IsClientError() {
- span.SetTag("error", true)
- }
- span.SetTag("peer.address", ctx.Request.RemoteAddr)
- span.SetTag("http.proto", ctx.Request.Proto)
-
- span.SetTag("beego.route", ctx.Input.GetData("RouterPattern"))
-
- if builder.CustomSpanFunc != nil {
- builder.CustomSpanFunc(span, ctx)
- }
- }
-}
-
-func (builder *FilterChainBuilder) operationName(ctx *beegoCtx.Context) string {
- operationName := ctx.Input.URL()
- // it means that there is not any span, so we create a span as the root span.
- // TODO, if we support multiple servers, this need to be changed
- route, found := web.BeeApp.Handlers.FindRouter(ctx)
- if found {
- operationName = ctx.Input.Method() + "#" + route.GetPattern()
- }
- return operationName
-}
diff --git a/server/web/filter/opentracing/filter_test.go b/server/web/filter/opentracing/filter_test.go
deleted file mode 100644
index d7222c37..00000000
--- a/server/web/filter/opentracing/filter_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2020 beego
-//
-// 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 opentracing
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/opentracing/opentracing-go"
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/server/web/context"
-)
-
-func TestFilterChainBuilder_FilterChain(t *testing.T) {
- builder := &FilterChainBuilder{
- CustomSpanFunc: func(span opentracing.Span, ctx *context.Context) {
- span.SetTag("aa", "bbb")
- },
- }
-
- ctx := context.NewContext()
- r, _ := http.NewRequest("GET", "/prometheus/user", nil)
- w := httptest.NewRecorder()
- ctx.Reset(w, r)
- ctx.Input.SetData("RouterPattern", "my-route")
-
- filterFunc := builder.FilterChain(func(ctx *context.Context) {
- ctx.Input.SetData("opentracing", true)
- })
-
- filterFunc(ctx)
- assert.True(t, ctx.Input.GetData("opentracing").(bool))
-}
diff --git a/server/web/filter/prometheus/filter.go b/server/web/filter/prometheus/filter.go
deleted file mode 100644
index 7daabd5a..00000000
--- a/server/web/filter/prometheus/filter.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2020 beego
-//
-// 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 prometheus
-
-import (
- "strconv"
- "strings"
- "time"
-
- "github.com/prometheus/client_golang/prometheus"
-
- "github.com/astaxie/beego"
- "github.com/astaxie/beego/server/web"
- "github.com/astaxie/beego/server/web/context"
-)
-
-// FilterChainBuilder is an extension point,
-// when we want to support some configuration,
-// please use this structure
-type FilterChainBuilder struct {
-}
-
-// FilterChain returns a FilterFunc. The filter will records some metrics
-func (builder *FilterChainBuilder) FilterChain(next web.FilterFunc) web.FilterFunc {
- summaryVec := prometheus.NewSummaryVec(prometheus.SummaryOpts{
- Name: "beego",
- Subsystem: "http_request",
- ConstLabels: map[string]string{
- "server": web.BConfig.ServerName,
- "env": web.BConfig.RunMode,
- "appname": web.BConfig.AppName,
- },
- Help: "The statics info for http request",
- }, []string{"pattern", "method", "status", "duration"})
-
- prometheus.MustRegister(summaryVec)
-
- registerBuildInfo()
-
- return func(ctx *context.Context) {
- startTime := time.Now()
- next(ctx)
- endTime := time.Now()
- go report(endTime.Sub(startTime), ctx, summaryVec)
- }
-}
-
-func registerBuildInfo() {
- buildInfo := prometheus.NewGaugeVec(prometheus.GaugeOpts{
- Name: "beego",
- Subsystem: "build_info",
- Help: "The building information",
- ConstLabels: map[string]string{
- "appname": web.BConfig.AppName,
- "build_version": beego.BuildVersion,
- "build_revision": beego.BuildGitRevision,
- "build_status": beego.BuildStatus,
- "build_tag": beego.BuildTag,
- "build_time": strings.Replace(beego.BuildTime, "--", " ", 1),
- "go_version": beego.GoVersion,
- "git_branch": beego.GitBranch,
- "start_time": time.Now().Format("2006-01-02 15:04:05"),
- },
- }, []string{})
-
- prometheus.MustRegister(buildInfo)
- buildInfo.WithLabelValues().Set(1)
-}
-
-func report(dur time.Duration, ctx *context.Context, vec *prometheus.SummaryVec) {
- status := ctx.Output.Status
- ptn := ctx.Input.GetData("RouterPattern").(string)
- ms := dur / time.Millisecond
- vec.WithLabelValues(ptn, ctx.Input.Method(), strconv.Itoa(status), strconv.Itoa(int(ms))).Observe(float64(ms))
-}
diff --git a/server/web/filter/prometheus/filter_test.go b/server/web/filter/prometheus/filter_test.go
deleted file mode 100644
index cb133a64..00000000
--- a/server/web/filter/prometheus/filter_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2020 beego
-//
-// 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 prometheus
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/server/web/context"
-)
-
-func TestFilterChain(t *testing.T) {
- filter := (&FilterChainBuilder{}).FilterChain(func(ctx *context.Context) {
- // do nothing
- ctx.Input.SetData("invocation", true)
- })
-
- ctx := context.NewContext()
- r, _ := http.NewRequest("GET", "/prometheus/user", nil)
- w := httptest.NewRecorder()
- ctx.Reset(w, r)
- ctx.Input.SetData("RouterPattern", "my-route")
- filter(ctx)
- assert.True(t, ctx.Input.GetData("invocation").(bool))
-}
diff --git a/server/web/filter_chain_test.go b/server/web/filter_chain_test.go
deleted file mode 100644
index e175ab29..00000000
--- a/server/web/filter_chain_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package web
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/server/web/context"
-)
-
-func TestControllerRegister_InsertFilterChain(t *testing.T) {
-
- InsertFilterChain("/*", func(next FilterFunc) FilterFunc {
- return func(ctx *context.Context) {
- ctx.Output.Header("filter", "filter-chain")
- next(ctx)
- }
- })
-
- ns := NewNamespace("/chain")
-
- ns.Get("/*", func(ctx *context.Context) {
- ctx.Output.Body([]byte("hello"))
- })
-
- r, _ := http.NewRequest("GET", "/chain/user", nil)
- w := httptest.NewRecorder()
-
- BeeApp.Handlers.ServeHTTP(w, r)
-
- assert.Equal(t, "filter-chain", w.Header().Get("filter"))
-}
diff --git a/server/web/server.go b/server/web/server.go
deleted file mode 100644
index 25841563..00000000
--- a/server/web/server.go
+++ /dev/null
@@ -1,751 +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 web
-
-import (
- "crypto/tls"
- "crypto/x509"
- "fmt"
- "io/ioutil"
- "net"
- "net/http"
- "net/http/fcgi"
- "os"
- "path"
- "strconv"
- "strings"
- "text/template"
- "time"
-
- "golang.org/x/crypto/acme/autocert"
-
- "github.com/astaxie/beego/core/logs"
- beecontext "github.com/astaxie/beego/server/web/context"
-
- "github.com/astaxie/beego/core/utils"
- "github.com/astaxie/beego/server/web/grace"
-)
-
-var (
- // BeeApp is an application instance
- // If you are using single server, you could use this
- // But if you need multiple servers, do not use this
- BeeApp *HttpServer
-)
-
-func init() {
- // create beego application
- BeeApp = NewHttpSever()
-}
-
-// HttpServer defines beego application with a new PatternServeMux.
-type HttpServer struct {
- Handlers *ControllerRegister
- Server *http.Server
- Cfg *Config
-}
-
-// NewHttpSever returns a new beego application.
-// this method will use the BConfig as the configure to create HttpServer
-// Be careful that when you update BConfig, the server's Cfg will be updated too
-func NewHttpSever() *HttpServer {
- return NewHttpServerWithCfg(BConfig)
-}
-
-// NewHttpServerWithCfg will create an sever with specific cfg
-func NewHttpServerWithCfg(cfg *Config) *HttpServer {
- cr := NewControllerRegisterWithCfg(cfg)
- app := &HttpServer{
- Handlers: cr,
- Server: &http.Server{},
- Cfg: cfg,
- }
-
- return app
-}
-
-// MiddleWare function for http.Handler
-type MiddleWare func(http.Handler) http.Handler
-
-// Run beego application.
-func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
-
- initBeforeHTTPRun()
-
- app.initAddr(addr)
-
- addr = app.Cfg.Listen.HTTPAddr
-
- if app.Cfg.Listen.HTTPPort != 0 {
- addr = fmt.Sprintf("%s:%d", app.Cfg.Listen.HTTPAddr, app.Cfg.Listen.HTTPPort)
- }
-
- var (
- err error
- l net.Listener
- endRunning = make(chan bool, 1)
- )
-
- // run cgi server
- if app.Cfg.Listen.EnableFcgi {
- if app.Cfg.Listen.EnableStdIo {
- if err = fcgi.Serve(nil, app.Handlers); err == nil { // standard I/O
- logs.Info("Use FCGI via standard I/O")
- } else {
- logs.Critical("Cannot use FCGI via standard I/O", err)
- }
- return
- }
- if app.Cfg.Listen.HTTPPort == 0 {
- // remove the Socket file before start
- if utils.FileExists(addr) {
- os.Remove(addr)
- }
- l, err = net.Listen("unix", addr)
- } else {
- l, err = net.Listen("tcp", addr)
- }
- if err != nil {
- logs.Critical("Listen: ", err)
- }
- if err = fcgi.Serve(l, app.Handlers); err != nil {
- logs.Critical("fcgi.Serve: ", err)
- }
- return
- }
-
- app.Server.Handler = app.Handlers
- for i := len(mws) - 1; i >= 0; i-- {
- if mws[i] == nil {
- continue
- }
- app.Server.Handler = mws[i](app.Server.Handler)
- }
- app.Server.ReadTimeout = time.Duration(app.Cfg.Listen.ServerTimeOut) * time.Second
- app.Server.WriteTimeout = time.Duration(app.Cfg.Listen.ServerTimeOut) * time.Second
- app.Server.ErrorLog = logs.GetLogger("HTTP")
-
- // run graceful mode
- if app.Cfg.Listen.Graceful {
- httpsAddr := app.Cfg.Listen.HTTPSAddr
- app.Server.Addr = httpsAddr
- if app.Cfg.Listen.EnableHTTPS || app.Cfg.Listen.EnableMutualHTTPS {
- go func() {
- time.Sleep(1000 * time.Microsecond)
- if app.Cfg.Listen.HTTPSPort != 0 {
- httpsAddr = fmt.Sprintf("%s:%d", app.Cfg.Listen.HTTPSAddr, app.Cfg.Listen.HTTPSPort)
- app.Server.Addr = httpsAddr
- }
- server := grace.NewServer(httpsAddr, app.Server.Handler)
- server.Server.ReadTimeout = app.Server.ReadTimeout
- server.Server.WriteTimeout = app.Server.WriteTimeout
- if app.Cfg.Listen.EnableMutualHTTPS {
- if err := server.ListenAndServeMutualTLS(app.Cfg.Listen.HTTPSCertFile,
- app.Cfg.Listen.HTTPSKeyFile,
- app.Cfg.Listen.TrustCaFile); err != nil {
- logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
- time.Sleep(100 * time.Microsecond)
- }
- } else {
- if app.Cfg.Listen.AutoTLS {
- m := autocert.Manager{
- Prompt: autocert.AcceptTOS,
- HostPolicy: autocert.HostWhitelist(app.Cfg.Listen.Domains...),
- Cache: autocert.DirCache(app.Cfg.Listen.TLSCacheDir),
- }
- app.Server.TLSConfig = &tls.Config{GetCertificate: m.GetCertificate}
- app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile = "", ""
- }
- if err := server.ListenAndServeTLS(app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile); err != nil {
- logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
- time.Sleep(100 * time.Microsecond)
- }
- }
- endRunning <- true
- }()
- }
- if app.Cfg.Listen.EnableHTTP {
- go func() {
- server := grace.NewServer(addr, app.Server.Handler)
- server.Server.ReadTimeout = app.Server.ReadTimeout
- server.Server.WriteTimeout = app.Server.WriteTimeout
- if app.Cfg.Listen.ListenTCP4 {
- server.Network = "tcp4"
- }
- if err := server.ListenAndServe(); err != nil {
- logs.Critical("ListenAndServe: ", err, fmt.Sprintf("%d", os.Getpid()))
- time.Sleep(100 * time.Microsecond)
- }
- endRunning <- true
- }()
- }
- <-endRunning
- return
- }
-
- // run normal mode
- if app.Cfg.Listen.EnableHTTPS || app.Cfg.Listen.EnableMutualHTTPS {
- go func() {
- time.Sleep(1000 * time.Microsecond)
- if app.Cfg.Listen.HTTPSPort != 0 {
- app.Server.Addr = fmt.Sprintf("%s:%d", app.Cfg.Listen.HTTPSAddr, app.Cfg.Listen.HTTPSPort)
- } else if app.Cfg.Listen.EnableHTTP {
- 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)
- if app.Cfg.Listen.AutoTLS {
- m := autocert.Manager{
- Prompt: autocert.AcceptTOS,
- HostPolicy: autocert.HostWhitelist(app.Cfg.Listen.Domains...),
- Cache: autocert.DirCache(app.Cfg.Listen.TLSCacheDir),
- }
- app.Server.TLSConfig = &tls.Config{GetCertificate: m.GetCertificate}
- app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile = "", ""
- } else if app.Cfg.Listen.EnableMutualHTTPS {
- pool := x509.NewCertPool()
- data, err := ioutil.ReadFile(app.Cfg.Listen.TrustCaFile)
- if err != nil {
- logs.Info("MutualHTTPS should provide TrustCaFile")
- return
- }
- pool.AppendCertsFromPEM(data)
- app.Server.TLSConfig = &tls.Config{
- ClientCAs: pool,
- ClientAuth: tls.ClientAuthType(app.Cfg.Listen.ClientAuth),
- }
- }
- if err := app.Server.ListenAndServeTLS(app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile); err != nil {
- logs.Critical("ListenAndServeTLS: ", err)
- time.Sleep(100 * time.Microsecond)
- endRunning <- true
- }
- }()
-
- }
- if app.Cfg.Listen.EnableHTTP {
- go func() {
- app.Server.Addr = addr
- logs.Info("http server Running on http://%s", app.Server.Addr)
- if app.Cfg.Listen.ListenTCP4 {
- ln, err := net.Listen("tcp4", app.Server.Addr)
- if err != nil {
- logs.Critical("ListenAndServe: ", err)
- time.Sleep(100 * time.Microsecond)
- endRunning <- true
- return
- }
- if err = app.Server.Serve(ln); err != nil {
- logs.Critical("ListenAndServe: ", err)
- time.Sleep(100 * time.Microsecond)
- endRunning <- true
- return
- }
- } else {
- if err := app.Server.ListenAndServe(); err != nil {
- logs.Critical("ListenAndServe: ", err)
- time.Sleep(100 * time.Microsecond)
- endRunning <- true
- }
- }
- }()
- }
- <-endRunning
-}
-
-// Router see HttpServer.Router
-func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *HttpServer {
- return BeeApp.Router(rootpath, c, mappingMethods...)
-}
-
-// Router adds a patterned controller handler to BeeApp.
-// it's an alias method of HttpServer.Router.
-// usage:
-// simple router
-// beego.Router("/admin", &admin.UserController{})
-// beego.Router("/admin/index", &admin.ArticleController{})
-//
-// regex router
-//
-// beego.Router("/api/:id([0-9]+)", &controllers.RController{})
-//
-// custom rules
-// beego.Router("/api/list",&RestController{},"*:ListFood")
-// beego.Router("/api/create",&RestController{},"post:CreateFood")
-// beego.Router("/api/update",&RestController{},"put:UpdateFood")
-// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
-func (app *HttpServer) Router(rootPath string, c ControllerInterface, mappingMethods ...string) *HttpServer {
- app.Handlers.Add(rootPath, c, mappingMethods...)
- return app
-}
-
-// UnregisterFixedRoute see HttpServer.UnregisterFixedRoute
-func UnregisterFixedRoute(fixedRoute string, method string) *HttpServer {
- return BeeApp.UnregisterFixedRoute(fixedRoute, method)
-}
-
-// UnregisterFixedRoute unregisters the route with the specified fixedRoute. It is particularly useful
-// in web applications that inherit most routes from a base webapp via the underscore
-// import, and aim to overwrite only certain paths.
-// The method parameter can be empty or "*" for all HTTP methods, or a particular
-// method type (e.g. "GET" or "POST") for selective removal.
-//
-// Usage (replace "GET" with "*" for all methods):
-// beego.UnregisterFixedRoute("/yourpreviouspath", "GET")
-// beego.Router("/yourpreviouspath", yourControllerAddress, "get:GetNewPage")
-func (app *HttpServer) UnregisterFixedRoute(fixedRoute string, method string) *HttpServer {
- subPaths := splitPath(fixedRoute)
- if method == "" || method == "*" {
- for m := range HTTPMETHOD {
- if _, ok := app.Handlers.routers[m]; !ok {
- continue
- }
- if app.Handlers.routers[m].prefix == strings.Trim(fixedRoute, "/ ") {
- findAndRemoveSingleTree(app.Handlers.routers[m])
- continue
- }
- findAndRemoveTree(subPaths, app.Handlers.routers[m], m)
- }
- return app
- }
- // Single HTTP method
- um := strings.ToUpper(method)
- if _, ok := app.Handlers.routers[um]; ok {
- if app.Handlers.routers[um].prefix == strings.Trim(fixedRoute, "/ ") {
- findAndRemoveSingleTree(app.Handlers.routers[um])
- return app
- }
- findAndRemoveTree(subPaths, app.Handlers.routers[um], um)
- }
- return app
-}
-
-func findAndRemoveTree(paths []string, entryPointTree *Tree, method string) {
- for i := range entryPointTree.fixrouters {
- if entryPointTree.fixrouters[i].prefix == paths[0] {
- if len(paths) == 1 {
- if len(entryPointTree.fixrouters[i].fixrouters) > 0 {
- // If the route had children subtrees, remove just the functional leaf,
- // to allow children to function as before
- if len(entryPointTree.fixrouters[i].leaves) > 0 {
- entryPointTree.fixrouters[i].leaves[0] = nil
- entryPointTree.fixrouters[i].leaves = entryPointTree.fixrouters[i].leaves[1:]
- }
- } else {
- // Remove the *Tree from the fixrouters slice
- entryPointTree.fixrouters[i] = nil
-
- if i == len(entryPointTree.fixrouters)-1 {
- entryPointTree.fixrouters = entryPointTree.fixrouters[:i]
- } else {
- entryPointTree.fixrouters = append(entryPointTree.fixrouters[:i], entryPointTree.fixrouters[i+1:len(entryPointTree.fixrouters)]...)
- }
- }
- return
- }
- findAndRemoveTree(paths[1:], entryPointTree.fixrouters[i], method)
- }
- }
-}
-
-func findAndRemoveSingleTree(entryPointTree *Tree) {
- if entryPointTree == nil {
- return
- }
- if len(entryPointTree.fixrouters) > 0 {
- // If the route had children subtrees, remove just the functional leaf,
- // to allow children to function as before
- if len(entryPointTree.leaves) > 0 {
- entryPointTree.leaves[0] = nil
- entryPointTree.leaves = entryPointTree.leaves[1:]
- }
- }
-}
-
-// Include see HttpServer.Include
-func Include(cList ...ControllerInterface) *HttpServer {
- return BeeApp.Include(cList...)
-}
-
-// Include will generate router file in the router/xxx.go from the controller's comments
-// usage:
-// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
-// type BankAccount struct{
-// beego.Controller
-// }
-//
-// register the function
-// func (b *BankAccount)Mapping(){
-// b.Mapping("ShowAccount" , b.ShowAccount)
-// b.Mapping("ModifyAccount", b.ModifyAccount)
-// }
-//
-// //@router /account/:id [get]
-// func (b *BankAccount) ShowAccount(){
-// //logic
-// }
-//
-//
-// //@router /account/:id [post]
-// func (b *BankAccount) ModifyAccount(){
-// //logic
-// }
-//
-// the comments @router url methodlist
-// url support all the function Router's pattern
-// methodlist [get post head put delete options *]
-func (app *HttpServer) Include(cList ...ControllerInterface) *HttpServer {
- app.Handlers.Include(cList...)
- return app
-}
-
-// RESTRouter see HttpServer.RESTRouter
-func RESTRouter(rootpath string, c ControllerInterface) *HttpServer {
- return BeeApp.RESTRouter(rootpath, c)
-}
-
-// RESTRouter adds a restful controller handler to BeeApp.
-// its' controller implements beego.ControllerInterface and
-// defines a param "pattern/:objectId" to visit each resource.
-func (app *HttpServer) RESTRouter(rootpath string, c ControllerInterface) *HttpServer {
- app.Router(rootpath, c)
- app.Router(path.Join(rootpath, ":objectId"), c)
- return app
-}
-
-// AutoRouter see HttpServer.AutoRouter
-func AutoRouter(c ControllerInterface) *HttpServer {
- return BeeApp.AutoRouter(c)
-}
-
-// AutoRouter adds defined controller handler to BeeApp.
-// it's same to HttpServer.AutoRouter.
-// if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
-// visit the url /main/list to exec List function or /main/page to exec Page function.
-func (app *HttpServer) AutoRouter(c ControllerInterface) *HttpServer {
- app.Handlers.AddAuto(c)
- return app
-}
-
-// AutoPrefix see HttpServer.AutoPrefix
-func AutoPrefix(prefix string, c ControllerInterface) *HttpServer {
- return BeeApp.AutoPrefix(prefix, c)
-}
-
-// AutoPrefix adds controller handler to BeeApp with prefix.
-// it's same to HttpServer.AutoRouterWithPrefix.
-// if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
-// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
-func (app *HttpServer) AutoPrefix(prefix string, c ControllerInterface) *HttpServer {
- app.Handlers.AddAutoPrefix(prefix, c)
- return app
-}
-
-// Get see HttpServer.Get
-func Get(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Get(rootpath, f)
-}
-
-// Get used to register router for Get method
-// usage:
-// beego.Get("/", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Get(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Get(rootpath, f)
- return app
-}
-
-// Post see HttpServer.Post
-func Post(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Post(rootpath, f)
-}
-
-// Post used to register router for Post method
-// usage:
-// beego.Post("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Post(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Post(rootpath, f)
- return app
-}
-
-// Delete see HttpServer.Delete
-func Delete(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Delete(rootpath, f)
-}
-
-// Delete used to register router for Delete method
-// usage:
-// beego.Delete("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Delete(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Delete(rootpath, f)
- return app
-}
-
-// Put see HttpServer.Put
-func Put(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Put(rootpath, f)
-}
-
-// Put used to register router for Put method
-// usage:
-// beego.Put("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Put(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Put(rootpath, f)
- return app
-}
-
-// Head see HttpServer.Head
-func Head(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Head(rootpath, f)
-}
-
-// Head used to register router for Head method
-// usage:
-// beego.Head("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Head(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Head(rootpath, f)
- return app
-}
-
-// Options see HttpServer.Options
-func Options(rootpath string, f FilterFunc) *HttpServer {
- BeeApp.Handlers.Options(rootpath, f)
- return BeeApp
-}
-
-// Options used to register router for Options method
-// usage:
-// beego.Options("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Options(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Options(rootpath, f)
- return app
-}
-
-// Patch see HttpServer.Patch
-func Patch(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Patch(rootpath, f)
-}
-
-// Patch used to register router for Patch method
-// usage:
-// beego.Patch("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Patch(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Patch(rootpath, f)
- return app
-}
-
-// Any see HttpServer.Any
-func Any(rootpath string, f FilterFunc) *HttpServer {
- return BeeApp.Any(rootpath, f)
-}
-
-// Any used to register router for all methods
-// usage:
-// beego.Any("/api", func(ctx *context.Context){
-// ctx.Output.Body("hello world")
-// })
-func (app *HttpServer) Any(rootpath string, f FilterFunc) *HttpServer {
- app.Handlers.Any(rootpath, f)
- return app
-}
-
-// Handler see HttpServer.Handler
-func Handler(rootpath string, h http.Handler, options ...interface{}) *HttpServer {
- return BeeApp.Handler(rootpath, h, options...)
-}
-
-// Handler used to register a Handler router
-// usage:
-// beego.Handler("/api", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
-// fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
-// }))
-func (app *HttpServer) Handler(rootpath string, h http.Handler, options ...interface{}) *HttpServer {
- app.Handlers.Handler(rootpath, h, options...)
- return app
-}
-
-// InserFilter see HttpServer.InsertFilter
-func InsertFilter(pattern string, pos int, filter FilterFunc, opts ...FilterOpt) *HttpServer {
- return BeeApp.InsertFilter(pattern, pos, filter, opts...)
-}
-
-// InsertFilter adds a FilterFunc with pattern condition and action constant.
-// The pos means action constant including
-// beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
-// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
-func (app *HttpServer) InsertFilter(pattern string, pos int, filter FilterFunc, opts ...FilterOpt) *HttpServer {
- app.Handlers.InsertFilter(pattern, pos, filter, opts...)
- return app
-}
-
-// InsertFilterChain see HttpServer.InsertFilterChain
-func InsertFilterChain(pattern string, filterChain FilterChain, opts ...FilterOpt) *HttpServer {
- return BeeApp.InsertFilterChain(pattern, filterChain, opts...)
-}
-
-// InsertFilterChain adds a FilterFunc built by filterChain.
-// This filter will be executed before all filters.
-// the filter's behavior like stack's behavior
-// and the last filter is serving the http request
-func (app *HttpServer) InsertFilterChain(pattern string, filterChain FilterChain, opts ...FilterOpt) *HttpServer {
- app.Handlers.InsertFilterChain(pattern, filterChain, opts...)
- return app
-}
-
-func (app *HttpServer) initAddr(addr string) {
- strs := strings.Split(addr, ":")
- if len(strs) > 0 && strs[0] != "" {
- app.Cfg.Listen.HTTPAddr = strs[0]
- app.Cfg.Listen.Domains = []string{strs[0]}
- }
- if len(strs) > 1 && strs[1] != "" {
- app.Cfg.Listen.HTTPPort, _ = strconv.Atoi(strs[1])
- }
-}
-
-func (app *HttpServer) LogAccess(ctx *beecontext.Context, startTime *time.Time, statusCode int) {
- // Skip logging if AccessLogs config is false
- if !app.Cfg.Log.AccessLogs {
- return
- }
- // Skip logging static requests unless EnableStaticLogs config is true
- if !app.Cfg.Log.EnableStaticLogs && DefaultAccessLogFilter.Filter(ctx) {
- return
- }
- var (
- requestTime time.Time
- elapsedTime time.Duration
- r = ctx.Request
- )
- if startTime != nil {
- requestTime = *startTime
- elapsedTime = time.Since(*startTime)
- }
- record := &logs.AccessLogRecord{
- RemoteAddr: ctx.Input.IP(),
- RequestTime: requestTime,
- RequestMethod: r.Method,
- Request: fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto),
- ServerProtocol: r.Proto,
- Host: r.Host,
- Status: statusCode,
- ElapsedTime: elapsedTime,
- HTTPReferrer: r.Header.Get("Referer"),
- HTTPUserAgent: r.Header.Get("User-Agent"),
- RemoteUser: r.Header.Get("Remote-User"),
- BodyBytesSent: r.ContentLength,
- }
- logs.AccessLog(record, app.Cfg.Log.AccessLogsFormat)
-}
-
-// PrintTree prints all registered routers.
-func (app *HttpServer) PrintTree() M {
- var (
- content = M{}
- methods = []string{}
- methodsData = make(M)
- )
- for method, t := range app.Handlers.routers {
-
- resultList := new([][]string)
-
- printTree(resultList, t)
-
- methods = append(methods, template.HTMLEscapeString(method))
- methodsData[template.HTMLEscapeString(method)] = resultList
- }
-
- content["Data"] = methodsData
- content["Methods"] = methods
- return content
-}
-
-func printTree(resultList *[][]string, t *Tree) {
- for _, tr := range t.fixrouters {
- printTree(resultList, tr)
- }
- if t.wildcard != nil {
- printTree(resultList, t.wildcard)
- }
- for _, l := range t.leaves {
- if v, ok := l.runObject.(*ControllerInfo); ok {
- if v.routerType == routerTypeBeego {
- var result = []string{
- template.HTMLEscapeString(v.pattern),
- template.HTMLEscapeString(fmt.Sprintf("%s", v.methods)),
- template.HTMLEscapeString(v.controllerType.String()),
- }
- *resultList = append(*resultList, result)
- } else if v.routerType == routerTypeRESTFul {
- var result = []string{
- template.HTMLEscapeString(v.pattern),
- template.HTMLEscapeString(fmt.Sprintf("%s", v.methods)),
- "",
- }
- *resultList = append(*resultList, result)
- } else if v.routerType == routerTypeHandler {
- var result = []string{
- template.HTMLEscapeString(v.pattern),
- "",
- "",
- }
- *resultList = append(*resultList, result)
- }
- }
- }
-}
-
-func (app *HttpServer) reportFilter() M {
- filterTypeData := make(M)
- // filterTypes := []string{}
- if app.Handlers.enableFilter {
- // var filterType string
- for k, fr := range map[int]string{
- BeforeStatic: "Before Static",
- BeforeRouter: "Before Router",
- BeforeExec: "Before Exec",
- AfterExec: "After Exec",
- FinishRouter: "Finish Router",
- } {
- if bf := app.Handlers.filters[k]; len(bf) > 0 {
- resultList := new([][]string)
- for _, f := range bf {
- var result = []string{
- // void xss
- template.HTMLEscapeString(f.pattern),
- template.HTMLEscapeString(utils.GetFuncName(f.filterFunc)),
- }
- *resultList = append(*resultList, result)
- }
- filterTypeData[fr] = resultList
- }
- }
- }
-
- return filterTypeData
-}
diff --git a/server/web/server_test.go b/server/web/server_test.go
deleted file mode 100644
index 0b0c601c..00000000
--- a/server/web/server_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package web
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestNewHttpServerWithCfg(t *testing.T) {
-
- BConfig.AppName = "Before"
- svr := NewHttpServerWithCfg(BConfig)
- svr.Cfg.AppName = "hello"
- assert.Equal(t, "hello", BConfig.AppName)
-
-}
diff --git a/server/web/session/couchbase/sess_couchbase_test.go b/server/web/session/couchbase/sess_couchbase_test.go
deleted file mode 100644
index 5959f9c3..00000000
--- a/server/web/session/couchbase/sess_couchbase_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package couchbase
-
-import (
- "context"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestProvider_SessionInit(t *testing.T) {
- // using old style
- savePath := `http://host:port/,Pool,Bucket`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "http://host:port/", cp.SavePath)
- assert.Equal(t, "Pool", cp.Pool)
- assert.Equal(t, "Bucket", cp.Bucket)
- assert.Equal(t, int64(12), cp.maxlifetime)
-
- savePath = `
-{ "save_path": "my save path", "pool": "mypool", "bucket": "mybucket"}
-`
- cp = &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "my save path", cp.SavePath)
- assert.Equal(t, "mypool", cp.Pool)
- assert.Equal(t, "mybucket", cp.Bucket)
- assert.Equal(t, int64(12), cp.maxlifetime)
-}
diff --git a/server/web/session/ledis/ledis_session_test.go b/server/web/session/ledis/ledis_session_test.go
deleted file mode 100644
index 1cfb3ed1..00000000
--- a/server/web/session/ledis/ledis_session_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ledis
-
-import (
- "context"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestProvider_SessionInit(t *testing.T) {
- // using old style
- savePath := `http://host:port/,100`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "http://host:port/", cp.SavePath)
- assert.Equal(t, 100, cp.Db)
- assert.Equal(t, int64(12), cp.maxlifetime)
-
- savePath = `
-{ "save_path": "my save path", "db": 100}
-`
- cp = &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "my save path", cp.SavePath)
- assert.Equal(t, 100, cp.Db)
- assert.Equal(t, int64(12), cp.maxlifetime)
-}
diff --git a/server/web/session/redis/sess_redis_test.go b/server/web/session/redis/sess_redis_test.go
deleted file mode 100644
index 64dbc9f9..00000000
--- a/server/web/session/redis/sess_redis_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package redis
-
-import (
- "context"
- "fmt"
- "net/http"
- "net/http/httptest"
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/server/web/session"
-)
-
-func TestRedis(t *testing.T) {
- sessionConfig := &session.ManagerConfig{
- CookieName: "gosessionid",
- EnableSetCookie: true,
- Gclifetime: 3600,
- Maxlifetime: 3600,
- Secure: false,
- CookieLifeTime: 3600,
- }
-
- redisAddr := os.Getenv("REDIS_ADDR")
- if redisAddr == "" {
- redisAddr = "127.0.0.1:6379"
- }
-
- sessionConfig.ProviderConfig = fmt.Sprintf("%s,100,,0,30", redisAddr)
- globalSession, err := session.NewManager("redis", sessionConfig)
- if err != nil {
- t.Fatal("could not create manager:", err)
- }
-
- go globalSession.GC()
-
- r, _ := http.NewRequest("GET", "/", nil)
- w := httptest.NewRecorder()
-
- sess, err := globalSession.SessionStart(w, r)
- if err != nil {
- t.Fatal("session start failed:", err)
- }
- defer sess.SessionRelease(nil, w)
-
- // SET AND GET
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set username failed:", err)
- }
- username := sess.Get(nil, "username")
- if username != "astaxie" {
- t.Fatal("get username failed")
- }
-
- // DELETE
- err = sess.Delete(nil, "username")
- if err != nil {
- t.Fatal("delete username failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != nil {
- t.Fatal("delete username failed")
- }
-
- // FLUSH
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set failed:", err)
- }
- err = sess.Set(nil, "password", "1qaz2wsx")
- if err != nil {
- t.Fatal("set failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != "astaxie" {
- t.Fatal("get username failed")
- }
- password := sess.Get(nil, "password")
- if password != "1qaz2wsx" {
- t.Fatal("get password failed")
- }
- err = sess.Flush(nil)
- if err != nil {
- t.Fatal("flush failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != nil {
- t.Fatal("flush failed")
- }
- password = sess.Get(nil, "password")
- if password != nil {
- t.Fatal("flush failed")
- }
-
- sess.SessionRelease(nil, w)
-}
-
-func TestProvider_SessionInit(t *testing.T) {
-
- savePath := `
-{ "save_path": "my save path", "idle_timeout": "3s"}
-`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "my save path", cp.SavePath)
- assert.Equal(t, 3*time.Second, cp.idleTimeout)
- assert.Equal(t, int64(12), cp.maxlifetime)
-}
diff --git a/server/web/session/redis_cluster/redis_cluster_test.go b/server/web/session/redis_cluster/redis_cluster_test.go
deleted file mode 100644
index 0192cd87..00000000
--- a/server/web/session/redis_cluster/redis_cluster_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package redis_cluster
-
-import (
- "context"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestProvider_SessionInit(t *testing.T) {
-
- savePath := `
-{ "save_path": "my save path", "idle_timeout": "3s"}
-`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "my save path", cp.SavePath)
- assert.Equal(t, 3*time.Second, cp.idleTimeout)
- assert.Equal(t, int64(12), cp.maxlifetime)
-}
diff --git a/server/web/session/redis_sentinel/sess_redis_sentinel_test.go b/server/web/session/redis_sentinel/sess_redis_sentinel_test.go
deleted file mode 100644
index f052a14a..00000000
--- a/server/web/session/redis_sentinel/sess_redis_sentinel_test.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package redis_sentinel
-
-import (
- "context"
- "net/http"
- "net/http/httptest"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/server/web/session"
-)
-
-func TestRedisSentinel(t *testing.T) {
- sessionConfig := &session.ManagerConfig{
- CookieName: "gosessionid",
- EnableSetCookie: true,
- Gclifetime: 3600,
- Maxlifetime: 3600,
- Secure: false,
- CookieLifeTime: 3600,
- ProviderConfig: "127.0.0.1:6379,100,,0,master",
- }
- globalSessions, e := session.NewManager("redis_sentinel", sessionConfig)
- if e != nil {
- t.Log(e)
- return
- }
- // todo test if e==nil
- 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(nil, w)
-
- // SET AND GET
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set username failed:", err)
- }
- username := sess.Get(nil, "username")
- if username != "astaxie" {
- t.Fatal("get username failed")
- }
-
- // DELETE
- err = sess.Delete(nil, "username")
- if err != nil {
- t.Fatal("delete username failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != nil {
- t.Fatal("delete username failed")
- }
-
- // FLUSH
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set failed:", err)
- }
- err = sess.Set(nil, "password", "1qaz2wsx")
- if err != nil {
- t.Fatal("set failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != "astaxie" {
- t.Fatal("get username failed")
- }
- password := sess.Get(nil, "password")
- if password != "1qaz2wsx" {
- t.Fatal("get password failed")
- }
- err = sess.Flush(nil)
- if err != nil {
- t.Fatal("flush failed:", err)
- }
- username = sess.Get(nil, "username")
- if username != nil {
- t.Fatal("flush failed")
- }
- password = sess.Get(nil, "password")
- if password != nil {
- t.Fatal("flush failed")
- }
-
- sess.SessionRelease(nil, w)
-
-}
-
-func TestProvider_SessionInit(t *testing.T) {
-
- savePath := `
-{ "save_path": "my save path", "idle_timeout": "3s"}
-`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "my save path", cp.SavePath)
- assert.Equal(t, 3*time.Second, cp.idleTimeout)
- assert.Equal(t, int64(12), cp.maxlifetime)
-}
diff --git a/server/web/session/sess_cookie_test.go b/server/web/session/sess_cookie_test.go
deleted file mode 100644
index a9fc876d..00000000
--- a/server/web/session/sess_cookie_test.go
+++ /dev/null
@@ -1,105 +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 session
-
-import (
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
-)
-
-func TestCookie(t *testing.T) {
- config := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`
- conf := new(ManagerConfig)
- if err := json.Unmarshal([]byte(config), conf); err != nil {
- t.Fatal("json decode error", err)
- }
- globalSessions, err := NewManager("cookie", conf)
- if err != nil {
- t.Fatal("init cookie session err", err)
- }
- r, _ := http.NewRequest("GET", "/", nil)
- w := httptest.NewRecorder()
- sess, err := globalSessions.SessionStart(w, r)
- if err != nil {
- t.Fatal("set error,", err)
- }
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set error,", err)
- }
- if username := sess.Get(nil, "username"); username != "astaxie" {
- t.Fatal("get username error")
- }
- sess.SessionRelease(nil, w)
- if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" {
- t.Fatal("setcookie error")
- } else {
- parts := strings.Split(strings.TrimSpace(cookiestr), ";")
- for k, v := range parts {
- nameval := strings.Split(v, "=")
- if k == 0 && nameval[0] != "gosessionid" {
- t.Fatal("error")
- }
- }
- }
-}
-
-func TestDestorySessionCookie(t *testing.T) {
- config := `{"cookieName":"gosessionid","enableSetCookie":true,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`
- conf := new(ManagerConfig)
- if err := json.Unmarshal([]byte(config), conf); err != nil {
- t.Fatal("json decode error", err)
- }
- globalSessions, err := NewManager("cookie", conf)
- if err != nil {
- t.Fatal("init cookie session err", err)
- }
-
- r, _ := http.NewRequest("GET", "/", nil)
- w := httptest.NewRecorder()
- session, err := globalSessions.SessionStart(w, r)
- if err != nil {
- t.Fatal("session start err,", err)
- }
-
- // request again ,will get same sesssion id .
- r1, _ := http.NewRequest("GET", "/", nil)
- r1.Header.Set("Cookie", w.Header().Get("Set-Cookie"))
- w = httptest.NewRecorder()
- newSession, err := globalSessions.SessionStart(w, r1)
- if err != nil {
- t.Fatal("session start err,", err)
- }
- if newSession.SessionID(nil) != session.SessionID(nil) {
- t.Fatal("get cookie session id is not the same again.")
- }
-
- // After destroy session , will get a new session id .
- globalSessions.SessionDestroy(w, r1)
- r2, _ := http.NewRequest("GET", "/", nil)
- r2.Header.Set("Cookie", w.Header().Get("Set-Cookie"))
-
- w = httptest.NewRecorder()
- newSession, err = globalSessions.SessionStart(w, r2)
- if err != nil {
- t.Fatal("session start error")
- }
- if newSession.SessionID(nil) == session.SessionID(nil) {
- t.Fatal("after destroy session and reqeust again ,get cookie session id is same.")
- }
-}
diff --git a/server/web/session/sess_file_test.go b/server/web/session/sess_file_test.go
deleted file mode 100644
index f40de69f..00000000
--- a/server/web/session/sess_file_test.go
+++ /dev/null
@@ -1,427 +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 session
-
-import (
- "context"
- "fmt"
- "os"
- "sync"
- "testing"
- "time"
-)
-
-const sid = "Session_id"
-const sidNew = "Session_id_new"
-const sessionPath = "./_session_runtime"
-
-var (
- mutex sync.Mutex
-)
-
-func TestFileProvider_SessionInit(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
- if fp.maxlifetime != 180 {
- t.Error()
- }
-
- if fp.savePath != sessionPath {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionExist(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- exists, err := fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if exists {
- t.Error()
- }
-
- _, err = fp.SessionRead(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
-
- exists, err = fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if !exists {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionExist2(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- exists, err := fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if exists {
- t.Error()
- }
-
- exists, err = fp.SessionExist(context.Background(), "")
- if err == nil {
- t.Error()
- }
- if exists {
- t.Error()
- }
-
- exists, err = fp.SessionExist(context.Background(), "1")
- if err == nil {
- t.Error()
- }
- if exists {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionRead(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- s, err := fp.SessionRead(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
-
- _ = s.Set(nil, "sessionValue", 18975)
- v := s.Get(nil, "sessionValue")
-
- if v.(int) != 18975 {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionRead1(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- _, err := fp.SessionRead(context.Background(), "")
- if err == nil {
- t.Error(err)
- }
-
- _, err = fp.SessionRead(context.Background(), "1")
- if err == nil {
- t.Error(err)
- }
-}
-
-func TestFileProvider_SessionAll(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- sessionCount := 546
-
- for i := 1; i <= sessionCount; i++ {
- _, err := fp.SessionRead(context.Background(), fmt.Sprintf("%s_%d", sid, i))
- if err != nil {
- t.Error(err)
- }
- }
-
- if fp.SessionAll(nil) != sessionCount {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionRegenerate(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- _, err := fp.SessionRead(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
-
- exists, err := fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if !exists {
- t.Error()
- }
-
- _, err = fp.SessionRegenerate(context.Background(), sid, sidNew)
- if err != nil {
- t.Error(err)
- }
-
- exists, err = fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if exists {
- t.Error()
- }
-
- exists, err = fp.SessionExist(context.Background(), sidNew)
- if err != nil {
- t.Error(err)
- }
- if !exists {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionDestroy(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- _, err := fp.SessionRead(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
-
- exists, err := fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if !exists {
- t.Error()
- }
-
- err = fp.SessionDestroy(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
-
- exists, err = fp.SessionExist(context.Background(), sid)
- if err != nil {
- t.Error(err)
- }
- if exists {
- t.Error()
- }
-}
-
-func TestFileProvider_SessionGC(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 1, sessionPath)
-
- sessionCount := 412
-
- for i := 1; i <= sessionCount; i++ {
- _, err := fp.SessionRead(context.Background(), fmt.Sprintf("%s_%d", sid, i))
- if err != nil {
- t.Error(err)
- }
- }
-
- time.Sleep(2 * time.Second)
-
- fp.SessionGC(nil)
- if fp.SessionAll(nil) != 0 {
- t.Error()
- }
-}
-
-func TestFileSessionStore_Set(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- sessionCount := 100
- s, _ := fp.SessionRead(context.Background(), sid)
- for i := 1; i <= sessionCount; i++ {
- err := s.Set(nil, i, i)
- if err != nil {
- t.Error(err)
- }
- }
-}
-
-func TestFileSessionStore_Get(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- sessionCount := 100
- s, _ := fp.SessionRead(context.Background(), sid)
- for i := 1; i <= sessionCount; i++ {
- _ = s.Set(nil, i, i)
-
- v := s.Get(nil, i)
- if v.(int) != i {
- t.Error()
- }
- }
-}
-
-func TestFileSessionStore_Delete(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- s, _ := fp.SessionRead(context.Background(), sid)
- s.Set(nil, "1", 1)
-
- if s.Get(nil, "1") == nil {
- t.Error()
- }
-
- s.Delete(nil, "1")
-
- if s.Get(nil, "1") != nil {
- t.Error()
- }
-}
-
-func TestFileSessionStore_Flush(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- sessionCount := 100
- s, _ := fp.SessionRead(context.Background(), sid)
- for i := 1; i <= sessionCount; i++ {
- _ = s.Set(nil, i, i)
- }
-
- _ = s.Flush(nil)
-
- for i := 1; i <= sessionCount; i++ {
- if s.Get(nil, i) != nil {
- t.Error()
- }
- }
-}
-
-func TestFileSessionStore_SessionID(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
-
- sessionCount := 85
-
- for i := 1; i <= sessionCount; i++ {
- s, err := fp.SessionRead(context.Background(), fmt.Sprintf("%s_%d", sid, i))
- if err != nil {
- t.Error(err)
- }
- if s.SessionID(nil) != fmt.Sprintf("%s_%d", sid, i) {
- t.Error(err)
- }
- }
-}
-
-func TestFileSessionStore_SessionRelease(t *testing.T) {
- mutex.Lock()
- defer mutex.Unlock()
- os.RemoveAll(sessionPath)
- defer os.RemoveAll(sessionPath)
- fp := &FileProvider{}
-
- _ = fp.SessionInit(context.Background(), 180, sessionPath)
- filepder.savePath = sessionPath
- sessionCount := 85
-
- for i := 1; i <= sessionCount; i++ {
- s, err := fp.SessionRead(context.Background(), fmt.Sprintf("%s_%d", sid, i))
- if err != nil {
- t.Error(err)
- }
-
- s.Set(nil, i, i)
- s.SessionRelease(nil, nil)
- }
-
- for i := 1; i <= sessionCount; i++ {
- s, err := fp.SessionRead(context.Background(), fmt.Sprintf("%s_%d", sid, i))
- if err != nil {
- t.Error(err)
- }
-
- if s.Get(nil, i).(int) != i {
- t.Error()
- }
- }
-}
diff --git a/server/web/session/sess_mem_test.go b/server/web/session/sess_mem_test.go
deleted file mode 100644
index e6d35476..00000000
--- a/server/web/session/sess_mem_test.go
+++ /dev/null
@@ -1,58 +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 session
-
-import (
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
-)
-
-func TestMem(t *testing.T) {
- config := `{"cookieName":"gosessionid","gclifetime":10, "enableSetCookie":true}`
- conf := new(ManagerConfig)
- if err := json.Unmarshal([]byte(config), conf); err != nil {
- t.Fatal("json decode error", err)
- }
- globalSessions, _ := NewManager("memory", conf)
- go globalSessions.GC()
- r, _ := http.NewRequest("GET", "/", nil)
- w := httptest.NewRecorder()
- sess, err := globalSessions.SessionStart(w, r)
- if err != nil {
- t.Fatal("set error,", err)
- }
- defer sess.SessionRelease(nil, w)
- err = sess.Set(nil, "username", "astaxie")
- if err != nil {
- t.Fatal("set error,", err)
- }
- if username := sess.Get(nil, "username"); username != "astaxie" {
- t.Fatal("get username error")
- }
- if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" {
- t.Fatal("setcookie error")
- } else {
- parts := strings.Split(strings.TrimSpace(cookiestr), ";")
- for k, v := range parts {
- nameval := strings.Split(v, "=")
- if k == 0 && nameval[0] != "gosessionid" {
- t.Fatal("error")
- }
- }
- }
-}
diff --git a/server/web/session/ssdb/sess_ssdb_test.go b/server/web/session/ssdb/sess_ssdb_test.go
deleted file mode 100644
index 3de5da0a..00000000
--- a/server/web/session/ssdb/sess_ssdb_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package ssdb
-
-import (
- "context"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestProvider_SessionInit(t *testing.T) {
- // using old style
- savePath := `localhost:8080`
- cp := &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "localhost", cp.Host)
- assert.Equal(t, 8080, cp.Port)
- assert.Equal(t, int64(12), cp.maxLifetime)
-
- savePath = `
-{ "host": "localhost", "port": 8080}
-`
- cp = &Provider{}
- cp.SessionInit(context.Background(), 12, savePath)
- assert.Equal(t, "localhost", cp.Host)
- assert.Equal(t, 8080, cp.Port)
- assert.Equal(t, int64(12), cp.maxLifetime)
-}
diff --git a/server/web/statistics_test.go b/server/web/statistics_test.go
deleted file mode 100644
index 7c83e15a..00000000
--- a/server/web/statistics_test.go
+++ /dev/null
@@ -1,40 +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 web
-
-import (
- "encoding/json"
- "testing"
- "time"
-)
-
-func TestStatics(t *testing.T) {
- StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(2000))
- StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(120000))
- StatisticsMap.AddStatistics("GET", "/api/user", "&admin.user", time.Duration(13000))
- StatisticsMap.AddStatistics("POST", "/api/admin", "&admin.user", time.Duration(14000))
- StatisticsMap.AddStatistics("POST", "/api/user/astaxie", "&admin.user", time.Duration(12000))
- StatisticsMap.AddStatistics("POST", "/api/user/xiemengjun", "&admin.user", time.Duration(13000))
- StatisticsMap.AddStatistics("DELETE", "/api/user", "&admin.user", time.Duration(1400))
- t.Log(StatisticsMap.GetMap())
-
- data := StatisticsMap.GetMapData()
- b, err := json.Marshal(data)
- if err != nil {
- t.Errorf(err.Error())
- }
-
- t.Log(string(b))
-}
diff --git a/server/web/session/README.md b/session/README.md
similarity index 98%
rename from server/web/session/README.md
rename to session/README.md
index a5c3bd6d..6d0a297e 100644
--- a/server/web/session/README.md
+++ b/session/README.md
@@ -101,7 +101,7 @@ Maybe you will find the **memory** provider is a good example.
type Provider interface {
SessionInit(gclifetime int64, config string) error
SessionRead(sid string) (SessionStore, error)
- SessionExist(sid string) (bool, error)
+ SessionExist(sid string) bool
SessionRegenerate(oldsid, sid string) (SessionStore, error)
SessionDestroy(sid string) error
SessionAll() int //get all active session
diff --git a/server/web/session/couchbase/sess_couchbase.go b/session/couchbase/sess_couchbase.go
similarity index 69%
rename from server/web/session/couchbase/sess_couchbase.go
rename to session/couchbase/sess_couchbase.go
index 7f15956a..707d042c 100644
--- a/server/web/session/couchbase/sess_couchbase.go
+++ b/session/couchbase/sess_couchbase.go
@@ -33,15 +33,13 @@
package couchbase
import (
- "context"
- "encoding/json"
"net/http"
"strings"
"sync"
couchbase "github.com/couchbase/go-couchbase"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/session"
)
var couchbpder = &Provider{}
@@ -58,14 +56,14 @@ type SessionStore struct {
// Provider couchabse provided
type Provider struct {
maxlifetime int64
- SavePath string `json:"save_path"`
- Pool string `json:"pool"`
- Bucket string `json:"bucket"`
+ savePath string
+ pool string
+ bucket string
b *couchbase.Bucket
}
// Set value to couchabse session
-func (cs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (cs *SessionStore) Set(key, value interface{}) error {
cs.lock.Lock()
defer cs.lock.Unlock()
cs.values[key] = value
@@ -73,7 +71,7 @@ func (cs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value from couchabse session
-func (cs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (cs *SessionStore) Get(key interface{}) interface{} {
cs.lock.RLock()
defer cs.lock.RUnlock()
if v, ok := cs.values[key]; ok {
@@ -83,7 +81,7 @@ func (cs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in couchbase session by given key
-func (cs *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (cs *SessionStore) Delete(key interface{}) error {
cs.lock.Lock()
defer cs.lock.Unlock()
delete(cs.values, key)
@@ -91,7 +89,7 @@ func (cs *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush Clean all values in couchbase session
-func (cs *SessionStore) Flush(context.Context) error {
+func (cs *SessionStore) Flush() error {
cs.lock.Lock()
defer cs.lock.Unlock()
cs.values = make(map[interface{}]interface{})
@@ -99,12 +97,12 @@ func (cs *SessionStore) Flush(context.Context) error {
}
// SessionID Get couchbase session store id
-func (cs *SessionStore) SessionID(context.Context) string {
+func (cs *SessionStore) SessionID() string {
return cs.sid
}
// SessionRelease Write couchbase session with Gob string
-func (cs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (cs *SessionStore) SessionRelease(w http.ResponseWriter) {
defer cs.b.Close()
bo, err := session.EncodeGob(cs.values)
@@ -116,17 +114,17 @@ func (cs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWrite
}
func (cp *Provider) getBucket() *couchbase.Bucket {
- c, err := couchbase.Connect(cp.SavePath)
+ c, err := couchbase.Connect(cp.savePath)
if err != nil {
return nil
}
- pool, err := c.GetPool(cp.Pool)
+ pool, err := c.GetPool(cp.pool)
if err != nil {
return nil
}
- bucket, err := pool.GetBucket(cp.Bucket)
+ bucket, err := pool.GetBucket(cp.bucket)
if err != nil {
return nil
}
@@ -136,38 +134,25 @@ func (cp *Provider) getBucket() *couchbase.Bucket {
// SessionInit init couchbase session
// savepath like couchbase server REST/JSON URL
-// For v1.x e.g. http://host:port/, Pool, Bucket
-// For v2.x, you should pass json string.
-// e.g. { "save_path": "http://host:port/", "pool": "mypool", "bucket": "mybucket"}
-func (cp *Provider) SessionInit(ctx context.Context, maxlifetime int64, cfg string) error {
+// e.g. http://host:port/, Pool, Bucket
+func (cp *Provider) SessionInit(maxlifetime int64, savePath string) error {
cp.maxlifetime = maxlifetime
- cfg = strings.TrimSpace(cfg)
- // we think this is v2.0, using json to init the session
- if strings.HasPrefix(cfg, "{") {
- return json.Unmarshal([]byte(cfg), cp)
- } else {
- return cp.initOldStyle(cfg)
- }
-}
-
-// initOldStyle keep compatible with v1.x
-func (cp *Provider) initOldStyle(savePath string) error {
configs := strings.Split(savePath, ",")
if len(configs) > 0 {
- cp.SavePath = configs[0]
+ cp.savePath = configs[0]
}
if len(configs) > 1 {
- cp.Pool = configs[1]
+ cp.pool = configs[1]
}
if len(configs) > 2 {
- cp.Bucket = configs[2]
+ cp.bucket = configs[2]
}
return nil
}
// SessionRead read couchbase session by sid
-func (cp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (cp *Provider) SessionRead(sid string) (session.Store, error) {
cp.b = cp.getBucket()
var (
@@ -194,20 +179,20 @@ func (cp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
// SessionExist Check couchbase session exist.
// it checkes sid exist or not.
-func (cp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (cp *Provider) SessionExist(sid string) bool {
cp.b = cp.getBucket()
defer cp.b.Close()
var doc []byte
if err := cp.b.Get(sid, &doc); err != nil || doc == nil {
- return false, err
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate remove oldsid and use sid to generate new session
-func (cp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (cp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
cp.b = cp.getBucket()
var doc []byte
@@ -239,8 +224,8 @@ func (cp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (
return cs, nil
}
-// SessionDestroy Remove Bucket in this couchbase
-func (cp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+// SessionDestroy Remove bucket in this couchbase
+func (cp *Provider) SessionDestroy(sid string) error {
cp.b = cp.getBucket()
defer cp.b.Close()
@@ -249,11 +234,11 @@ func (cp *Provider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC Recycle
-func (cp *Provider) SessionGC(context.Context) {
+func (cp *Provider) SessionGC() {
}
// SessionAll return all active session
-func (cp *Provider) SessionAll(context.Context) int {
+func (cp *Provider) SessionAll() int {
return 0
}
diff --git a/server/web/session/ledis/ledis_session.go b/session/ledis/ledis_session.go
similarity index 59%
rename from server/web/session/ledis/ledis_session.go
rename to session/ledis/ledis_session.go
index 5b930fcd..ee81df67 100644
--- a/server/web/session/ledis/ledis_session.go
+++ b/session/ledis/ledis_session.go
@@ -2,8 +2,6 @@
package ledis
import (
- "context"
- "encoding/json"
"net/http"
"strconv"
"strings"
@@ -12,7 +10,7 @@ import (
"github.com/ledisdb/ledisdb/config"
"github.com/ledisdb/ledisdb/ledis"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/session"
)
var (
@@ -29,7 +27,7 @@ type SessionStore struct {
}
// Set value in ledis session
-func (ls *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (ls *SessionStore) Set(key, value interface{}) error {
ls.lock.Lock()
defer ls.lock.Unlock()
ls.values[key] = value
@@ -37,7 +35,7 @@ func (ls *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value in ledis session
-func (ls *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (ls *SessionStore) Get(key interface{}) interface{} {
ls.lock.RLock()
defer ls.lock.RUnlock()
if v, ok := ls.values[key]; ok {
@@ -47,7 +45,7 @@ func (ls *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in ledis session
-func (ls *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (ls *SessionStore) Delete(key interface{}) error {
ls.lock.Lock()
defer ls.lock.Unlock()
delete(ls.values, key)
@@ -55,7 +53,7 @@ func (ls *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in ledis session
-func (ls *SessionStore) Flush(context.Context) error {
+func (ls *SessionStore) Flush() error {
ls.lock.Lock()
defer ls.lock.Unlock()
ls.values = make(map[interface{}]interface{})
@@ -63,12 +61,12 @@ func (ls *SessionStore) Flush(context.Context) error {
}
// SessionID get ledis session id
-func (ls *SessionStore) SessionID(context.Context) string {
+func (ls *SessionStore) SessionID() string {
return ls.sid
}
// SessionRelease save session values to ledis
-func (ls *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (ls *SessionStore) SessionRelease(w http.ResponseWriter) {
b, err := session.EncodeGob(ls.values)
if err != nil {
return
@@ -80,56 +78,40 @@ func (ls *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWrite
// Provider ledis session provider
type Provider struct {
maxlifetime int64
- SavePath string `json:"save_path"`
- Db int `json:"db"`
+ savePath string
+ db int
}
// SessionInit init ledis session
// savepath like ledis server saveDataPath,pool size
-// v1.x e.g. 127.0.0.1:6379,100
-// v2.x you should pass a json string
-// e.g. { "save_path": "my save path", "db": 100}
-func (lp *Provider) SessionInit(ctx context.Context, maxlifetime int64, cfgStr string) error {
+// e.g. 127.0.0.1:6379,100,astaxie
+func (lp *Provider) SessionInit(maxlifetime int64, savePath string) error {
var err error
lp.maxlifetime = maxlifetime
- cfgStr = strings.TrimSpace(cfgStr)
- // we think cfgStr is v2.0, using json to init the session
- if strings.HasPrefix(cfgStr, "{") {
- err = json.Unmarshal([]byte(cfgStr), lp)
- } else {
- err = lp.initOldStyle(cfgStr)
+ configs := strings.Split(savePath, ",")
+ if len(configs) == 1 {
+ lp.savePath = configs[0]
+ } else if len(configs) == 2 {
+ lp.savePath = configs[0]
+ lp.db, err = strconv.Atoi(configs[1])
+ if err != nil {
+ return err
+ }
}
-
- if err != nil {
- return err
- }
-
cfg := new(config.Config)
- cfg.DataDir = lp.SavePath
+ cfg.DataDir = lp.savePath
var ledisInstance *ledis.Ledis
ledisInstance, err = ledis.Open(cfg)
if err != nil {
return err
}
- c, err = ledisInstance.Select(lp.Db)
- return err
-}
-
-func (lp *Provider) initOldStyle(cfgStr string) error {
- var err error
- configs := strings.Split(cfgStr, ",")
- if len(configs) == 1 {
- lp.SavePath = configs[0]
- } else if len(configs) == 2 {
- lp.SavePath = configs[0]
- lp.Db, err = strconv.Atoi(configs[1])
- }
+ c, err = ledisInstance.Select(lp.db)
return err
}
// SessionRead read ledis session by sid
-func (lp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (lp *Provider) SessionRead(sid string) (session.Store, error) {
var (
kv map[interface{}]interface{}
err error
@@ -150,13 +132,13 @@ func (lp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check ledis session exist by sid
-func (lp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (lp *Provider) SessionExist(sid string) bool {
count, _ := c.Exists([]byte(sid))
- return count != 0, nil
+ return count != 0
}
// SessionRegenerate generate new sid for ledis session
-func (lp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (lp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
count, _ := c.Exists([]byte(sid))
if count == 0 {
// oldsid doesn't exists, set the new sid directly
@@ -169,21 +151,21 @@ func (lp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (
c.Set([]byte(sid), data)
c.Expire([]byte(sid), lp.maxlifetime)
}
- return lp.SessionRead(context.Background(), sid)
+ return lp.SessionRead(sid)
}
// SessionDestroy delete ledis session by id
-func (lp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (lp *Provider) SessionDestroy(sid string) error {
c.Del([]byte(sid))
return nil
}
// SessionGC Impelment method, no used.
-func (lp *Provider) SessionGC(context.Context) {
+func (lp *Provider) SessionGC() {
}
// SessionAll return all active session
-func (lp *Provider) SessionAll(context.Context) int {
+func (lp *Provider) SessionAll() int {
return 0
}
func init() {
diff --git a/server/web/session/memcache/sess_memcache.go b/session/memcache/sess_memcache.go
similarity index 81%
rename from server/web/session/memcache/sess_memcache.go
rename to session/memcache/sess_memcache.go
index 168116ef..85a2d815 100644
--- a/server/web/session/memcache/sess_memcache.go
+++ b/session/memcache/sess_memcache.go
@@ -33,12 +33,11 @@
package memcache
import (
- "context"
"net/http"
"strings"
"sync"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/session"
"github.com/bradfitz/gomemcache/memcache"
)
@@ -55,7 +54,7 @@ type SessionStore struct {
}
// Set value in memcache session
-func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (rs *SessionStore) Set(key, value interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values[key] = value
@@ -63,7 +62,7 @@ func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value in memcache session
-func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (rs *SessionStore) Get(key interface{}) interface{} {
rs.lock.RLock()
defer rs.lock.RUnlock()
if v, ok := rs.values[key]; ok {
@@ -73,7 +72,7 @@ func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in memcache session
-func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (rs *SessionStore) Delete(key interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
delete(rs.values, key)
@@ -81,7 +80,7 @@ func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in memcache session
-func (rs *SessionStore) Flush(context.Context) error {
+func (rs *SessionStore) Flush() error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values = make(map[interface{}]interface{})
@@ -89,12 +88,12 @@ func (rs *SessionStore) Flush(context.Context) error {
}
// SessionID get memcache session id
-func (rs *SessionStore) SessionID(context.Context) string {
+func (rs *SessionStore) SessionID() string {
return rs.sid
}
// SessionRelease save session values to memcache
-func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
if err != nil {
return
@@ -114,7 +113,7 @@ type MemProvider struct {
// SessionInit init memcache session
// savepath like
// e.g. 127.0.0.1:9090
-func (rp *MemProvider) SessionInit(ctx context.Context, maxlifetime int64, savePath string) error {
+func (rp *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
rp.conninfo = strings.Split(savePath, ";")
client = memcache.New(rp.conninfo...)
@@ -122,7 +121,7 @@ func (rp *MemProvider) SessionInit(ctx context.Context, maxlifetime int64, saveP
}
// SessionRead read memcache session by sid
-func (rp *MemProvider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (rp *MemProvider) SessionRead(sid string) (session.Store, error) {
if client == nil {
if err := rp.connectInit(); err != nil {
return nil, err
@@ -150,20 +149,20 @@ func (rp *MemProvider) SessionRead(ctx context.Context, sid string) (session.Sto
}
// SessionExist check memcache session exist by sid
-func (rp *MemProvider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (rp *MemProvider) SessionExist(sid string) bool {
if client == nil {
if err := rp.connectInit(); err != nil {
- return false, err
+ return false
}
}
if item, err := client.Get(sid); err != nil || len(item.Value) == 0 {
- return false, err
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate generate new sid for memcache session
-func (rp *MemProvider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
if client == nil {
if err := rp.connectInit(); err != nil {
return nil, err
@@ -202,7 +201,7 @@ func (rp *MemProvider) SessionRegenerate(ctx context.Context, oldsid, sid string
}
// SessionDestroy delete memcache session by id
-func (rp *MemProvider) SessionDestroy(ctx context.Context, sid string) error {
+func (rp *MemProvider) SessionDestroy(sid string) error {
if client == nil {
if err := rp.connectInit(); err != nil {
return err
@@ -218,11 +217,11 @@ func (rp *MemProvider) connectInit() error {
}
// SessionGC Impelment method, no used.
-func (rp *MemProvider) SessionGC(context.Context) {
+func (rp *MemProvider) SessionGC() {
}
// SessionAll return all activeSession
-func (rp *MemProvider) SessionAll(context.Context) int {
+func (rp *MemProvider) SessionAll() int {
return 0
}
diff --git a/server/web/session/mysql/sess_mysql.go b/session/mysql/sess_mysql.go
similarity index 82%
rename from server/web/session/mysql/sess_mysql.go
rename to session/mysql/sess_mysql.go
index 89da361d..301353ab 100644
--- a/server/web/session/mysql/sess_mysql.go
+++ b/session/mysql/sess_mysql.go
@@ -41,13 +41,12 @@
package mysql
import (
- "context"
"database/sql"
"net/http"
"sync"
"time"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/session"
// import mysql driver
_ "github.com/go-sql-driver/mysql"
)
@@ -68,7 +67,7 @@ type SessionStore struct {
// Set value in mysql session.
// it is temp value in map.
-func (st *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (st *SessionStore) Set(key, value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
st.values[key] = value
@@ -76,7 +75,7 @@ func (st *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value from mysql session
-func (st *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (st *SessionStore) Get(key interface{}) interface{} {
st.lock.RLock()
defer st.lock.RUnlock()
if v, ok := st.values[key]; ok {
@@ -86,7 +85,7 @@ func (st *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in mysql session
-func (st *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (st *SessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.values, key)
@@ -94,7 +93,7 @@ func (st *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in mysql session
-func (st *SessionStore) Flush(context.Context) error {
+func (st *SessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
st.values = make(map[interface{}]interface{})
@@ -102,13 +101,13 @@ func (st *SessionStore) Flush(context.Context) error {
}
// SessionID get session id of this mysql session store
-func (st *SessionStore) SessionID(context.Context) string {
+func (st *SessionStore) SessionID() string {
return st.sid
}
// SessionRelease save mysql session values to database.
// must call this method to save values to database.
-func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (st *SessionStore) SessionRelease(w http.ResponseWriter) {
defer st.c.Close()
b, err := session.EncodeGob(st.values)
if err != nil {
@@ -135,14 +134,14 @@ func (mp *Provider) connectInit() *sql.DB {
// SessionInit init mysql session.
// savepath is the connection string of mysql.
-func (mp *Provider) SessionInit(ctx context.Context, maxlifetime int64, savePath string) error {
+func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error {
mp.maxlifetime = maxlifetime
mp.savePath = savePath
return nil
}
// SessionRead get mysql session by sid
-func (mp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (mp *Provider) SessionRead(sid string) (session.Store, error) {
c := mp.connectInit()
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
var sessiondata []byte
@@ -165,23 +164,17 @@ func (mp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check mysql session exist
-func (mp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (mp *Provider) SessionExist(sid string) bool {
c := mp.connectInit()
defer c.Close()
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
var sessiondata []byte
err := row.Scan(&sessiondata)
- if err != nil {
- if err == sql.ErrNoRows {
- return false, nil
- }
- return false, err
- }
- return true, nil
+ return err != sql.ErrNoRows
}
// SessionRegenerate generate new sid for mysql session
-func (mp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
c := mp.connectInit()
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid)
var sessiondata []byte
@@ -204,7 +197,7 @@ func (mp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (
}
// SessionDestroy delete mysql session by sid
-func (mp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (mp *Provider) SessionDestroy(sid string) error {
c := mp.connectInit()
c.Exec("DELETE FROM "+TableName+" where session_key=?", sid)
c.Close()
@@ -212,14 +205,14 @@ func (mp *Provider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC delete expired values in mysql session
-func (mp *Provider) SessionGC(context.Context) {
+func (mp *Provider) SessionGC() {
c := mp.connectInit()
c.Exec("DELETE from "+TableName+" where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
c.Close()
}
// SessionAll count values in mysql session
-func (mp *Provider) SessionAll(context.Context) int {
+func (mp *Provider) SessionAll() int {
c := mp.connectInit()
defer c.Close()
var total int
diff --git a/server/web/session/postgres/sess_postgresql.go b/session/postgres/sess_postgresql.go
similarity index 83%
rename from server/web/session/postgres/sess_postgresql.go
rename to session/postgres/sess_postgresql.go
index a83ac083..0b8b9645 100644
--- a/server/web/session/postgres/sess_postgresql.go
+++ b/session/postgres/sess_postgresql.go
@@ -51,13 +51,12 @@
package postgres
import (
- "context"
"database/sql"
"net/http"
"sync"
"time"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/astaxie/beego/session"
// import postgresql Driver
_ "github.com/lib/pq"
)
@@ -74,7 +73,7 @@ type SessionStore struct {
// Set value in postgresql session.
// it is temp value in map.
-func (st *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (st *SessionStore) Set(key, value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
st.values[key] = value
@@ -82,7 +81,7 @@ func (st *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value from postgresql session
-func (st *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (st *SessionStore) Get(key interface{}) interface{} {
st.lock.RLock()
defer st.lock.RUnlock()
if v, ok := st.values[key]; ok {
@@ -92,7 +91,7 @@ func (st *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in postgresql session
-func (st *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (st *SessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.values, key)
@@ -100,7 +99,7 @@ func (st *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in postgresql session
-func (st *SessionStore) Flush(context.Context) error {
+func (st *SessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
st.values = make(map[interface{}]interface{})
@@ -108,13 +107,13 @@ func (st *SessionStore) Flush(context.Context) error {
}
// SessionID get session id of this postgresql session store
-func (st *SessionStore) SessionID(context.Context) string {
+func (st *SessionStore) SessionID() string {
return st.sid
}
// SessionRelease save postgresql session values to database.
// must call this method to save values to database.
-func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (st *SessionStore) SessionRelease(w http.ResponseWriter) {
defer st.c.Close()
b, err := session.EncodeGob(st.values)
if err != nil {
@@ -142,14 +141,14 @@ func (mp *Provider) connectInit() *sql.DB {
// SessionInit init postgresql session.
// savepath is the connection string of postgresql.
-func (mp *Provider) SessionInit(ctx context.Context, maxlifetime int64, savePath string) error {
+func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error {
mp.maxlifetime = maxlifetime
mp.savePath = savePath
return nil
}
// SessionRead get postgresql session by sid
-func (mp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (mp *Provider) SessionRead(sid string) (session.Store, error) {
c := mp.connectInit()
row := c.QueryRow("select session_data from session where session_key=$1", sid)
var sessiondata []byte
@@ -179,23 +178,17 @@ func (mp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check postgresql session exist
-func (mp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (mp *Provider) SessionExist(sid string) bool {
c := mp.connectInit()
defer c.Close()
row := c.QueryRow("select session_data from session where session_key=$1", sid)
var sessiondata []byte
err := row.Scan(&sessiondata)
- if err != nil {
- if err == sql.ErrNoRows {
- return false, nil
- }
- return false, err
- }
- return true, nil
+ return err != sql.ErrNoRows
}
// SessionRegenerate generate new sid for postgresql session
-func (mp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
c := mp.connectInit()
row := c.QueryRow("select session_data from session where session_key=$1", oldsid)
var sessiondata []byte
@@ -219,7 +212,7 @@ func (mp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (
}
// SessionDestroy delete postgresql session by sid
-func (mp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (mp *Provider) SessionDestroy(sid string) error {
c := mp.connectInit()
c.Exec("DELETE FROM session where session_key=$1", sid)
c.Close()
@@ -227,14 +220,14 @@ func (mp *Provider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC delete expired values in postgresql session
-func (mp *Provider) SessionGC(context.Context) {
+func (mp *Provider) SessionGC() {
c := mp.connectInit()
c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime)
c.Close()
}
// SessionAll count values in postgresql session
-func (mp *Provider) SessionAll(context.Context) int {
+func (mp *Provider) SessionAll() int {
c := mp.connectInit()
defer c.Close()
var total int
diff --git a/server/web/session/redis/sess_redis.go b/session/redis/sess_redis.go
similarity index 50%
rename from server/web/session/redis/sess_redis.go
rename to session/redis/sess_redis.go
index c6e3bcbb..5c382d61 100644
--- a/server/web/session/redis/sess_redis.go
+++ b/session/redis/sess_redis.go
@@ -33,17 +33,15 @@
package redis
import (
- "context"
- "encoding/json"
"net/http"
"strconv"
"strings"
"sync"
"time"
- "github.com/go-redis/redis/v7"
+ "github.com/astaxie/beego/session"
- "github.com/astaxie/beego/server/web/session"
+ "github.com/gomodule/redigo/redis"
)
var redispder = &Provider{}
@@ -53,7 +51,7 @@ var MaxPoolSize = 100
// SessionStore redis session store
type SessionStore struct {
- p *redis.Client
+ p *redis.Pool
sid string
lock sync.RWMutex
values map[interface{}]interface{}
@@ -61,7 +59,7 @@ type SessionStore struct {
}
// Set value in redis session
-func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (rs *SessionStore) Set(key, value interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values[key] = value
@@ -69,7 +67,7 @@ func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value in redis session
-func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (rs *SessionStore) Get(key interface{}) interface{} {
rs.lock.RLock()
defer rs.lock.RUnlock()
if v, ok := rs.values[key]; ok {
@@ -79,7 +77,7 @@ func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in redis session
-func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (rs *SessionStore) Delete(key interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
delete(rs.values, key)
@@ -87,7 +85,7 @@ func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in redis session
-func (rs *SessionStore) Flush(context.Context) error {
+func (rs *SessionStore) Flush() error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values = make(map[interface{}]interface{})
@@ -95,132 +93,109 @@ func (rs *SessionStore) Flush(context.Context) error {
}
// SessionID get redis session id
-func (rs *SessionStore) SessionID(context.Context) string {
+func (rs *SessionStore) SessionID() string {
return rs.sid
}
// SessionRelease save session values to redis
-func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+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)
+ c := rs.p.Get()
+ defer c.Close()
+ c.Do("SETEX", rs.sid, rs.maxlifetime, string(b))
}
// Provider redis session provider
type Provider struct {
maxlifetime int64
- SavePath string `json:"save_path"`
- Poolsize int `json:"poolsize"`
- Password string `json:"password"`
- DbNum int `json:"db_num"`
-
- idleTimeout time.Duration
- IdleTimeoutStr string `json:"idle_timeout"`
-
- idleCheckFrequency time.Duration
- IdleCheckFrequencyStr string `json:"idle_check_frequency"`
- MaxRetries int `json:"max_retries"`
- poollist *redis.Client
+ savePath string
+ poolsize int
+ password string
+ dbNum int
+ poollist *redis.Pool
}
// SessionInit init redis session
// savepath like redis server addr,pool size,password,dbnum,IdleTimeout second
-// v1.x e.g. 127.0.0.1:6379,100,astaxie,0,30
-// v2.0 you should pass json string
-func (rp *Provider) SessionInit(ctx context.Context, maxlifetime int64, cfgStr string) error {
+// e.g. 127.0.0.1:6379,100,astaxie,0,30
+func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
-
- cfgStr = strings.TrimSpace(cfgStr)
- // we think cfgStr is v2.0, using json to init the session
- if strings.HasPrefix(cfgStr, "{") {
- err := json.Unmarshal([]byte(cfgStr), rp)
- if err != nil {
- return err
- }
- rp.idleTimeout, err = time.ParseDuration(rp.IdleTimeoutStr)
- if err != nil {
- return err
- }
-
- rp.idleCheckFrequency, err = time.ParseDuration(rp.IdleCheckFrequencyStr)
- if err != nil {
- return err
- }
-
- } else {
- rp.initOldStyle(cfgStr)
- }
-
- rp.poollist = redis.NewClient(&redis.Options{
- Addr: rp.SavePath,
- Password: rp.Password,
- PoolSize: rp.Poolsize,
- DB: rp.DbNum,
- IdleTimeout: rp.idleTimeout,
- IdleCheckFrequency: rp.idleCheckFrequency,
- MaxRetries: rp.MaxRetries,
- })
-
- return rp.poollist.Ping().Err()
-}
-
-func (rp *Provider) initOldStyle(savePath string) {
configs := strings.Split(savePath, ",")
if len(configs) > 0 {
- rp.SavePath = configs[0]
+ rp.savePath = configs[0]
}
if len(configs) > 1 {
poolsize, err := strconv.Atoi(configs[1])
if err != nil || poolsize < 0 {
- rp.Poolsize = MaxPoolSize
+ rp.poolsize = MaxPoolSize
} else {
- rp.Poolsize = poolsize
+ rp.poolsize = poolsize
}
} else {
- rp.Poolsize = MaxPoolSize
+ rp.poolsize = MaxPoolSize
}
if len(configs) > 2 {
- rp.Password = configs[2]
+ rp.password = configs[2]
}
if len(configs) > 3 {
dbnum, err := strconv.Atoi(configs[3])
if err != nil || dbnum < 0 {
- rp.DbNum = 0
+ rp.dbNum = 0
} else {
- rp.DbNum = dbnum
+ rp.dbNum = dbnum
}
} else {
- rp.DbNum = 0
+ rp.dbNum = 0
}
+ var idleTimeout time.Duration = 0
if len(configs) > 4 {
timeout, err := strconv.Atoi(configs[4])
if err == nil && timeout > 0 {
- rp.idleTimeout = time.Duration(timeout) * time.Second
+ idleTimeout = time.Duration(timeout) * time.Second
}
}
- if len(configs) > 5 {
- checkFrequency, err := strconv.Atoi(configs[5])
- if err == nil && checkFrequency > 0 {
- rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
- }
- }
- if len(configs) > 6 {
- retries, err := strconv.Atoi(configs[6])
- if err == nil && retries > 0 {
- rp.MaxRetries = retries
- }
+ rp.poollist = &redis.Pool{
+ Dial: func() (redis.Conn, error) {
+ c, err := redis.Dial("tcp", rp.savePath)
+ if err != nil {
+ return nil, err
+ }
+ if rp.password != "" {
+ if _, err = c.Do("AUTH", rp.password); err != nil {
+ c.Close()
+ return nil, err
+ }
+ }
+ // some redis proxy such as twemproxy is not support select command
+ if rp.dbNum > 0 {
+ _, err = c.Do("SELECT", rp.dbNum)
+ if err != nil {
+ c.Close()
+ return nil, err
+ }
+ }
+ return c, err
+ },
+ MaxIdle: rp.poolsize,
}
+
+ rp.poollist.IdleTimeout = idleTimeout
+
+ return rp.poollist.Get().Err()
}
// SessionRead read redis session by sid
-func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (rp *Provider) SessionRead(sid string) (session.Store, error) {
+ c := rp.poollist.Get()
+ defer c.Close()
+
var kv map[interface{}]interface{}
- kvs, err := rp.poollist.Get(sid).Result()
- if err != nil && err != redis.Nil {
+ kvs, err := redis.String(c.Do("GET", sid))
+ if err != nil && err != redis.ErrNil {
return nil, err
}
if len(kvs) == 0 {
@@ -236,44 +211,48 @@ func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check redis session exist by sid
-func (rp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
- c := rp.poollist
+func (rp *Provider) SessionExist(sid string) bool {
+ c := rp.poollist.Get()
+ defer c.Close()
- if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
- return false, err
+ if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate generate new sid for redis session
-func (rp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
- c := rp.poollist
- if existed, _ := c.Exists(oldsid).Result(); existed == 0 {
+func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
+ c := rp.poollist.Get()
+ defer c.Close()
+
+ if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); 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.Do(c.Context(), "SET", sid, "", "EX", rp.maxlifetime)
+ c.Do("SET", sid, "", "EX", rp.maxlifetime)
} else {
- c.Rename(oldsid, sid)
- c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
+ c.Do("RENAME", oldsid, sid)
+ c.Do("EXPIRE", sid, rp.maxlifetime)
}
- return rp.SessionRead(context.Background(), sid)
+ return rp.SessionRead(sid)
}
// SessionDestroy delete redis session by id
-func (rp *Provider) SessionDestroy(ctx context.Context, sid string) error {
- c := rp.poollist
+func (rp *Provider) SessionDestroy(sid string) error {
+ c := rp.poollist.Get()
+ defer c.Close()
- c.Del(sid)
+ c.Do("DEL", sid)
return nil
}
// SessionGC Impelment method, no used.
-func (rp *Provider) SessionGC(context.Context) {
+func (rp *Provider) SessionGC() {
}
// SessionAll return all activeSession
-func (rp *Provider) SessionAll(context.Context) int {
+func (rp *Provider) SessionAll() int {
return 0
}
diff --git a/server/web/session/redis_cluster/redis_cluster.go b/session/redis_cluster/redis_cluster.go
similarity index 55%
rename from server/web/session/redis_cluster/redis_cluster.go
rename to session/redis_cluster/redis_cluster.go
index d2971e71..2fe300df 100644
--- a/server/web/session/redis_cluster/redis_cluster.go
+++ b/session/redis_cluster/redis_cluster.go
@@ -31,19 +31,14 @@
//
// more docs: http://beego.me/docs/module/session.md
package redis_cluster
-
import (
- "context"
- "encoding/json"
"net/http"
"strconv"
"strings"
"sync"
+ "github.com/astaxie/beego/session"
+ rediss "github.com/go-redis/redis"
"time"
-
- rediss "github.com/go-redis/redis/v7"
-
- "github.com/astaxie/beego/server/web/session"
)
var redispder = &Provider{}
@@ -61,7 +56,7 @@ type SessionStore struct {
}
// Set value in redis_cluster session
-func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (rs *SessionStore) Set(key, value interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values[key] = value
@@ -69,7 +64,7 @@ func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value in redis_cluster session
-func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (rs *SessionStore) Get(key interface{}) interface{} {
rs.lock.RLock()
defer rs.lock.RUnlock()
if v, ok := rs.values[key]; ok {
@@ -79,7 +74,7 @@ func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in redis_cluster session
-func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (rs *SessionStore) Delete(key interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
delete(rs.values, key)
@@ -87,7 +82,7 @@ func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in redis_cluster session
-func (rs *SessionStore) Flush(context.Context) error {
+func (rs *SessionStore) Flush() error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values = make(map[interface{}]interface{})
@@ -95,125 +90,73 @@ func (rs *SessionStore) Flush(context.Context) error {
}
// SessionID get redis_cluster session id
-func (rs *SessionStore) SessionID(context.Context) string {
+func (rs *SessionStore) SessionID() string {
return rs.sid
}
// SessionRelease save session values to redis_cluster
-func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+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)
+ c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime) * time.Second)
}
// Provider redis_cluster session provider
type Provider struct {
maxlifetime int64
- SavePath string `json:"save_path"`
- Poolsize int `json:"poolsize"`
- Password string `json:"password"`
- DbNum int `json:"db_num"`
-
- idleTimeout time.Duration
- IdleTimeoutStr string `json:"idle_timeout"`
-
- idleCheckFrequency time.Duration
- IdleCheckFrequencyStr string `json:"idle_check_frequency"`
- MaxRetries int `json:"max_retries"`
- poollist *rediss.ClusterClient
+ savePath string
+ poolsize int
+ password string
+ dbNum int
+ poollist *rediss.ClusterClient
}
// SessionInit init redis_cluster session
-// cfgStr like redis server addr,pool size,password,dbnum
+// savepath like redis server addr,pool size,password,dbnum
// e.g. 127.0.0.1:6379;127.0.0.1:6380,100,test,0
-func (rp *Provider) SessionInit(ctx context.Context, maxlifetime int64, cfgStr string) error {
+func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
- cfgStr = strings.TrimSpace(cfgStr)
- // we think cfgStr is v2.0, using json to init the session
- if strings.HasPrefix(cfgStr, "{") {
- err := json.Unmarshal([]byte(cfgStr), rp)
- if err != nil {
- return err
- }
- rp.idleTimeout, err = time.ParseDuration(rp.IdleTimeoutStr)
- if err != nil {
- return err
- }
-
- rp.idleCheckFrequency, err = time.ParseDuration(rp.IdleCheckFrequencyStr)
- if err != nil {
- return err
- }
-
- } else {
- rp.initOldStyle(cfgStr)
- }
-
- rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
- Addrs: strings.Split(rp.SavePath, ";"),
- Password: rp.Password,
- PoolSize: rp.Poolsize,
- IdleTimeout: rp.idleTimeout,
- IdleCheckFrequency: rp.idleCheckFrequency,
- MaxRetries: rp.MaxRetries,
- })
- return rp.poollist.Ping().Err()
-}
-
-// for v1.x
-func (rp *Provider) initOldStyle(savePath string) {
configs := strings.Split(savePath, ",")
if len(configs) > 0 {
- rp.SavePath = configs[0]
+ rp.savePath = configs[0]
}
if len(configs) > 1 {
poolsize, err := strconv.Atoi(configs[1])
if err != nil || poolsize < 0 {
- rp.Poolsize = MaxPoolSize
+ rp.poolsize = MaxPoolSize
} else {
- rp.Poolsize = poolsize
+ rp.poolsize = poolsize
}
} else {
- rp.Poolsize = MaxPoolSize
+ rp.poolsize = MaxPoolSize
}
if len(configs) > 2 {
- rp.Password = configs[2]
+ rp.password = configs[2]
}
if len(configs) > 3 {
dbnum, err := strconv.Atoi(configs[3])
if err != nil || dbnum < 0 {
- rp.DbNum = 0
+ rp.dbNum = 0
} else {
- rp.DbNum = dbnum
+ rp.dbNum = dbnum
}
} else {
- rp.DbNum = 0
- }
- if len(configs) > 4 {
- timeout, err := strconv.Atoi(configs[4])
- if err == nil && timeout > 0 {
- rp.idleTimeout = time.Duration(timeout) * time.Second
- }
- }
- if len(configs) > 5 {
- checkFrequency, err := strconv.Atoi(configs[5])
- if err == nil && checkFrequency > 0 {
- rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
- }
- }
- if len(configs) > 6 {
- retries, err := strconv.Atoi(configs[6])
- if err == nil && retries > 0 {
- rp.MaxRetries = retries
- }
+ rp.dbNum = 0
}
+
+ rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
+ Addrs: strings.Split(rp.savePath, ";"),
+ Password: rp.password,
+ PoolSize: rp.poolsize,
+ })
+ return rp.poollist.Ping().Err()
}
// SessionRead read redis_cluster session by sid
-func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+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 != rediss.Nil {
@@ -232,43 +175,43 @@ func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check redis_cluster session exist by sid
-func (rp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (rp *Provider) SessionExist(sid string) bool {
c := rp.poollist
if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
- return false, err
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate generate new sid for redis_cluster session
-func (rp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+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)
+ c.Set(sid, "", time.Duration(rp.maxlifetime) * time.Second)
} else {
c.Rename(oldsid, sid)
- c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
+ c.Expire(sid, time.Duration(rp.maxlifetime) * time.Second)
}
- return rp.SessionRead(context.Background(), sid)
+ return rp.SessionRead(sid)
}
// SessionDestroy delete redis session by id
-func (rp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (rp *Provider) SessionDestroy(sid string) error {
c := rp.poollist
c.Del(sid)
return nil
}
// SessionGC Impelment method, no used.
-func (rp *Provider) SessionGC(context.Context) {
+func (rp *Provider) SessionGC() {
}
// SessionAll return all activeSession
-func (rp *Provider) SessionAll(context.Context) int {
+func (rp *Provider) SessionAll() int {
return 0
}
diff --git a/server/web/session/redis_sentinel/sess_redis_sentinel.go b/session/redis_sentinel/sess_redis_sentinel.go
similarity index 57%
rename from server/web/session/redis_sentinel/sess_redis_sentinel.go
rename to session/redis_sentinel/sess_redis_sentinel.go
index 89d73b86..6ecb2977 100644
--- a/server/web/session/redis_sentinel/sess_redis_sentinel.go
+++ b/session/redis_sentinel/sess_redis_sentinel.go
@@ -33,17 +33,13 @@
package redis_sentinel
import (
- "context"
- "encoding/json"
+ "github.com/astaxie/beego/session"
+ "github.com/go-redis/redis"
"net/http"
"strconv"
"strings"
"sync"
"time"
-
- "github.com/go-redis/redis/v7"
-
- "github.com/astaxie/beego/server/web/session"
)
var redispder = &Provider{}
@@ -61,7 +57,7 @@ type SessionStore struct {
}
// Set value in redis_sentinel session
-func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (rs *SessionStore) Set(key, value interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values[key] = value
@@ -69,7 +65,7 @@ func (rs *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get value in redis_sentinel session
-func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (rs *SessionStore) Get(key interface{}) interface{} {
rs.lock.RLock()
defer rs.lock.RUnlock()
if v, ok := rs.values[key]; ok {
@@ -79,7 +75,7 @@ func (rs *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete value in redis_sentinel session
-func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (rs *SessionStore) Delete(key interface{}) error {
rs.lock.Lock()
defer rs.lock.Unlock()
delete(rs.values, key)
@@ -87,7 +83,7 @@ func (rs *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in redis_sentinel session
-func (rs *SessionStore) Flush(context.Context) error {
+func (rs *SessionStore) Flush() error {
rs.lock.Lock()
defer rs.lock.Unlock()
rs.values = make(map[interface{}]interface{})
@@ -95,12 +91,12 @@ func (rs *SessionStore) Flush(context.Context) error {
}
// SessionID get redis_sentinel session id
-func (rs *SessionStore) SessionID(context.Context) string {
+func (rs *SessionStore) SessionID() string {
return rs.sid
}
// SessionRelease save session values to redis_sentinel
-func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
if err != nil {
return
@@ -112,121 +108,69 @@ func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWrite
// Provider redis_sentinel session provider
type Provider struct {
maxlifetime int64
- SavePath string `json:"save_path"`
- Poolsize int `json:"poolsize"`
- Password string `json:"password"`
- DbNum int `json:"db_num"`
-
- idleTimeout time.Duration
- IdleTimeoutStr string `json:"idle_timeout"`
-
- idleCheckFrequency time.Duration
- IdleCheckFrequencyStr string `json:"idle_check_frequency"`
- MaxRetries int `json:"max_retries"`
- poollist *redis.Client
- MasterName string `json:"master_name"`
+ savePath string
+ poolsize int
+ password string
+ dbNum int
+ poollist *redis.Client
+ masterName string
}
// SessionInit init redis_sentinel session
-// cfgStr like redis sentinel addr,pool size,password,dbnum,masterName
+// 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(ctx context.Context, maxlifetime int64, cfgStr string) error {
+func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
- cfgStr = strings.TrimSpace(cfgStr)
- // we think cfgStr is v2.0, using json to init the session
- if strings.HasPrefix(cfgStr, "{") {
- err := json.Unmarshal([]byte(cfgStr), rp)
- if err != nil {
- return err
+ 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
}
- rp.idleTimeout, err = time.ParseDuration(rp.IdleTimeoutStr)
- if err != nil {
- return err
- }
-
- rp.idleCheckFrequency, err = time.ParseDuration(rp.IdleCheckFrequencyStr)
- if err != nil {
- return err
- }
-
} else {
- rp.initOldStyle(cfgStr)
+ 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,
- IdleTimeout: rp.idleTimeout,
- IdleCheckFrequency: rp.idleCheckFrequency,
- MaxRetries: rp.MaxRetries,
+ SentinelAddrs: strings.Split(rp.savePath, ";"),
+ Password: rp.password,
+ PoolSize: rp.poolsize,
+ DB: rp.dbNum,
+ MasterName: rp.masterName,
})
return rp.poollist.Ping().Err()
}
-// for v1.x
-func (rp *Provider) initOldStyle(savePath string) {
- 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"
- }
- if len(configs) > 5 {
- timeout, err := strconv.Atoi(configs[4])
- if err == nil && timeout > 0 {
- rp.idleTimeout = time.Duration(timeout) * time.Second
- }
- }
- if len(configs) > 6 {
- checkFrequency, err := strconv.Atoi(configs[5])
- if err == nil && checkFrequency > 0 {
- rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
- }
- }
- if len(configs) > 7 {
- retries, err := strconv.Atoi(configs[6])
- if err == nil && retries > 0 {
- rp.MaxRetries = retries
- }
- }
-}
-
// SessionRead read redis_sentinel session by sid
-func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+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 {
@@ -245,16 +189,16 @@ func (rp *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist check redis_sentinel session exist by sid
-func (rp *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (rp *Provider) SessionExist(sid string) bool {
c := rp.poollist
if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
- return false, err
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate generate new sid for redis_sentinel session
-func (rp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
+func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
c := rp.poollist
if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 {
@@ -266,22 +210,22 @@ func (rp *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (
c.Rename(oldsid, sid)
c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
}
- return rp.SessionRead(context.Background(), sid)
+ return rp.SessionRead(sid)
}
// SessionDestroy delete redis session by id
-func (rp *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (rp *Provider) SessionDestroy(sid string) error {
c := rp.poollist
c.Del(sid)
return nil
}
// SessionGC Impelment method, no used.
-func (rp *Provider) SessionGC(context.Context) {
+func (rp *Provider) SessionGC() {
}
// SessionAll return all activeSession
-func (rp *Provider) SessionAll(context.Context) int {
+func (rp *Provider) SessionAll() int {
return 0
}
diff --git a/adapter/session/redis_sentinel/sess_redis_sentinel_test.go b/session/redis_sentinel/sess_redis_sentinel_test.go
similarity index 96%
rename from adapter/session/redis_sentinel/sess_redis_sentinel_test.go
rename to session/redis_sentinel/sess_redis_sentinel_test.go
index 407d32ab..fd4155c6 100644
--- a/adapter/session/redis_sentinel/sess_redis_sentinel_test.go
+++ b/session/redis_sentinel/sess_redis_sentinel_test.go
@@ -5,7 +5,7 @@ import (
"net/http/httptest"
"testing"
- "github.com/astaxie/beego/adapter/session"
+ "github.com/astaxie/beego/session"
)
func TestRedisSentinel(t *testing.T) {
@@ -23,7 +23,7 @@ func TestRedisSentinel(t *testing.T) {
t.Log(e)
return
}
- // todo test if e==nil
+ //todo test if e==nil
go globalSessions.GC()
r, _ := http.NewRequest("GET", "/", nil)
diff --git a/server/web/session/sess_cookie.go b/session/sess_cookie.go
similarity index 77%
rename from server/web/session/sess_cookie.go
rename to session/sess_cookie.go
index 649f6510..6ad5debc 100644
--- a/server/web/session/sess_cookie.go
+++ b/session/sess_cookie.go
@@ -15,7 +15,6 @@
package session
import (
- "context"
"crypto/aes"
"crypto/cipher"
"encoding/json"
@@ -35,7 +34,7 @@ type CookieSessionStore struct {
// Set value to cookie session.
// the value are encoded as gob with hash block string.
-func (st *CookieSessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (st *CookieSessionStore) Set(key, value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
st.values[key] = value
@@ -43,7 +42,7 @@ func (st *CookieSessionStore) Set(ctx context.Context, key, value interface{}) e
}
// Get value from cookie session
-func (st *CookieSessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (st *CookieSessionStore) Get(key interface{}) interface{} {
st.lock.RLock()
defer st.lock.RUnlock()
if v, ok := st.values[key]; ok {
@@ -53,7 +52,7 @@ func (st *CookieSessionStore) Get(ctx context.Context, key interface{}) interfac
}
// Delete value in cookie session
-func (st *CookieSessionStore) Delete(ctx context.Context, key interface{}) error {
+func (st *CookieSessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.values, key)
@@ -61,7 +60,7 @@ func (st *CookieSessionStore) Delete(ctx context.Context, key interface{}) error
}
// Flush Clean all values in cookie session
-func (st *CookieSessionStore) Flush(context.Context) error {
+func (st *CookieSessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
st.values = make(map[interface{}]interface{})
@@ -69,12 +68,12 @@ func (st *CookieSessionStore) Flush(context.Context) error {
}
// SessionID Return id of this cookie session
-func (st *CookieSessionStore) SessionID(context.Context) string {
+func (st *CookieSessionStore) SessionID() string {
return st.sid
}
// SessionRelease Write cookie session to http response cookie
-func (st *CookieSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
st.lock.Lock()
encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values)
st.lock.Unlock()
@@ -113,7 +112,7 @@ type CookieProvider struct {
// securityName - recognized name in encoded cookie string
// cookieName - cookie name
// maxage - cookie max life time.
-func (pder *CookieProvider) SessionInit(ctx context.Context, maxlifetime int64, config string) error {
+func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error {
pder.config = &cookieConfig{}
err := json.Unmarshal([]byte(config), pder.config)
if err != nil {
@@ -135,7 +134,7 @@ func (pder *CookieProvider) SessionInit(ctx context.Context, maxlifetime int64,
// SessionRead Get SessionStore in cooke.
// decode cooke string to map and put into SessionStore with sid.
-func (pder *CookieProvider) SessionRead(ctx context.Context, sid string) (Store, error) {
+func (pder *CookieProvider) SessionRead(sid string) (Store, error) {
maps, _ := decodeCookie(pder.block,
pder.config.SecurityKey,
pder.config.SecurityName,
@@ -148,31 +147,31 @@ func (pder *CookieProvider) SessionRead(ctx context.Context, sid string) (Store,
}
// SessionExist Cookie session is always existed
-func (pder *CookieProvider) SessionExist(ctx context.Context, sid string) (bool, error) {
- return true, nil
+func (pder *CookieProvider) SessionExist(sid string) bool {
+ return true
}
// SessionRegenerate Implement method, no used.
-func (pder *CookieProvider) SessionRegenerate(ctx context.Context, oldsid, sid string) (Store, error) {
+func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
return nil, nil
}
// SessionDestroy Implement method, no used.
-func (pder *CookieProvider) SessionDestroy(ctx context.Context, sid string) error {
+func (pder *CookieProvider) SessionDestroy(sid string) error {
return nil
}
// SessionGC Implement method, no used.
-func (pder *CookieProvider) SessionGC(context.Context) {
+func (pder *CookieProvider) SessionGC() {
}
// SessionAll Implement method, return 0.
-func (pder *CookieProvider) SessionAll(context.Context) int {
+func (pder *CookieProvider) SessionAll() int {
return 0
}
// SessionUpdate Implement method, no used.
-func (pder *CookieProvider) SessionUpdate(ctx context.Context, sid string) error {
+func (pder *CookieProvider) SessionUpdate(sid string) error {
return nil
}
diff --git a/adapter/session/sess_cookie_test.go b/session/sess_cookie_test.go
similarity index 100%
rename from adapter/session/sess_cookie_test.go
rename to session/sess_cookie_test.go
diff --git a/server/web/session/sess_file.go b/session/sess_file.go
similarity index 85%
rename from server/web/session/sess_file.go
rename to session/sess_file.go
index 90de9a79..c6dbf209 100644
--- a/server/web/session/sess_file.go
+++ b/session/sess_file.go
@@ -15,12 +15,11 @@
package session
import (
- "context"
- "errors"
"fmt"
"io/ioutil"
"net/http"
"os"
+ "errors"
"path"
"path/filepath"
"strings"
@@ -41,7 +40,7 @@ type FileSessionStore struct {
}
// Set value to file session
-func (fs *FileSessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (fs *FileSessionStore) Set(key, value interface{}) error {
fs.lock.Lock()
defer fs.lock.Unlock()
fs.values[key] = value
@@ -49,7 +48,7 @@ func (fs *FileSessionStore) Set(ctx context.Context, key, value interface{}) err
}
// Get value from file session
-func (fs *FileSessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (fs *FileSessionStore) Get(key interface{}) interface{} {
fs.lock.RLock()
defer fs.lock.RUnlock()
if v, ok := fs.values[key]; ok {
@@ -59,7 +58,7 @@ func (fs *FileSessionStore) Get(ctx context.Context, key interface{}) interface{
}
// Delete value in file session by given key
-func (fs *FileSessionStore) Delete(ctx context.Context, key interface{}) error {
+func (fs *FileSessionStore) Delete(key interface{}) error {
fs.lock.Lock()
defer fs.lock.Unlock()
delete(fs.values, key)
@@ -67,7 +66,7 @@ func (fs *FileSessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush Clean all values in file session
-func (fs *FileSessionStore) Flush(context.Context) error {
+func (fs *FileSessionStore) Flush() error {
fs.lock.Lock()
defer fs.lock.Unlock()
fs.values = make(map[interface{}]interface{})
@@ -75,12 +74,12 @@ func (fs *FileSessionStore) Flush(context.Context) error {
}
// SessionID Get file session store id
-func (fs *FileSessionStore) SessionID(context.Context) string {
+func (fs *FileSessionStore) SessionID() string {
return fs.sid
}
// SessionRelease Write file session to local file with Gob string
-func (fs *FileSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
filepder.lock.Lock()
defer filepder.lock.Unlock()
b, err := EncodeGob(fs.values)
@@ -120,7 +119,7 @@ type FileProvider struct {
// SessionInit Init file session provider.
// savePath sets the session files path.
-func (fp *FileProvider) SessionInit(ctx context.Context, maxlifetime int64, savePath string) error {
+func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error {
fp.maxlifetime = maxlifetime
fp.savePath = savePath
return nil
@@ -129,7 +128,7 @@ func (fp *FileProvider) SessionInit(ctx context.Context, maxlifetime int64, save
// SessionRead Read file session by sid.
// if file is not exist, create it.
// the file path is generated from sid string.
-func (fp *FileProvider) SessionRead(ctx context.Context, sid string) (Store, error) {
+func (fp *FileProvider) SessionRead(sid string) (Store, error) {
invalidChars := "./"
if strings.ContainsAny(sid, invalidChars) {
return nil, errors.New("the sid shouldn't have following characters: " + invalidChars)
@@ -177,21 +176,16 @@ func (fp *FileProvider) SessionRead(ctx context.Context, sid string) (Store, err
// SessionExist Check file session exist.
// it checks the file named from sid exist or not.
-func (fp *FileProvider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (fp *FileProvider) SessionExist(sid string) bool {
filepder.lock.Lock()
defer filepder.lock.Unlock()
- if len(sid) < 2 {
- SLogger.Println("min length of session id is 2 but got length: ", sid)
- return false, errors.New("min length of session id is 2")
- }
-
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
- return err == nil, nil
+ return err == nil
}
// SessionDestroy Remove all files in this save path
-func (fp *FileProvider) SessionDestroy(ctx context.Context, sid string) error {
+func (fp *FileProvider) SessionDestroy(sid string) error {
filepder.lock.Lock()
defer filepder.lock.Unlock()
os.Remove(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
@@ -199,7 +193,7 @@ func (fp *FileProvider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC Recycle files in save path
-func (fp *FileProvider) SessionGC(context.Context) {
+func (fp *FileProvider) SessionGC() {
filepder.lock.Lock()
defer filepder.lock.Unlock()
@@ -209,7 +203,7 @@ func (fp *FileProvider) SessionGC(context.Context) {
// SessionAll Get active file session number.
// it walks save path to count files.
-func (fp *FileProvider) SessionAll(context.Context) int {
+func (fp *FileProvider) SessionAll() int {
a := &activeSession{}
err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error {
return a.visit(path, f, err)
@@ -223,7 +217,7 @@ func (fp *FileProvider) SessionAll(context.Context) int {
// SessionRegenerate Generate new sid for file session.
// it delete old file and create new file named from new sid.
-func (fp *FileProvider) SessionRegenerate(ctx context.Context, oldsid, sid string) (Store, error) {
+func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
filepder.lock.Lock()
defer filepder.lock.Unlock()
diff --git a/server/web/session/sess_mem.go b/session/sess_mem.go
similarity index 78%
rename from server/web/session/sess_mem.go
rename to session/sess_mem.go
index 27e24c73..64d8b056 100644
--- a/server/web/session/sess_mem.go
+++ b/session/sess_mem.go
@@ -16,7 +16,6 @@ package session
import (
"container/list"
- "context"
"net/http"
"sync"
"time"
@@ -34,7 +33,7 @@ type MemSessionStore struct {
}
// Set value to memory session
-func (st *MemSessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (st *MemSessionStore) Set(key, value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
st.value[key] = value
@@ -42,7 +41,7 @@ func (st *MemSessionStore) Set(ctx context.Context, key, value interface{}) erro
}
// Get value from memory session by key
-func (st *MemSessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (st *MemSessionStore) Get(key interface{}) interface{} {
st.lock.RLock()
defer st.lock.RUnlock()
if v, ok := st.value[key]; ok {
@@ -52,7 +51,7 @@ func (st *MemSessionStore) Get(ctx context.Context, key interface{}) interface{}
}
// Delete in memory session by key
-func (st *MemSessionStore) Delete(ctx context.Context, key interface{}) error {
+func (st *MemSessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.value, key)
@@ -60,7 +59,7 @@ func (st *MemSessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush clear all values in memory session
-func (st *MemSessionStore) Flush(context.Context) error {
+func (st *MemSessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
st.value = make(map[interface{}]interface{})
@@ -68,12 +67,12 @@ func (st *MemSessionStore) Flush(context.Context) error {
}
// SessionID get this id of memory session store
-func (st *MemSessionStore) SessionID(context.Context) string {
+func (st *MemSessionStore) SessionID() string {
return st.sid
}
// SessionRelease Implement method, no used.
-func (st *MemSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) {
}
// MemProvider Implement the provider interface
@@ -86,17 +85,17 @@ type MemProvider struct {
}
// SessionInit init memory session
-func (pder *MemProvider) SessionInit(ctx context.Context, maxlifetime int64, savePath string) error {
+func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
pder.maxlifetime = maxlifetime
pder.savePath = savePath
return nil
}
// SessionRead get memory session store by sid
-func (pder *MemProvider) SessionRead(ctx context.Context, sid string) (Store, error) {
+func (pder *MemProvider) SessionRead(sid string) (Store, error) {
pder.lock.RLock()
if element, ok := pder.sessions[sid]; ok {
- go pder.SessionUpdate(nil, sid)
+ go pder.SessionUpdate(sid)
pder.lock.RUnlock()
return element.Value.(*MemSessionStore), nil
}
@@ -110,20 +109,20 @@ func (pder *MemProvider) SessionRead(ctx context.Context, sid string) (Store, er
}
// SessionExist check session store exist in memory session by sid
-func (pder *MemProvider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (pder *MemProvider) SessionExist(sid string) bool {
pder.lock.RLock()
defer pder.lock.RUnlock()
if _, ok := pder.sessions[sid]; ok {
- return true, nil
+ return true
}
- return false, nil
+ return false
}
// SessionRegenerate generate new sid for session store in memory session
-func (pder *MemProvider) SessionRegenerate(ctx context.Context, oldsid, sid string) (Store, error) {
+func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
pder.lock.RLock()
if element, ok := pder.sessions[oldsid]; ok {
- go pder.SessionUpdate(nil, oldsid)
+ go pder.SessionUpdate(oldsid)
pder.lock.RUnlock()
pder.lock.Lock()
element.Value.(*MemSessionStore).sid = sid
@@ -142,7 +141,7 @@ func (pder *MemProvider) SessionRegenerate(ctx context.Context, oldsid, sid stri
}
// SessionDestroy delete session store in memory session by id
-func (pder *MemProvider) SessionDestroy(ctx context.Context, sid string) error {
+func (pder *MemProvider) SessionDestroy(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
@@ -154,7 +153,7 @@ func (pder *MemProvider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC clean expired session stores in memory session
-func (pder *MemProvider) SessionGC(context.Context) {
+func (pder *MemProvider) SessionGC() {
pder.lock.RLock()
for {
element := pder.list.Back()
@@ -176,12 +175,12 @@ func (pder *MemProvider) SessionGC(context.Context) {
}
// SessionAll get count number of memory session
-func (pder *MemProvider) SessionAll(context.Context) int {
+func (pder *MemProvider) SessionAll() int {
return pder.list.Len()
}
// SessionUpdate expand time of session store by id in memory session
-func (pder *MemProvider) SessionUpdate(ctx context.Context, sid string) error {
+func (pder *MemProvider) SessionUpdate(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
diff --git a/adapter/session/sess_mem_test.go b/session/sess_mem_test.go
similarity index 100%
rename from adapter/session/sess_mem_test.go
rename to session/sess_mem_test.go
diff --git a/server/web/session/sess_test.go b/session/sess_test.go
similarity index 100%
rename from server/web/session/sess_test.go
rename to session/sess_test.go
diff --git a/server/web/session/sess_utils.go b/session/sess_utils.go
similarity index 99%
rename from server/web/session/sess_utils.go
rename to session/sess_utils.go
index 8a031dd5..20915bb6 100644
--- a/server/web/session/sess_utils.go
+++ b/session/sess_utils.go
@@ -29,7 +29,7 @@ import (
"strconv"
"time"
- "github.com/astaxie/beego/core/utils"
+ "github.com/astaxie/beego/utils"
)
func init() {
diff --git a/server/web/session/session.go b/session/session.go
similarity index 86%
rename from server/web/session/session.go
rename to session/session.go
index bb7e5bd6..eb85360a 100644
--- a/server/web/session/session.go
+++ b/session/session.go
@@ -28,7 +28,6 @@
package session
import (
- "context"
"crypto/rand"
"encoding/hex"
"errors"
@@ -44,24 +43,24 @@ import (
// Store contains all data for one session process with specific id.
type Store interface {
- Set(ctx context.Context, key, value interface{}) error //set session value
- Get(ctx context.Context, key interface{}) interface{} //get session value
- Delete(ctx context.Context, key interface{}) error //delete session value
- SessionID(ctx context.Context) string //back current sessionID
- SessionRelease(ctx context.Context, w http.ResponseWriter) // release the resource & save data to provider & return the data
- Flush(ctx context.Context) error //delete all data
+ Set(key, value interface{}) error //set session value
+ Get(key interface{}) interface{} //get session value
+ Delete(key interface{}) error //delete session value
+ SessionID() string //back current sessionID
+ SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data
+ Flush() error //delete all data
}
// Provider contains global session methods and saved SessionStores.
// it can operate a SessionStore by its id.
type Provider interface {
- SessionInit(ctx context.Context, gclifetime int64, config string) error
- SessionRead(ctx context.Context, sid string) (Store, error)
- SessionExist(ctx context.Context, sid string) (bool, error)
- SessionRegenerate(ctx context.Context, oldsid, sid string) (Store, error)
- SessionDestroy(ctx context.Context, sid string) error
- SessionAll(ctx context.Context) int //get all active session
- SessionGC(ctx context.Context)
+ SessionInit(gclifetime int64, config string) error
+ SessionRead(sid string) (Store, error)
+ SessionExist(sid string) bool
+ SessionRegenerate(oldsid, sid string) (Store, error)
+ SessionDestroy(sid string) error
+ SessionAll() int //get all active session
+ SessionGC()
}
var provides = make(map[string]Provider)
@@ -149,7 +148,7 @@ func NewManager(provideName string, cf *ManagerConfig) (*Manager, error) {
}
}
- err := provider.SessionInit(nil, cf.Maxlifetime, cf.ProviderConfig)
+ err := provider.SessionInit(cf.Maxlifetime, cf.ProviderConfig)
if err != nil {
return nil, err
}
@@ -212,14 +211,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
return nil, errs
}
- if sid != "" {
- exists, err := manager.provider.SessionExist(nil, sid)
- if err != nil {
- return nil, err
- }
- if exists {
- return manager.provider.SessionRead(nil, sid)
- }
+ if sid != "" && manager.provider.SessionExist(sid) {
+ return manager.provider.SessionRead(sid)
}
// Generate a new session
@@ -228,7 +221,7 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
return nil, errs
}
- session, err = manager.provider.SessionRead(nil, sid)
+ session, err = manager.provider.SessionRead(sid)
if err != nil {
return nil, err
}
@@ -270,7 +263,7 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
}
sid, _ := url.QueryUnescape(cookie.Value)
- manager.provider.SessionDestroy(nil, sid)
+ manager.provider.SessionDestroy(sid)
if manager.config.EnableSetCookie {
expiration := time.Now()
cookie = &http.Cookie{Name: manager.config.CookieName,
@@ -286,14 +279,14 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
// GetSessionStore Get SessionStore by its id.
func (manager *Manager) GetSessionStore(sid string) (sessions Store, err error) {
- sessions, err = manager.provider.SessionRead(nil, sid)
+ sessions, err = manager.provider.SessionRead(sid)
return
}
// GC Start session gc process.
// it can do gc in times after gc lifetime.
func (manager *Manager) GC() {
- manager.provider.SessionGC(nil)
+ manager.provider.SessionGC()
time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() })
}
@@ -306,7 +299,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
cookie, err := r.Cookie(manager.config.CookieName)
if err != nil || cookie.Value == "" {
//delete old cookie
- session, _ = manager.provider.SessionRead(nil, sid)
+ session, _ = manager.provider.SessionRead(sid)
cookie = &http.Cookie{Name: manager.config.CookieName,
Value: url.QueryEscape(sid),
Path: "/",
@@ -316,7 +309,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
}
} else {
oldsid, _ := url.QueryUnescape(cookie.Value)
- session, _ = manager.provider.SessionRegenerate(nil, oldsid, sid)
+ session, _ = manager.provider.SessionRegenerate(oldsid, sid)
cookie.Value = url.QueryEscape(sid)
cookie.HttpOnly = true
cookie.Path = "/"
@@ -340,7 +333,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
// GetActiveSession Get all active sessions count number.
func (manager *Manager) GetActiveSession() int {
- return manager.provider.SessionAll(nil)
+ return manager.provider.SessionAll()
}
// SetSecure Set cookie with https.
diff --git a/server/web/session/ssdb/sess_ssdb.go b/session/ssdb/sess_ssdb.go
similarity index 66%
rename from server/web/session/ssdb/sess_ssdb.go
rename to session/ssdb/sess_ssdb.go
index 0adc41bd..de0c6360 100644
--- a/server/web/session/ssdb/sess_ssdb.go
+++ b/session/ssdb/sess_ssdb.go
@@ -1,17 +1,14 @@
package ssdb
import (
- "context"
- "encoding/json"
"errors"
"net/http"
"strconv"
"strings"
"sync"
+ "github.com/astaxie/beego/session"
"github.com/ssdb/gossdb/ssdb"
-
- "github.com/astaxie/beego/server/web/session"
)
var ssdbProvider = &Provider{}
@@ -19,50 +16,35 @@ var ssdbProvider = &Provider{}
// Provider holds ssdb client and configs
type Provider struct {
client *ssdb.Client
- Host string `json:"host"`
- Port int `json:"port"`
+ host string
+ port int
maxLifetime int64
}
func (p *Provider) connectInit() error {
var err error
- if p.Host == "" || p.Port == 0 {
+ if p.host == "" || p.port == 0 {
return errors.New("SessionInit First")
}
- p.client, err = ssdb.Connect(p.Host, p.Port)
+ p.client, err = ssdb.Connect(p.host, p.port)
return err
}
// SessionInit init the ssdb with the config
-func (p *Provider) SessionInit(ctx context.Context, maxLifetime int64, cfg string) error {
+func (p *Provider) SessionInit(maxLifetime int64, savePath string) error {
p.maxLifetime = maxLifetime
+ address := strings.Split(savePath, ":")
+ p.host = address[0]
- cfg = strings.TrimSpace(cfg)
var err error
- // we think this is v2.0, using json to init the session
- if strings.HasPrefix(cfg, "{") {
- err = json.Unmarshal([]byte(cfg), p)
- } else {
- err = p.initOldStyle(cfg)
- }
- if err != nil {
+ if p.port, err = strconv.Atoi(address[1]); err != nil {
return err
}
return p.connectInit()
}
-// for v1.x
-func (p *Provider) initOldStyle(savePath string) error {
- address := strings.Split(savePath, ":")
- p.Host = address[0]
-
- var err error
- p.Port, err = strconv.Atoi(address[1])
- return err
-}
-
// SessionRead return a ssdb client session Store
-func (p *Provider) SessionRead(ctx context.Context, sid string) (session.Store, error) {
+func (p *Provider) SessionRead(sid string) (session.Store, error) {
if p.client == nil {
if err := p.connectInit(); err != nil {
return nil, err
@@ -86,10 +68,10 @@ func (p *Provider) SessionRead(ctx context.Context, sid string) (session.Store,
}
// SessionExist judged whether sid is exist in session
-func (p *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
+func (p *Provider) SessionExist(sid string) bool {
if p.client == nil {
if err := p.connectInit(); err != nil {
- return false, err
+ panic(err)
}
}
value, err := p.client.Get(sid)
@@ -97,14 +79,14 @@ func (p *Provider) SessionExist(ctx context.Context, sid string) (bool, error) {
panic(err)
}
if value == nil || len(value.(string)) == 0 {
- return false, nil
+ return false
}
- return true, nil
+ return true
}
// SessionRegenerate regenerate session with new sid and delete oldsid
-func (p *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (session.Store, error) {
- // conn.Do("setx", key, v, ttl)
+func (p *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
+ //conn.Do("setx", key, v, ttl)
if p.client == nil {
if err := p.connectInit(); err != nil {
return nil, err
@@ -136,7 +118,7 @@ func (p *Provider) SessionRegenerate(ctx context.Context, oldsid, sid string) (s
}
// SessionDestroy destroy the sid
-func (p *Provider) SessionDestroy(ctx context.Context, sid string) error {
+func (p *Provider) SessionDestroy(sid string) error {
if p.client == nil {
if err := p.connectInit(); err != nil {
return err
@@ -147,11 +129,11 @@ func (p *Provider) SessionDestroy(ctx context.Context, sid string) error {
}
// SessionGC not implemented
-func (p *Provider) SessionGC(context.Context) {
+func (p *Provider) SessionGC() {
}
// SessionAll not implemented
-func (p *Provider) SessionAll(context.Context) int {
+func (p *Provider) SessionAll() int {
return 0
}
@@ -165,7 +147,7 @@ type SessionStore struct {
}
// Set the key and value
-func (s *SessionStore) Set(ctx context.Context, key, value interface{}) error {
+func (s *SessionStore) Set(key, value interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
s.values[key] = value
@@ -173,7 +155,7 @@ func (s *SessionStore) Set(ctx context.Context, key, value interface{}) error {
}
// Get return the value by the key
-func (s *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
+func (s *SessionStore) Get(key interface{}) interface{} {
s.lock.Lock()
defer s.lock.Unlock()
if value, ok := s.values[key]; ok {
@@ -183,7 +165,7 @@ func (s *SessionStore) Get(ctx context.Context, key interface{}) interface{} {
}
// Delete the key in session store
-func (s *SessionStore) Delete(ctx context.Context, key interface{}) error {
+func (s *SessionStore) Delete(key interface{}) error {
s.lock.Lock()
defer s.lock.Unlock()
delete(s.values, key)
@@ -191,7 +173,7 @@ func (s *SessionStore) Delete(ctx context.Context, key interface{}) error {
}
// Flush delete all keys and values
-func (s *SessionStore) Flush(context.Context) error {
+func (s *SessionStore) Flush() error {
s.lock.Lock()
defer s.lock.Unlock()
s.values = make(map[interface{}]interface{})
@@ -199,12 +181,12 @@ func (s *SessionStore) Flush(context.Context) error {
}
// SessionID return the sessionID
-func (s *SessionStore) SessionID(context.Context) string {
+func (s *SessionStore) SessionID() string {
return s.sid
}
// SessionRelease Store the keyvalues into ssdb
-func (s *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
+func (s *SessionStore) SessionRelease(w http.ResponseWriter) {
b, err := session.EncodeGob(s.values)
if err != nil {
return
diff --git a/server/web/staticfile.go b/staticfile.go
similarity index 96%
rename from server/web/staticfile.go
rename to staticfile.go
index aa3f35d8..84e9aa7b 100644
--- a/server/web/staticfile.go
+++ b/staticfile.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"bytes"
@@ -26,10 +26,9 @@ import (
"sync"
"time"
- "github.com/astaxie/beego/core/logs"
- lru "github.com/hashicorp/golang-lru"
-
- "github.com/astaxie/beego/server/web/context"
+ "github.com/astaxie/beego/context"
+ "github.com/astaxie/beego/logs"
+ "github.com/hashicorp/golang-lru"
)
var errNotStaticRequest = errors.New("request not a static file request")
@@ -203,7 +202,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) {
if !strings.Contains(requestPath, prefix) {
continue
}
- if prefix != "/" && len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
+ if prefix != "/" && len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
continue
}
filePath := path.Join(staticDir, requestPath[len(prefix):])
diff --git a/server/web/staticfile_test.go b/staticfile_test.go
similarity index 99%
rename from server/web/staticfile_test.go
rename to staticfile_test.go
index 0725a2f8..e46c13ec 100644
--- a/server/web/staticfile_test.go
+++ b/staticfile_test.go
@@ -1,4 +1,4 @@
-package web
+package beego
import (
"bytes"
diff --git a/server/web/swagger/swagger.go b/swagger/swagger.go
similarity index 100%
rename from server/web/swagger/swagger.go
rename to swagger/swagger.go
diff --git a/task/govenor_command.go b/task/govenor_command.go
deleted file mode 100644
index 15e25e43..00000000
--- a/task/govenor_command.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package task
-
-import (
- "context"
- "fmt"
- "html/template"
-
- "github.com/pkg/errors"
-
- "github.com/astaxie/beego/core/governor"
-)
-
-type listTaskCommand struct {
-}
-
-func (l *listTaskCommand) Execute(params ...interface{}) *governor.Result {
- resultList := make([][]string, 0, len(globalTaskManager.adminTaskList))
- for tname, tk := range globalTaskManager.adminTaskList {
- result := []string{
- template.HTMLEscapeString(tname),
- template.HTMLEscapeString(tk.GetSpec(nil)),
- template.HTMLEscapeString(tk.GetStatus(nil)),
- template.HTMLEscapeString(tk.GetPrev(context.Background()).String()),
- }
- resultList = append(resultList, result)
- }
-
- return &governor.Result{
- Status: 200,
- Content: resultList,
- }
-}
-
-type runTaskCommand struct {
-}
-
-func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
- if len(params) == 0 {
- return &governor.Result{
- Status: 400,
- Error: errors.New("task name not passed"),
- }
- }
-
- tn, ok := params[0].(string)
-
- if !ok {
- return &governor.Result{
- Status: 400,
- Error: errors.New("parameter is invalid"),
- }
- }
-
- if t, ok := globalTaskManager.adminTaskList[tn]; ok {
- err := t.Run(context.Background())
- if err != nil {
- return &governor.Result{
- Status: 500,
- Error: err,
- }
- }
- return &governor.Result{
- Status: 200,
- Content: t.GetStatus(context.Background()),
- }
- } else {
- return &governor.Result{
- Status: 400,
- Error: errors.New(fmt.Sprintf("task with name %s not found", tn)),
- }
- }
-
-}
-
-func registerCommands() {
- governor.RegisterCommand("task", "list", &listTaskCommand{})
- governor.RegisterCommand("task", "run", &runTaskCommand{})
-}
diff --git a/task/governor_command_test.go b/task/governor_command_test.go
deleted file mode 100644
index 00ed37f2..00000000
--- a/task/governor_command_test.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2020
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package task
-
-import (
- "context"
- "errors"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-type countTask struct {
- cnt int
- mockErr error
-}
-
-func (c *countTask) GetSpec(ctx context.Context) string {
- return "AAA"
-}
-
-func (c *countTask) GetStatus(ctx context.Context) string {
- return "SUCCESS"
-}
-
-func (c *countTask) Run(ctx context.Context) error {
- c.cnt++
- return c.mockErr
-}
-
-func (c *countTask) SetNext(ctx context.Context, time time.Time) {
-}
-
-func (c *countTask) GetNext(ctx context.Context) time.Time {
- return time.Now()
-}
-
-func (c *countTask) SetPrev(ctx context.Context, time time.Time) {
-}
-
-func (c *countTask) GetPrev(ctx context.Context) time.Time {
- return time.Now()
-}
-
-func TestRunTaskCommand_Execute(t *testing.T) {
- task := &countTask{}
- AddTask("count", task)
-
- cmd := &runTaskCommand{}
-
- res := cmd.Execute()
- assert.NotNil(t, res)
- assert.NotNil(t, res.Error)
- assert.Equal(t, "task name not passed", res.Error.Error())
-
- res = cmd.Execute(10)
- assert.NotNil(t, res)
- assert.NotNil(t, res.Error)
- assert.Equal(t, "parameter is invalid", res.Error.Error())
-
- res = cmd.Execute("CCCC")
- assert.NotNil(t, res)
- assert.NotNil(t, res.Error)
- assert.Equal(t, "task with name CCCC not found", res.Error.Error())
-
- res = cmd.Execute("count")
- assert.NotNil(t, res)
- assert.True(t, res.IsSuccess())
-
- task.mockErr = errors.New("mock error")
- res = cmd.Execute("count")
- assert.NotNil(t, res)
- assert.NotNil(t, res.Error)
- assert.Equal(t, "mock error", res.Error.Error())
-}
-
-func TestListTaskCommand_Execute(t *testing.T) {
- task := &countTask{}
-
- cmd := &listTaskCommand{}
-
- res := cmd.Execute()
-
- assert.True(t, res.IsSuccess())
-
- _, ok := res.Content.([][]string)
- assert.True(t, ok)
-
- AddTask("count", task)
-
- res = cmd.Execute()
-
- assert.True(t, res.IsSuccess())
-
- rl, ok := res.Content.([][]string)
- assert.True(t, ok)
- assert.Equal(t, 1, len(rl))
-}
diff --git a/task/task_test.go b/task/task_test.go
deleted file mode 100644
index 2cb807ce..00000000
--- a/task/task_test.go
+++ /dev/null
@@ -1,117 +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 task
-
-import (
- "context"
- "errors"
- "fmt"
- "sync"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestParse(t *testing.T) {
- m := newTaskManager()
- defer m.ClearTask()
- tk := NewTask("taska", "0/30 * * * * *", func(ctx context.Context) error {
- fmt.Println("hello world")
- return nil
- })
- err := tk.Run(nil)
- if err != nil {
- t.Fatal(err)
- }
- m.AddTask("taska", tk)
- m.StartTask()
- time.Sleep(3 * time.Second)
- m.StopTask()
-}
-
-func TestModifyTaskListAfterRunning(t *testing.T) {
- m := newTaskManager()
- defer m.ClearTask()
- tk := NewTask("taskb", "0/30 * * * * *", func(ctx context.Context) error {
- fmt.Println("hello world")
- return nil
- })
- err := tk.Run(nil)
- if err != nil {
- t.Fatal(err)
- }
- m.AddTask("taskb", tk)
- m.StartTask()
- go func() {
- m.DeleteTask("taskb")
- }()
- go func() {
- m.AddTask("taskb1", tk)
- }()
-
- time.Sleep(3 * time.Second)
- m.StopTask()
-}
-
-func TestSpec(t *testing.T) {
- m := newTaskManager()
- defer m.ClearTask()
- wg := &sync.WaitGroup{}
- wg.Add(2)
- tk1 := NewTask("tk1", "0 12 * * * *", func(ctx context.Context) error { fmt.Println("tk1"); return nil })
- tk2 := NewTask("tk2", "0,10,20 * * * * *", func(ctx context.Context) error { fmt.Println("tk2"); wg.Done(); return nil })
- tk3 := NewTask("tk3", "0 10 * * * *", func(ctx context.Context) error { fmt.Println("tk3"); wg.Done(); return nil })
-
- m.AddTask("tk1", tk1)
- m.AddTask("tk2", tk2)
- m.AddTask("tk3", tk3)
- m.StartTask()
- defer m.StopTask()
-
- select {
- case <-time.After(200 * time.Second):
- t.FailNow()
- case <-wait(wg):
- }
-}
-
-func TestTask_Run(t *testing.T) {
- cnt := -1
- task := func(ctx context.Context) error {
- cnt++
- fmt.Printf("Hello, world! %d \n", cnt)
- return errors.New(fmt.Sprintf("Hello, world! %d", cnt))
- }
- tk := NewTask("taska", "0/30 * * * * *", task)
- for i := 0; i < 200; i++ {
- e := tk.Run(nil)
- assert.NotNil(t, e)
- }
-
- l := tk.Errlist
- assert.Equal(t, 100, len(l))
- assert.Equal(t, "Hello, world! 100", l[0].errinfo)
- assert.Equal(t, "Hello, world! 101", l[1].errinfo)
-}
-
-func wait(wg *sync.WaitGroup) chan bool {
- ch := make(chan bool)
- go func() {
- wg.Wait()
- ch <- true
- }()
- return ch
-}
diff --git a/server/web/template.go b/template.go
similarity index 97%
rename from server/web/template.go
rename to template.go
index d582dcda..59875be7 100644
--- a/server/web/template.go
+++ b/template.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"errors"
@@ -27,8 +27,8 @@ import (
"strings"
"sync"
- "github.com/astaxie/beego/core/logs"
- "github.com/astaxie/beego/core/utils"
+ "github.com/astaxie/beego/logs"
+ "github.com/astaxie/beego/utils"
)
var (
@@ -368,14 +368,14 @@ func SetTemplateFSFunc(fnt templateFSFunc) {
}
// SetViewsPath sets view directory path in beego application.
-func SetViewsPath(path string) *HttpServer {
+func SetViewsPath(path string) *App {
BConfig.WebConfig.ViewsPath = path
return BeeApp
}
// SetStaticPath sets static directory path and proper url pattern in beego application.
// if beego.SetStaticPath("static","public"), visit /static/* to load static file in folder "public".
-func SetStaticPath(url string, path string) *HttpServer {
+func SetStaticPath(url string, path string) *App {
if !strings.HasPrefix(url, "/") {
url = "/" + url
}
@@ -387,7 +387,7 @@ func SetStaticPath(url string, path string) *HttpServer {
}
// DelStaticPath removes the static folder setting in this url pattern in beego application.
-func DelStaticPath(url string) *HttpServer {
+func DelStaticPath(url string) *App {
if !strings.HasPrefix(url, "/") {
url = "/" + url
}
@@ -399,7 +399,7 @@ func DelStaticPath(url string) *HttpServer {
}
// AddTemplateEngine add a new templatePreProcessor which support extension
-func AddTemplateEngine(extension string, fn templatePreProcessor) *HttpServer {
+func AddTemplateEngine(extension string, fn templatePreProcessor) *App {
AddTemplateExt(extension)
beeTemplateEngines[extension] = fn
return BeeApp
diff --git a/server/web/template_test.go b/template_test.go
similarity index 88%
rename from server/web/template_test.go
rename to template_test.go
index b542494d..287faadc 100644
--- a/server/web/template_test.go
+++ b/template_test.go
@@ -12,19 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"bytes"
+ "github.com/astaxie/beego/testdata"
+ "github.com/elazarl/go-bindata-assetfs"
"net/http"
"os"
"path/filepath"
"testing"
-
- assetfs "github.com/elazarl/go-bindata-assetfs"
- "github.com/stretchr/testify/assert"
-
- "github.com/astaxie/beego/test"
)
var header = `{{define "header"}}
@@ -49,9 +46,7 @@ var block = `{{define "block"}}
{{end}}`
func TestTemplate(t *testing.T) {
- wkdir, err := os.Getwd()
- assert.Nil(t, err)
- dir := filepath.Join(wkdir, "_beeTmp", "TestTemplate")
+ dir := "_beeTmp"
files := []string{
"header.tpl",
"index.tpl",
@@ -61,8 +56,7 @@ func TestTemplate(t *testing.T) {
t.Fatal(err)
}
for k, name := range files {
- dirErr := os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
- assert.Nil(t, dirErr)
+ os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
if f, err := os.Create(filepath.Join(dir, name)); err != nil {
t.Fatal(err)
} else {
@@ -113,9 +107,7 @@ var user = `
`
func TestRelativeTemplate(t *testing.T) {
- wkdir, err := os.Getwd()
- assert.Nil(t, err)
- dir := filepath.Join(wkdir, "_beeTmp")
+ dir := "_beeTmp"
//Just add dir to known viewPaths
if err := AddViewPath(dir); err != nil {
@@ -226,10 +218,7 @@ var output = `
`
func TestTemplateLayout(t *testing.T) {
- wkdir, err := os.Getwd()
- assert.Nil(t, err)
-
- dir := filepath.Join(wkdir, "_beeTmp", "TestTemplateLayout")
+ dir := "_beeTmp"
files := []string{
"add.tpl",
"layout_blog.tpl",
@@ -237,22 +226,17 @@ func TestTemplateLayout(t *testing.T) {
if err := os.MkdirAll(dir, 0777); err != nil {
t.Fatal(err)
}
-
for k, name := range files {
- dirErr := os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
- assert.Nil(t, dirErr)
+ os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
if f, err := os.Create(filepath.Join(dir, name)); err != nil {
t.Fatal(err)
} else {
if k == 0 {
- _, writeErr := f.WriteString(add)
- assert.Nil(t, writeErr)
+ f.WriteString(add)
} else if k == 1 {
- _, writeErr := f.WriteString(layoutBlog)
- assert.Nil(t, writeErr)
+ f.WriteString(layoutBlog)
}
- clErr := f.Close()
- assert.Nil(t, clErr)
+ f.Close()
}
}
if err := AddViewPath(dir); err != nil {
@@ -263,7 +247,6 @@ func TestTemplateLayout(t *testing.T) {
t.Fatalf("should be 2 but got %v", len(beeTemplates))
}
out := bytes.NewBufferString("")
-
if err := beeTemplates["add.tpl"].ExecuteTemplate(out, "add.tpl", map[string]string{"Title": "Hello", "SomeVar": "val"}); err != nil {
t.Fatal(err)
}
@@ -308,7 +291,7 @@ var outputBinData = `
func TestFsBinData(t *testing.T) {
SetTemplateFSFunc(func() http.FileSystem {
- return TestingFileSystem{&assetfs.AssetFS{Asset: test.Asset, AssetDir: test.AssetDir, AssetInfo: test.AssetInfo}}
+ return TestingFileSystem{&assetfs.AssetFS{Asset: testdata.Asset, AssetDir: testdata.AssetDir, AssetInfo: testdata.AssetInfo}}
})
dir := "views"
if err := AddViewPath("views"); err != nil {
diff --git a/server/web/templatefunc.go b/templatefunc.go
similarity index 98%
rename from server/web/templatefunc.go
rename to templatefunc.go
index 53c99018..ba1ec5eb 100644
--- a/server/web/templatefunc.go
+++ b/templatefunc.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package web
+package beego
import (
"errors"
@@ -58,11 +58,11 @@ func HTML2str(html string) string {
re := regexp.MustCompile(`\<[\S\s]+?\>`)
html = re.ReplaceAllStringFunc(html, strings.ToLower)
- // remove STYLE
+ //remove STYLE
re = regexp.MustCompile(`\
+
+
+
+