mirror of
https://github.com/astaxie/beego.git
synced 2024-11-23 20:10:56 +00:00
Merge branch 'develop' of https://github.com/astaxie/beego into develop-bk
This commit is contained in:
commit
53688ce32f
19
README.md
19
README.md
@ -6,6 +6,21 @@ It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific feature
|
|||||||
|
|
||||||
###### More info at [beego.me](http://beego.me).
|
###### More info at [beego.me](http://beego.me).
|
||||||
|
|
||||||
|
> If you could not open this website, go to [beedoc](https://github.com/beego/beedoc)
|
||||||
|
|
||||||
|
## beego 1.x and 2.x
|
||||||
|
|
||||||
|
We recently release beego 2.0.0-beta, and its structure change a lot, so you may get some error
|
||||||
|
|
||||||
|
1. If you are working on beego v1.x please try `go get github.com/astaxie/beego@v1.12.3`
|
||||||
|
2. If you want to try beego 2.0.0, run `go get github.com/astaxie/beego@develop`
|
||||||
|
|
||||||
|
We are still working on fix bug and documentation of v2.x. And v2.x's doc will be released with v2.0.0.
|
||||||
|
|
||||||
|
## Next version
|
||||||
|
|
||||||
|
v1.12.4 will be released on Jan 2021 And v2.0.0 will be released next month.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
###### Please see [Documentation](http://beego.me/docs) for more.
|
###### Please see [Documentation](http://beego.me/docs) for more.
|
||||||
@ -25,7 +40,9 @@ It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific feature
|
|||||||
|
|
||||||
#### Download and install
|
#### Download and install
|
||||||
|
|
||||||
go get github.com/astaxie/beego
|
go get -u github.com/astaxie/beego@develop
|
||||||
|
|
||||||
|
Now we are working on beego v2.0.0, so using `@develop`.
|
||||||
|
|
||||||
#### Create file `hello.go`
|
#### Create file `hello.go`
|
||||||
```go
|
```go
|
||||||
|
@ -212,7 +212,8 @@ func (c *Controller) ServeFormatted(encoding ...bool) {
|
|||||||
|
|
||||||
// Input returns the input data map from POST or PUT request body and query string.
|
// Input returns the input data map from POST or PUT request body and query string.
|
||||||
func (c *Controller) Input() url.Values {
|
func (c *Controller) Input() url.Values {
|
||||||
return (*web.Controller)(c).Input()
|
val, _ := (*web.Controller)(c).Input()
|
||||||
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseForm maps input data map to obj struct.
|
// ParseForm maps input data map to obj struct.
|
||||||
|
@ -141,7 +141,7 @@ func (manager *Manager) GC() {
|
|||||||
|
|
||||||
// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request.
|
// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request.
|
||||||
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) Store {
|
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) Store {
|
||||||
s := (*session.Manager)(manager).SessionRegenerateID(w, r)
|
s, _ := (*session.Manager)(manager).SessionRegenerateID(w, r)
|
||||||
return &NewToOldStoreAdapter{
|
return &NewToOldStoreAdapter{
|
||||||
delegate: s,
|
delegate: s,
|
||||||
}
|
}
|
||||||
|
@ -1,249 +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 adapter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/adapter/context"
|
|
||||||
beecontext "github.com/astaxie/beego/server/web/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
type testinfo struct {
|
|
||||||
url string
|
|
||||||
requesturl string
|
|
||||||
params map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
var routers []testinfo
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routers = make([]testinfo, 0)
|
|
||||||
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic", nil})
|
|
||||||
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}})
|
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/:id", "/123", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/hello/?:id", "/hello", map[string]string{":id": ""}})
|
|
||||||
routers = append(routers, testinfo{"/", "/", nil})
|
|
||||||
routers = append(routers, testinfo{"/customer/login", "/customer/login", nil})
|
|
||||||
routers = append(routers, testinfo{"/customer/login", "/customer/login.json", map[string]string{":ext": "json"}})
|
|
||||||
routers = append(routers, testinfo{"/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}})
|
|
||||||
routers = append(routers, testinfo{"/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}})
|
|
||||||
routers = append(routers, testinfo{"/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}})
|
|
||||||
routers = append(routers, testinfo{"/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}})
|
|
||||||
routers = append(routers, testinfo{"/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}})
|
|
||||||
routers = append(routers, testinfo{"/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}})
|
|
||||||
routers = append(routers, testinfo{"/thumbnail/:size/uploads/*",
|
|
||||||
"/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg",
|
|
||||||
map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}})
|
|
||||||
routers = append(routers, testinfo{"/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}})
|
|
||||||
routers = append(routers, testinfo{"/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
|
|
||||||
routers = append(routers, testinfo{"/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
|
|
||||||
routers = append(routers, testinfo{"/dl/:width:int/:height:int/*.*",
|
|
||||||
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg",
|
|
||||||
map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeRouters(t *testing.T) {
|
|
||||||
for _, r := range routers {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter(r.url, "astaxie")
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := tr.Match(r.requesturl, ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal(r.url+" can't get obj, Expect ", r.requesturl)
|
|
||||||
}
|
|
||||||
if r.params != nil {
|
|
||||||
for k, v := range r.params {
|
|
||||||
if vv := ctx.Input.Param(k); vv != v {
|
|
||||||
t.Fatal("The Rule: " + r.url + "\nThe RequestURL:" + r.requesturl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
|
|
||||||
} else if vv == "" && v != "" {
|
|
||||||
t.Fatal(r.url + " " + r.requesturl + " get param empty:" + k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStaticPath(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/topic/:id", "wildcard")
|
|
||||||
tr.AddRouter("/topic", "static")
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := tr.Match("/topic", ctx)
|
|
||||||
if obj == nil || obj.(string) != "static" {
|
|
||||||
t.Fatal("/topic is a static route")
|
|
||||||
}
|
|
||||||
obj = tr.Match("/topic/1", ctx)
|
|
||||||
if obj == nil || obj.(string) != "wildcard" {
|
|
||||||
t.Fatal("/topic/1 is a wildcard route")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddTree(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/shop/:id/account", "astaxie")
|
|
||||||
tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie")
|
|
||||||
t1 := NewTree()
|
|
||||||
t1.AddTree("/v1/zl", tr)
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := t1.Match("/v1/zl/shop/123/account", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/v1/zl/shop/:id/account can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":id") != "123" {
|
|
||||||
t.Fatal("get :id param error")
|
|
||||||
}
|
|
||||||
ctx.Input.Reset((*beecontext.Context)(ctx))
|
|
||||||
obj = t1.Match("/v1/zl/shop/123/ttt_1_12.html", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/v1/zl//shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" {
|
|
||||||
t.Fatal("get :sd :id :page param error")
|
|
||||||
}
|
|
||||||
|
|
||||||
t2 := NewTree()
|
|
||||||
t2.AddTree("/v1/:shopid", tr)
|
|
||||||
ctx.Input.Reset((*beecontext.Context)(ctx))
|
|
||||||
obj = t2.Match("/v1/zl/shop/123/account", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/v1/:shopid/shop/:id/account can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":shopid") != "zl" {
|
|
||||||
t.Fatal("get :id :shopid param error")
|
|
||||||
}
|
|
||||||
ctx.Input.Reset((*beecontext.Context)(ctx))
|
|
||||||
obj = t2.Match("/v1/zl/shop/123/ttt_1_12.html", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/v1/:shopid/shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get :shopid param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" || ctx.Input.Param(":shopid") != "zl" {
|
|
||||||
t.Fatal("get :sd :id :page :shopid param error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddTree2(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/shop/:id/account", "astaxie")
|
|
||||||
tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie")
|
|
||||||
t3 := NewTree()
|
|
||||||
t3.AddTree("/:version(v1|v2)/:prefix", tr)
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := t3.Match("/v1/zl/shop/123/account", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/:version(v1|v2)/:prefix/shop/:id/account can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":prefix") != "zl" || ctx.Input.Param(":version") != "v1" {
|
|
||||||
t.Fatal("get :id :prefix :version param error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddTree3(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/create", "astaxie")
|
|
||||||
tr.AddRouter("/shop/:sd/account", "astaxie")
|
|
||||||
t3 := NewTree()
|
|
||||||
t3.AddTree("/table/:num", tr)
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := t3.Match("/table/123/shop/123/account", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/table/:num/shop/:sd/account can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":num") != "123" || ctx.Input.Param(":sd") != "123" {
|
|
||||||
t.Fatal("get :num :sd param error")
|
|
||||||
}
|
|
||||||
ctx.Input.Reset((*beecontext.Context)(ctx))
|
|
||||||
obj = t3.Match("/table/123/create", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/table/:num/create can't get obj ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddTree4(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/create", "astaxie")
|
|
||||||
tr.AddRouter("/shop/:sd/:account", "astaxie")
|
|
||||||
t4 := NewTree()
|
|
||||||
t4.AddTree("/:info:int/:num/:id", tr)
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := t4.Match("/12/123/456/shop/123/account", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/:info:int/:num/:id/shop/:sd/:account can't get obj ")
|
|
||||||
}
|
|
||||||
if ctx.Input.ParamsLen() == 0 {
|
|
||||||
t.Fatal("get param error")
|
|
||||||
}
|
|
||||||
if ctx.Input.Param(":info") != "12" || ctx.Input.Param(":num") != "123" ||
|
|
||||||
ctx.Input.Param(":id") != "456" || ctx.Input.Param(":sd") != "123" ||
|
|
||||||
ctx.Input.Param(":account") != "account" {
|
|
||||||
t.Fatal("get :info :num :id :sd :account param error")
|
|
||||||
}
|
|
||||||
ctx.Input.Reset((*beecontext.Context)(ctx))
|
|
||||||
obj = t4.Match("/12/123/456/create", ctx)
|
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
|
||||||
t.Fatal("/:info:int/:num/:id/create can't get obj ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test for issue #1595
|
|
||||||
func TestAddTree5(t *testing.T) {
|
|
||||||
tr := NewTree()
|
|
||||||
tr.AddRouter("/v1/shop/:id", "shopdetail")
|
|
||||||
tr.AddRouter("/v1/shop/", "shophome")
|
|
||||||
ctx := context.NewContext()
|
|
||||||
obj := tr.Match("/v1/shop/", ctx)
|
|
||||||
if obj == nil || obj.(string) != "shophome" {
|
|
||||||
t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
|
|
||||||
}
|
|
||||||
}
|
|
98
client/cache/cache_test.go
vendored
98
client/cache/cache_test.go
vendored
@ -72,21 +72,9 @@ func TestCache(t *testing.T) {
|
|||||||
t.Error("set Error", err)
|
t.Error("set Error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = bm.Incr(context.Background(), "astaxie"); err != nil {
|
// test different integer type for incr & decr
|
||||||
t.Error("Incr Error", err)
|
testMultiIncrDecr(t, bm, timeoutDuration)
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 2 {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Decr(context.Background(), "astaxie"); err != nil {
|
|
||||||
t.Error("Decr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
bm.Delete(context.Background(), "astaxie")
|
bm.Delete(context.Background(), "astaxie")
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
||||||
t.Error("delete err")
|
t.Error("delete err")
|
||||||
@ -120,6 +108,20 @@ func TestCache(t *testing.T) {
|
|||||||
if vv[1].(string) != "author1" {
|
if vv[1].(string) != "author1" {
|
||||||
t.Error("GetMulti ERROR")
|
t.Error("GetMulti ERROR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
|
if len(vv) != 2 {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if vv[0] != nil {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if vv[1].(string) != "author1" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if err != nil && err.Error() != "key [astaxie0] error: the key isn't exist" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileCache(t *testing.T) {
|
func TestFileCache(t *testing.T) {
|
||||||
@ -139,21 +141,9 @@ func TestFileCache(t *testing.T) {
|
|||||||
t.Error("get err")
|
t.Error("get err")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = bm.Incr(context.Background(), "astaxie"); err != nil {
|
// test different integer type for incr & decr
|
||||||
t.Error("Incr Error", err)
|
testMultiIncrDecr(t, bm, timeoutDuration)
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 2 {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = bm.Decr(context.Background(), "astaxie"); err != nil {
|
|
||||||
t.Error("Decr Error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 {
|
|
||||||
t.Error("get err")
|
|
||||||
}
|
|
||||||
bm.Delete(context.Background(), "astaxie")
|
bm.Delete(context.Background(), "astaxie")
|
||||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
||||||
t.Error("delete err")
|
t.Error("delete err")
|
||||||
@ -189,5 +179,57 @@ func TestFileCache(t *testing.T) {
|
|||||||
t.Error("GetMulti ERROR")
|
t.Error("GetMulti ERROR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
|
if len(vv) != 2 {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if vv[0] != nil {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if vv[1].(string) != "author1" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
os.RemoveAll("cache")
|
os.RemoveAll("cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testMultiIncrDecr(t *testing.T, c Cache, timeout time.Duration) {
|
||||||
|
testIncrDecr(t, c, 1, 2, timeout)
|
||||||
|
testIncrDecr(t, c, int32(1), int32(2), timeout)
|
||||||
|
testIncrDecr(t, c, int64(1), int64(2), timeout)
|
||||||
|
testIncrDecr(t, c, uint(1), uint(2), timeout)
|
||||||
|
testIncrDecr(t, c, uint32(1), uint32(2), timeout)
|
||||||
|
testIncrDecr(t, c, uint64(1), uint64(2), timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testIncrDecr(t *testing.T, c Cache, beforeIncr interface{}, afterIncr interface{}, timeout time.Duration) {
|
||||||
|
var err error
|
||||||
|
ctx := context.Background()
|
||||||
|
key := "incDecKey"
|
||||||
|
if err = c.Put(ctx, key, beforeIncr, timeout); err != nil {
|
||||||
|
t.Error("Get Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.Incr(ctx, key); err != nil {
|
||||||
|
t.Error("Incr Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, _ := c.Get(ctx, key); v != afterIncr {
|
||||||
|
t.Error("Get Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.Decr(ctx, key); err != nil {
|
||||||
|
t.Error("Decr Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, _ := c.Get(ctx, key); v != beforeIncr {
|
||||||
|
t.Error("Get Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Delete(ctx, key); err != nil {
|
||||||
|
t.Error("Delete Error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
95
client/cache/file.go
vendored
95
client/cache/file.go
vendored
@ -26,8 +26,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -144,18 +144,23 @@ func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) {
|
|||||||
// GetMulti gets values from file cache.
|
// GetMulti gets values from file cache.
|
||||||
// if nonexistent or expired return an empty string.
|
// if nonexistent or expired return an empty string.
|
||||||
func (fc *FileCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
func (fc *FileCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||||
var rc []interface{}
|
rc := make([]interface{}, len(keys))
|
||||||
for _, key := range keys {
|
keysErr := make([]string, 0)
|
||||||
val, err := fc.Get(context.Background(), key)
|
|
||||||
|
for i, ki := range keys {
|
||||||
|
val, err := fc.Get(context.Background(), ki)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc = append(rc, err)
|
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, err.Error()))
|
||||||
} else {
|
continue
|
||||||
rc = append(rc, val)
|
}
|
||||||
|
rc[i] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if len(keysErr) == 0 {
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
return rc, errors.New(strings.Join(keysErr, "; "))
|
||||||
|
}
|
||||||
|
|
||||||
// Put value into file cache.
|
// Put value into file cache.
|
||||||
// timeout: how long this file should be kept in ms
|
// timeout: how long this file should be kept in ms
|
||||||
@ -189,28 +194,70 @@ func (fc *FileCache) Delete(ctx context.Context, key string) error {
|
|||||||
// Incr increases cached int value.
|
// Incr increases cached int value.
|
||||||
// fc value is saved forever unless deleted.
|
// fc value is saved forever unless deleted.
|
||||||
func (fc *FileCache) Incr(ctx context.Context, key string) error {
|
func (fc *FileCache) Incr(ctx context.Context, key string) error {
|
||||||
data, _ := fc.Get(context.Background(), key)
|
data, err := fc.Get(context.Background(), key)
|
||||||
var incr int
|
if err != nil {
|
||||||
if reflect.TypeOf(data).Name() != "int" {
|
return err
|
||||||
incr = 0
|
|
||||||
} else {
|
|
||||||
incr = data.(int) + 1
|
|
||||||
}
|
}
|
||||||
fc.Put(context.Background(), key, incr, time.Duration(fc.EmbedExpiry))
|
|
||||||
return nil
|
var res interface{}
|
||||||
|
switch val := data.(type) {
|
||||||
|
case int:
|
||||||
|
res = val + 1
|
||||||
|
case int32:
|
||||||
|
res = val + 1
|
||||||
|
case int64:
|
||||||
|
res = val + 1
|
||||||
|
case uint:
|
||||||
|
res = val + 1
|
||||||
|
case uint32:
|
||||||
|
res = val + 1
|
||||||
|
case uint64:
|
||||||
|
res = val + 1
|
||||||
|
default:
|
||||||
|
return errors.Errorf("data is not (u)int (u)int32 (u)int64")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fc.Put(context.Background(), key, res, time.Duration(fc.EmbedExpiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decr decreases cached int value.
|
// Decr decreases cached int value.
|
||||||
func (fc *FileCache) Decr(ctx context.Context, key string) error {
|
func (fc *FileCache) Decr(ctx context.Context, key string) error {
|
||||||
data, _ := fc.Get(context.Background(), key)
|
data, err := fc.Get(context.Background(), key)
|
||||||
var decr int
|
if err != nil {
|
||||||
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
|
return err
|
||||||
decr = 0
|
|
||||||
} else {
|
|
||||||
decr = data.(int) - 1
|
|
||||||
}
|
}
|
||||||
fc.Put(context.Background(), key, decr, time.Duration(fc.EmbedExpiry))
|
|
||||||
return nil
|
var res interface{}
|
||||||
|
switch val := data.(type) {
|
||||||
|
case int:
|
||||||
|
res = val - 1
|
||||||
|
case int32:
|
||||||
|
res = val - 1
|
||||||
|
case int64:
|
||||||
|
res = val - 1
|
||||||
|
case uint:
|
||||||
|
if val > 0 {
|
||||||
|
res = val - 1
|
||||||
|
} else {
|
||||||
|
return errors.New("data val is less than 0")
|
||||||
|
}
|
||||||
|
case uint32:
|
||||||
|
if val > 0 {
|
||||||
|
res = val - 1
|
||||||
|
} else {
|
||||||
|
return errors.New("data val is less than 0")
|
||||||
|
}
|
||||||
|
case uint64:
|
||||||
|
if val > 0 {
|
||||||
|
res = val - 1
|
||||||
|
} else {
|
||||||
|
return errors.New("data val is less than 0")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return errors.Errorf("data is not (u)int (u)int32 (u)int64")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fc.Put(context.Background(), key, res, time.Duration(fc.EmbedExpiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsExist checks if value exists.
|
// IsExist checks if value exists.
|
||||||
|
25
client/cache/memcache/memcache.go
vendored
25
client/cache/memcache/memcache.go
vendored
@ -33,6 +33,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -68,21 +69,33 @@ func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) {
|
|||||||
|
|
||||||
// GetMulti gets a value from a key in memcache.
|
// GetMulti gets a value from a key in memcache.
|
||||||
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||||
var rv []interface{}
|
rv := make([]interface{}, len(keys))
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return rv, err
|
return rv, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mv, err := rc.conn.GetMulti(keys)
|
mv, err := rc.conn.GetMulti(keys)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
for _, v := range mv {
|
|
||||||
rv = append(rv, v.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv, err
|
return rv, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keysErr := make([]string, 0)
|
||||||
|
for i, ki := range keys {
|
||||||
|
if _, ok := mv[ki]; !ok {
|
||||||
|
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, "the key isn't exist"))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rv[i] = mv[ki].Value
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(keysErr) == 0 {
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
return rv, fmt.Errorf(strings.Join(keysErr, "; "))
|
||||||
|
}
|
||||||
|
|
||||||
// Put puts a value into memcache.
|
// Put puts a value into memcache.
|
||||||
func (rc *Cache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error {
|
func (rc *Cache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
|
15
client/cache/memcache/memcache_test.go
vendored
15
client/cache/memcache/memcache_test.go
vendored
@ -28,7 +28,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMemcacheCache(t *testing.T) {
|
func TestMemcacheCache(t *testing.T) {
|
||||||
|
|
||||||
addr := os.Getenv("MEMCACHE_ADDR")
|
addr := os.Getenv("MEMCACHE_ADDR")
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = "127.0.0.1:11211"
|
addr = "127.0.0.1:11211"
|
||||||
@ -114,6 +113,20 @@ func TestMemcacheCache(t *testing.T) {
|
|||||||
t.Error("GetMulti ERROR")
|
t.Error("GetMulti ERROR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vv, err = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
|
if len(vv) != 2 {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if vv[0] != nil {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if string(vv[1].([]byte)) != "author1" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if err != nil && err.Error() == "key [astaxie0] error: key isn't exist" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
// test clear all
|
// test clear all
|
||||||
if err = bm.ClearAll(context.Background()); err != nil {
|
if err = bm.ClearAll(context.Background()); err != nil {
|
||||||
t.Error("clear all err")
|
t.Error("clear all err")
|
||||||
|
22
client/cache/memory.go
vendored
22
client/cache/memory.go
vendored
@ -18,6 +18,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -68,23 +70,29 @@ func (bc *MemoryCache) Get(ctx context.Context, key string) (interface{}, error)
|
|||||||
}
|
}
|
||||||
return itm.val, nil
|
return itm.val, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, errors.New("the key isn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMulti gets caches from memory.
|
// GetMulti gets caches from memory.
|
||||||
// If non-existent or expired, return nil.
|
// If non-existent or expired, return nil.
|
||||||
func (bc *MemoryCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
func (bc *MemoryCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||||
var rc []interface{}
|
rc := make([]interface{}, len(keys))
|
||||||
for _, name := range keys {
|
keysErr := make([]string, 0)
|
||||||
val, err := bc.Get(context.Background(), name)
|
|
||||||
|
for i, ki := range keys {
|
||||||
|
val, err := bc.Get(context.Background(), ki)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rc = append(rc, err)
|
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, err.Error()))
|
||||||
} else {
|
continue
|
||||||
rc = append(rc, val)
|
|
||||||
}
|
}
|
||||||
|
rc[i] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(keysErr) == 0 {
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
return rc, errors.New(strings.Join(keysErr, "; "))
|
||||||
|
}
|
||||||
|
|
||||||
// Put puts cache into memory.
|
// Put puts cache into memory.
|
||||||
// If lifespan is 0, it will never overwrite this value unless restarted
|
// If lifespan is 0, it will never overwrite this value unless restarted
|
||||||
|
8
client/cache/redis/redis_test.go
vendored
8
client/cache/redis/redis_test.go
vendored
@ -113,6 +113,14 @@ func TestRedisCache(t *testing.T) {
|
|||||||
t.Error("GetMulti ERROR")
|
t.Error("GetMulti ERROR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vv, _ = bm.GetMulti(context.Background(), []string{"astaxie0", "astaxie1"})
|
||||||
|
if vv[0] != nil {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
if v, _ := redis.String(vv[1], nil); v != "author1" {
|
||||||
|
t.Error("GetMulti ERROR")
|
||||||
|
}
|
||||||
|
|
||||||
// test clear all
|
// test clear all
|
||||||
if err = bm.ClearAll(context.Background()); err != nil {
|
if err = bm.ClearAll(context.Background()); err != nil {
|
||||||
t.Error("clear all err")
|
t.Error("clear all err")
|
||||||
|
31
client/cache/ssdb/ssdb.go
vendored
31
client/cache/ssdb/ssdb.go
vendored
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -28,36 +29,50 @@ func NewSsdbCache() cache.Cache {
|
|||||||
func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) {
|
func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return nil, nil
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value, err := rc.conn.Get(key)
|
value, err := rc.conn.Get(key)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMulti gets one or keys values from ssdb.
|
// GetMulti gets one or keys values from ssdb.
|
||||||
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||||
size := len(keys)
|
size := len(keys)
|
||||||
var values []interface{}
|
values := make([]interface{}, size)
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return values, err
|
return values, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := rc.conn.Do("multi_get", keys)
|
res, err := rc.conn.Do("multi_get", keys)
|
||||||
|
if err != nil {
|
||||||
|
return values, err
|
||||||
|
}
|
||||||
|
|
||||||
resSize := len(res)
|
resSize := len(res)
|
||||||
if err == nil {
|
keyIdx := make(map[string]int)
|
||||||
for i := 1; i < resSize; i += 2 {
|
for i := 1; i < resSize; i += 2 {
|
||||||
values = append(values, res[i+1])
|
keyIdx[res[i]] = i
|
||||||
}
|
}
|
||||||
return values, nil
|
|
||||||
|
keysErr := make([]string, 0)
|
||||||
|
for i, ki := range keys {
|
||||||
|
if _, ok := keyIdx[ki]; !ok {
|
||||||
|
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, "the key isn't exist"))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
for i := 0; i < size; i++ {
|
values[i] = res[keyIdx[ki]+1]
|
||||||
values = append(values, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(keysErr) != 0 {
|
||||||
|
return values, fmt.Errorf(strings.Join(keysErr, "; "))
|
||||||
|
}
|
||||||
|
|
||||||
return values, nil
|
return values, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
client/cache/ssdb/ssdb_test.go
vendored
14
client/cache/ssdb/ssdb_test.go
vendored
@ -106,6 +106,20 @@ func TestSsdbcacheCache(t *testing.T) {
|
|||||||
t.Error("getmulti error")
|
t.Error("getmulti error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vv, err = ssdb.GetMulti(context.Background(), []string{"ssdb", "ssdb11"})
|
||||||
|
if len(vv) != 2 {
|
||||||
|
t.Error("getmulti error")
|
||||||
|
}
|
||||||
|
if vv[0].(string) != "ssdb" {
|
||||||
|
t.Error("getmulti error")
|
||||||
|
}
|
||||||
|
if vv[1] != nil {
|
||||||
|
t.Error("getmulti error")
|
||||||
|
}
|
||||||
|
if err != nil && err.Error() != "key [ssdb11] error: the key isn't exist" {
|
||||||
|
t.Error("getmulti error")
|
||||||
|
}
|
||||||
|
|
||||||
// test clear all done
|
// test clear all done
|
||||||
if err = ssdb.ClearAll(context.Background()); err != nil {
|
if err = ssdb.ClearAll(context.Background()); err != nil {
|
||||||
t.Error("clear all err")
|
t.Error("clear all err")
|
||||||
|
@ -76,10 +76,13 @@ func (c Condition) AndNot(expr string, args ...interface{}) *Condition {
|
|||||||
|
|
||||||
// AndCond combine a condition to current condition
|
// AndCond combine a condition to current condition
|
||||||
func (c *Condition) AndCond(cond *Condition) *Condition {
|
func (c *Condition) AndCond(cond *Condition) *Condition {
|
||||||
c = c.clone()
|
|
||||||
if c == cond {
|
if c == cond {
|
||||||
panic(fmt.Errorf("<Condition.AndCond> cannot use self as sub cond"))
|
panic(fmt.Errorf("<Condition.AndCond> cannot use self as sub cond"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = c.clone()
|
||||||
|
|
||||||
if cond != nil {
|
if cond != nil {
|
||||||
c.params = append(c.params, condValue{cond: cond, isCond: true})
|
c.params = append(c.params, condValue{cond: cond, isCond: true})
|
||||||
}
|
}
|
||||||
@ -149,5 +152,8 @@ func (c *Condition) IsEmpty() bool {
|
|||||||
|
|
||||||
// clone clone a condition
|
// clone clone a condition
|
||||||
func (c Condition) clone() *Condition {
|
func (c Condition) clone() *Condition {
|
||||||
|
params := make([]condValue, len(c.params))
|
||||||
|
copy(params, c.params)
|
||||||
|
c.params = params
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
@ -2668,3 +2668,48 @@ func TestPSQueryBuilder(t *testing.T) {
|
|||||||
throwFailNow(t, AssertIs(l[0].UserName, "astaxie"))
|
throwFailNow(t, AssertIs(l[0].UserName, "astaxie"))
|
||||||
throwFailNow(t, AssertIs(l[0].Age, 30))
|
throwFailNow(t, AssertIs(l[0].Age, 30))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCondition(t *testing.T) {
|
||||||
|
// test Condition whether to include yourself
|
||||||
|
cond := NewCondition()
|
||||||
|
cond = cond.AndCond(cond.Or("ID", 1))
|
||||||
|
cond = cond.AndCond(cond.Or("ID", 2))
|
||||||
|
cond = cond.AndCond(cond.Or("ID", 3))
|
||||||
|
cond = cond.AndCond(cond.Or("ID", 4))
|
||||||
|
|
||||||
|
cycleFlag := false
|
||||||
|
var hasCycle func(*Condition)
|
||||||
|
hasCycle = func(c *Condition) {
|
||||||
|
if nil == c || cycleFlag {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
condPointMap := make(map[string]bool)
|
||||||
|
condPointMap[fmt.Sprintf("%p", c)] = true
|
||||||
|
for _, p := range c.params {
|
||||||
|
if p.isCond {
|
||||||
|
adr := fmt.Sprintf("%p", p.cond)
|
||||||
|
if condPointMap[adr] {
|
||||||
|
// self as sub cond was cycle
|
||||||
|
cycleFlag = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
condPointMap[adr] = true
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cycleFlag {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, p := range c.params {
|
||||||
|
if p.isCond {
|
||||||
|
// check next cond
|
||||||
|
hasCycle(p.cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hasCycle(cond)
|
||||||
|
// cycleFlag was true,meaning use self as sub cond
|
||||||
|
throwFail(t, AssertIs(!cycleFlag, true))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -49,12 +49,12 @@ func (f *StrTo) Set(v string) {
|
|||||||
|
|
||||||
// Clear string
|
// Clear string
|
||||||
func (f *StrTo) Clear() {
|
func (f *StrTo) Clear() {
|
||||||
*f = StrTo(0x1E)
|
*f = StrTo(rune(0x1E))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist check string exist
|
// Exist check string exist
|
||||||
func (f StrTo) Exist() bool {
|
func (f StrTo) Exist() bool {
|
||||||
return string(f) != string(0x1E)
|
return string(f) != string(rune(0x1E))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool string to bool
|
// Bool string to bool
|
||||||
|
@ -18,7 +18,6 @@ package config
|
|||||||
// for most users, they only need to use those methods
|
// for most users, they only need to use those methods
|
||||||
var globalInstance Configer
|
var globalInstance Configer
|
||||||
|
|
||||||
|
|
||||||
// InitGlobalInstance will ini the global instance
|
// InitGlobalInstance will ini the global instance
|
||||||
// If you want to use specific implementation, don't forget to import it.
|
// If you want to use specific implementation, don't forget to import it.
|
||||||
// e.g. _ import "github.com/astaxie/beego/core/config/etcd"
|
// e.g. _ import "github.com/astaxie/beego/core/config/etcd"
|
||||||
|
@ -519,7 +519,7 @@ func (c *IniConfigContainer) Unmarshaler(prefix string, obj interface{}, opt ...
|
|||||||
func init() {
|
func init() {
|
||||||
Register("ini", &IniConfig{})
|
Register("ini", &IniConfig{})
|
||||||
|
|
||||||
err := InitGlobalInstance("ini", "config/app.conf")
|
err := InitGlobalInstance("ini", "conf/app.conf")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Warn("init global config instance failed. If you donot use this, just ignore it. ", err)
|
logs.Warn("init global config instance failed. If you donot use this, just ignore it. ", err)
|
||||||
}
|
}
|
||||||
|
@ -764,9 +764,7 @@ func formatLog(f interface{}, v ...interface{}) string {
|
|||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
|
if !strings.Contains(msg, "%") {
|
||||||
// format string
|
|
||||||
} else {
|
|
||||||
// do not contain format char
|
// do not contain format char
|
||||||
msg += strings.Repeat(" %v", len(v))
|
msg += strings.Repeat(" %v", len(v))
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package logs
|
package logs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -25,8 +25,8 @@ func newSLACKWriter() Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SLACKWriter) Format(lm *LogMsg) string {
|
func (s *SLACKWriter) Format(lm *LogMsg) string {
|
||||||
text := fmt.Sprintf("{\"text\": \"%s %s\"}", lm.When.Format("2006-01-02 15:04:05"), lm.OldStyleFormat())
|
// text := fmt.Sprintf("{\"text\": \"%s\"}", msg)
|
||||||
return text
|
return lm.When.Format("2006-01-02 15:04:05") + " " + lm.OldStyleFormat()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SLACKWriter) SetFormatter(f LogFormatter) {
|
func (s *SLACKWriter) SetFormatter(f LogFormatter) {
|
||||||
@ -55,10 +55,12 @@ func (s *SLACKWriter) WriteMsg(lm *LogMsg) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
msg := s.Format(lm)
|
msg := s.Format(lm)
|
||||||
form := url.Values{}
|
m := make(map[string]string, 1)
|
||||||
form.Add("payload", msg)
|
m["text"] = msg
|
||||||
|
|
||||||
resp, err := http.PostForm(s.WebhookURL, form)
|
body, _ := json.Marshal(m)
|
||||||
|
// resp, err := http.PostForm(s.WebhookURL, form)
|
||||||
|
resp, err := http.Post(s.WebhookURL, "application/json", bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
44
core/logs/slack_test.go
Normal file
44
core/logs/slack_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// 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 logs
|
||||||
|
|
||||||
|
// func TestSLACKWriter_WriteMsg(t *testing.T) {
|
||||||
|
// sc := `
|
||||||
|
// {
|
||||||
|
// "webhookurl":"",
|
||||||
|
// "level":7
|
||||||
|
// }
|
||||||
|
// `
|
||||||
|
// l := newSLACKWriter()
|
||||||
|
// err := l.Init(sc)
|
||||||
|
// if err != nil {
|
||||||
|
// Debug(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// err = l.WriteMsg(&LogMsg{
|
||||||
|
// Level: 7,
|
||||||
|
// Msg: `{ "abs"`,
|
||||||
|
// When: time.Now(),
|
||||||
|
// FilePath: "main.go",
|
||||||
|
// LineNumber: 100,
|
||||||
|
// enableFullFilePath: true,
|
||||||
|
// enableFuncCallDepth: true,
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// Debug(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
@ -261,15 +261,15 @@ func (output *BeegoOutput) XML(data interface{}, hasIndent bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServeFormatted serves YAML, XML or JSON, depending on the value of the Accept header
|
// ServeFormatted serves YAML, XML or JSON, depending on the value of the Accept header
|
||||||
func (output *BeegoOutput) ServeFormatted(data interface{}, hasIndent bool, hasEncode ...bool) {
|
func (output *BeegoOutput) ServeFormatted(data interface{}, hasIndent bool, hasEncode ...bool) error {
|
||||||
accept := output.Context.Input.Header("Accept")
|
accept := output.Context.Input.Header("Accept")
|
||||||
switch accept {
|
switch accept {
|
||||||
case ApplicationYAML:
|
case ApplicationYAML:
|
||||||
output.YAML(data)
|
return output.YAML(data)
|
||||||
case ApplicationXML, TextXML:
|
case ApplicationXML, TextXML:
|
||||||
output.XML(data, hasIndent)
|
return output.XML(data, hasIndent)
|
||||||
default:
|
default:
|
||||||
output.JSON(data, hasIndent, len(hasEncode) > 0 && hasEncode[0])
|
return output.JSON(data, hasIndent, len(hasEncode) > 0 && hasEncode[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ package web
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
context2 "context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
@ -250,6 +251,9 @@ func (c *Controller) Render() error {
|
|||||||
// RenderString returns the rendered template string. Do not send out response.
|
// RenderString returns the rendered template string. Do not send out response.
|
||||||
func (c *Controller) RenderString() (string, error) {
|
func (c *Controller) RenderString() (string, error) {
|
||||||
b, e := c.RenderBytes()
|
b, e := c.RenderBytes()
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
return string(b), e
|
return string(b), e
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +280,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
|
err = ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
|
||||||
}
|
}
|
||||||
return buf.Bytes(), err
|
return buf.Bytes(), err
|
||||||
}
|
}
|
||||||
@ -373,50 +377,57 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServeJSON sends a json response with encoding charset.
|
// ServeJSON sends a json response with encoding charset.
|
||||||
func (c *Controller) ServeJSON(encoding ...bool) {
|
func (c *Controller) ServeJSON(encoding ...bool) error {
|
||||||
var (
|
var (
|
||||||
hasIndent = BConfig.RunMode != PROD
|
hasIndent = BConfig.RunMode != PROD
|
||||||
hasEncoding = len(encoding) > 0 && encoding[0]
|
hasEncoding = len(encoding) > 0 && encoding[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
|
return c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeJSONP sends a jsonp response.
|
// ServeJSONP sends a jsonp response.
|
||||||
func (c *Controller) ServeJSONP() {
|
func (c *Controller) ServeJSONP() error {
|
||||||
hasIndent := BConfig.RunMode != PROD
|
hasIndent := BConfig.RunMode != PROD
|
||||||
c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
|
return c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeXML sends xml response.
|
// ServeXML sends xml response.
|
||||||
func (c *Controller) ServeXML() {
|
func (c *Controller) ServeXML() error {
|
||||||
hasIndent := BConfig.RunMode != PROD
|
hasIndent := BConfig.RunMode != PROD
|
||||||
c.Ctx.Output.XML(c.Data["xml"], hasIndent)
|
return c.Ctx.Output.XML(c.Data["xml"], hasIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeYAML sends yaml response.
|
// ServeYAML sends yaml response.
|
||||||
func (c *Controller) ServeYAML() {
|
func (c *Controller) ServeYAML() error {
|
||||||
c.Ctx.Output.YAML(c.Data["yaml"])
|
return c.Ctx.Output.YAML(c.Data["yaml"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header
|
// ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header
|
||||||
func (c *Controller) ServeFormatted(encoding ...bool) {
|
func (c *Controller) ServeFormatted(encoding ...bool) error {
|
||||||
hasIndent := BConfig.RunMode != PROD
|
hasIndent := BConfig.RunMode != PROD
|
||||||
hasEncoding := len(encoding) > 0 && encoding[0]
|
hasEncoding := len(encoding) > 0 && encoding[0]
|
||||||
c.Ctx.Output.ServeFormatted(c.Data, hasIndent, hasEncoding)
|
return c.Ctx.Output.ServeFormatted(c.Data, hasIndent, hasEncoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input returns the input data map from POST or PUT request body and query string.
|
// Input returns the input data map from POST or PUT request body and query string.
|
||||||
func (c *Controller) Input() url.Values {
|
func (c *Controller) Input() (url.Values, error) {
|
||||||
if c.Ctx.Request.Form == nil {
|
if c.Ctx.Request.Form == nil {
|
||||||
c.Ctx.Request.ParseForm()
|
err := c.Ctx.Request.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.Ctx.Request.Form
|
}
|
||||||
|
return c.Ctx.Request.Form, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseForm maps input data map to obj struct.
|
// ParseForm maps input data map to obj struct.
|
||||||
func (c *Controller) ParseForm(obj interface{}) error {
|
func (c *Controller) ParseForm(obj interface{}) error {
|
||||||
return ParseForm(c.Input(), obj)
|
form, err := c.Input()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ParseForm(form, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetString returns the input value by key string or the default value while it's present and input is blank
|
// GetString returns the input value by key string or the default value while it's present and input is blank
|
||||||
@ -438,7 +449,7 @@ func (c *Controller) GetStrings(key string, def ...[]string) []string {
|
|||||||
defv = def[0]
|
defv = def[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if f := c.Input(); f == nil {
|
if f, err := c.Input(); f == nil || err != nil {
|
||||||
return defv
|
return defv
|
||||||
} else if vs := f[key]; len(vs) > 0 {
|
} else if vs := f[key]; len(vs) > 0 {
|
||||||
return vs
|
return vs
|
||||||
@ -618,11 +629,11 @@ func (c *Controller) StartSession() session.Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetSession puts value into session.
|
// SetSession puts value into session.
|
||||||
func (c *Controller) SetSession(name interface{}, value interface{}) {
|
func (c *Controller) SetSession(name interface{}, value interface{}) error {
|
||||||
if c.CruSession == nil {
|
if c.CruSession == nil {
|
||||||
c.StartSession()
|
c.StartSession()
|
||||||
}
|
}
|
||||||
c.CruSession.Set(nil, name, value)
|
return c.CruSession.Set(context2.Background(), name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSession gets value from session.
|
// GetSession gets value from session.
|
||||||
@ -630,32 +641,38 @@ func (c *Controller) GetSession(name interface{}) interface{} {
|
|||||||
if c.CruSession == nil {
|
if c.CruSession == nil {
|
||||||
c.StartSession()
|
c.StartSession()
|
||||||
}
|
}
|
||||||
return c.CruSession.Get(nil, name)
|
return c.CruSession.Get(context2.Background(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelSession removes value from session.
|
// DelSession removes value from session.
|
||||||
func (c *Controller) DelSession(name interface{}) {
|
func (c *Controller) DelSession(name interface{}) error {
|
||||||
if c.CruSession == nil {
|
if c.CruSession == nil {
|
||||||
c.StartSession()
|
c.StartSession()
|
||||||
}
|
}
|
||||||
c.CruSession.Delete(nil, name)
|
return c.CruSession.Delete(context2.Background(), name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionRegenerateID regenerates session id for this session.
|
// SessionRegenerateID regenerates session id for this session.
|
||||||
// the session data have no changes.
|
// the session data have no changes.
|
||||||
func (c *Controller) SessionRegenerateID() {
|
func (c *Controller) SessionRegenerateID() error {
|
||||||
if c.CruSession != nil {
|
if c.CruSession != nil {
|
||||||
c.CruSession.SessionRelease(nil, c.Ctx.ResponseWriter)
|
c.CruSession.SessionRelease(context2.Background(), c.Ctx.ResponseWriter)
|
||||||
}
|
}
|
||||||
c.CruSession = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
|
var err error
|
||||||
|
c.CruSession, err = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||||
c.Ctx.Input.CruSession = c.CruSession
|
c.Ctx.Input.CruSession = c.CruSession
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DestroySession cleans session data and session cookie.
|
// DestroySession cleans session data and session cookie.
|
||||||
func (c *Controller) DestroySession() {
|
func (c *Controller) DestroySession() error {
|
||||||
c.Ctx.Input.CruSession.Flush(nil)
|
err := c.Ctx.Input.CruSession.Flush(nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
c.Ctx.Input.CruSession = nil
|
c.Ctx.Input.CruSession = nil
|
||||||
GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
|
GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAjax returns this request is ajax or not.
|
// IsAjax returns this request is ajax or not.
|
||||||
|
@ -273,7 +273,6 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) {
|
|||||||
for _, f := range a.Filters {
|
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, WithReturnOnOutput(f.ReturnOnOutput), WithResetParams(f.ResetParams))
|
||||||
}
|
}
|
||||||
|
|
||||||
p.addWithMethodParams(a.Router, c, a.MethodParams, strings.Join(a.AllowHTTPMethods, ",")+":"+a.Method)
|
p.addWithMethodParams(a.Router, c, a.MethodParams, strings.Join(a.AllowHTTPMethods, ",")+":"+a.Method)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,15 +298,21 @@ func (manager *Manager) GC() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request.
|
// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request.
|
||||||
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) (session Store) {
|
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) (Store, error) {
|
||||||
sid, err := manager.sessionID()
|
sid, err := manager.sessionID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var session Store
|
||||||
|
|
||||||
cookie, err := r.Cookie(manager.config.CookieName)
|
cookie, err := r.Cookie(manager.config.CookieName)
|
||||||
if err != nil || cookie.Value == "" {
|
if err != nil || cookie.Value == "" {
|
||||||
//delete old cookie
|
//delete old cookie
|
||||||
session, _ = manager.provider.SessionRead(nil, sid)
|
session, err = manager.provider.SessionRead(nil, sid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
cookie = &http.Cookie{Name: manager.config.CookieName,
|
cookie = &http.Cookie{Name: manager.config.CookieName,
|
||||||
Value: url.QueryEscape(sid),
|
Value: url.QueryEscape(sid),
|
||||||
Path: "/",
|
Path: "/",
|
||||||
@ -315,8 +321,16 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
|
|||||||
Domain: manager.config.Domain,
|
Domain: manager.config.Domain,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oldsid, _ := url.QueryUnescape(cookie.Value)
|
oldsid, err := url.QueryUnescape(cookie.Value)
|
||||||
session, _ = manager.provider.SessionRegenerate(nil, oldsid, sid)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err = manager.provider.SessionRegenerate(nil, oldsid, sid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
cookie.Value = url.QueryEscape(sid)
|
cookie.Value = url.QueryEscape(sid)
|
||||||
cookie.HttpOnly = true
|
cookie.HttpOnly = true
|
||||||
cookie.Path = "/"
|
cookie.Path = "/"
|
||||||
@ -335,7 +349,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
|
|||||||
w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
|
w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActiveSession Get all active sessions count number.
|
// GetActiveSession Get all active sessions count number.
|
||||||
|
@ -21,76 +21,109 @@ import (
|
|||||||
"github.com/astaxie/beego/server/web/context"
|
"github.com/astaxie/beego/server/web/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testinfo struct {
|
type testInfo struct {
|
||||||
url string
|
pattern string
|
||||||
requesturl string
|
requestUrl string
|
||||||
params map[string]string
|
params map[string]string
|
||||||
|
shouldMatchOrNot bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var routers []testinfo
|
var routers []testInfo
|
||||||
|
|
||||||
|
func matchTestInfo(pattern, url string, params map[string]string) testInfo {
|
||||||
|
return testInfo{
|
||||||
|
pattern: pattern,
|
||||||
|
requestUrl: url,
|
||||||
|
params: params,
|
||||||
|
shouldMatchOrNot: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func notMatchTestInfo(pattern, url string) testInfo {
|
||||||
|
return testInfo{
|
||||||
|
pattern: pattern,
|
||||||
|
requestUrl: url,
|
||||||
|
params: nil,
|
||||||
|
shouldMatchOrNot: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
routers = make([]testinfo, 0)
|
routers = make([]testInfo, 0)
|
||||||
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic", nil})
|
//match example
|
||||||
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}})
|
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic", nil))
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}})
|
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}))
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}})
|
routers = append(routers, matchTestInfo("/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}))
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}})
|
routers = append(routers, matchTestInfo("/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}))
|
||||||
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}})
|
routers = append(routers, matchTestInfo("/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}))
|
||||||
routers = append(routers, testinfo{"/:id", "/123", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}))
|
||||||
routers = append(routers, testinfo{"/hello/?:id", "/hello", map[string]string{":id": ""}})
|
routers = append(routers, matchTestInfo("/:id", "/123", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/", "/", nil})
|
routers = append(routers, matchTestInfo("/hello/?:id", "/hello", map[string]string{":id": ""}))
|
||||||
routers = append(routers, testinfo{"/customer/login", "/customer/login", nil})
|
routers = append(routers, matchTestInfo("/", "/", nil))
|
||||||
routers = append(routers, testinfo{"/customer/login", "/customer/login.json", map[string]string{":ext": "json"}})
|
routers = append(routers, matchTestInfo("/customer/login", "/customer/login", nil))
|
||||||
routers = append(routers, testinfo{"/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}})
|
routers = append(routers, matchTestInfo("/customer/login", "/customer/login.json", map[string]string{":ext": "json"}))
|
||||||
routers = append(routers, testinfo{"/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}})
|
routers = append(routers, matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}))
|
||||||
routers = append(routers, testinfo{"/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}})
|
routers = append(routers, matchTestInfo("/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}))
|
||||||
routers = append(routers, testinfo{"/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}})
|
routers = append(routers, matchTestInfo("/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}))
|
||||||
routers = append(routers, testinfo{"/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}})
|
routers = append(routers, matchTestInfo("/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}))
|
||||||
routers = append(routers, testinfo{"/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}})
|
routers = append(routers, matchTestInfo("/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}))
|
||||||
routers = append(routers, testinfo{"/thumbnail/:size/uploads/*",
|
routers = append(routers, matchTestInfo("/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}))
|
||||||
"/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg",
|
routers = append(routers, matchTestInfo("/thumbnail/:size/uploads/*", "/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg", map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}))
|
||||||
map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}})
|
routers = append(routers, matchTestInfo("/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}))
|
||||||
routers = append(routers, testinfo{"/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}})
|
routers = append(routers, matchTestInfo("/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}))
|
||||||
routers = append(routers, testinfo{"/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
|
routers = append(routers, matchTestInfo("/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}))
|
||||||
routers = append(routers, testinfo{"/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
|
routers = append(routers, matchTestInfo("/dl/:width:int/:height:int/*.*", "/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg", map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}))
|
||||||
routers = append(routers, testinfo{"/dl/:width:int/:height:int/*.*",
|
routers = append(routers, matchTestInfo("/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}))
|
||||||
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg",
|
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}))
|
||||||
map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}})
|
routers = append(routers, matchTestInfo("/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}})
|
routers = append(routers, matchTestInfo("/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}})
|
routers = append(routers, matchTestInfo("/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
|
||||||
routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}})
|
routers = append(routers, matchTestInfo("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
|
||||||
routers = append(routers, testinfo{"/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
routers = append(routers, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}))
|
||||||
routers = append(routers, testinfo{"/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
routers = append(routers, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}))
|
||||||
routers = append(routers, testinfo{"/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
|
|
||||||
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}})
|
//not match example
|
||||||
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}})
|
|
||||||
|
// https://github.com/astaxie/beego/issues/3865
|
||||||
|
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", "/read_222htm"))
|
||||||
|
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", "/read_222_htm"))
|
||||||
|
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", " /read_262shtm"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTreeRouters(t *testing.T) {
|
func TestTreeRouters(t *testing.T) {
|
||||||
for _, r := range routers {
|
for _, r := range routers {
|
||||||
|
shouldMatch := r.shouldMatchOrNot
|
||||||
|
|
||||||
tr := NewTree()
|
tr := NewTree()
|
||||||
tr.AddRouter(r.url, "astaxie")
|
tr.AddRouter(r.pattern, "astaxie")
|
||||||
ctx := context.NewContext()
|
ctx := context.NewContext()
|
||||||
obj := tr.Match(r.requesturl, ctx)
|
obj := tr.Match(r.requestUrl, ctx)
|
||||||
|
if !shouldMatch {
|
||||||
|
if obj != nil {
|
||||||
|
t.Fatal("pattern:", r.pattern, ", should not match", r.requestUrl)
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if obj == nil || obj.(string) != "astaxie" {
|
if obj == nil || obj.(string) != "astaxie" {
|
||||||
t.Fatal(r.url+" can't get obj, Expect ", r.requesturl)
|
t.Fatal("pattern:", r.pattern+", can't match obj, Expect ", r.requestUrl)
|
||||||
}
|
}
|
||||||
if r.params != nil {
|
if r.params != nil {
|
||||||
for k, v := range r.params {
|
for k, v := range r.params {
|
||||||
if vv := ctx.Input.Param(k); vv != v {
|
if vv := ctx.Input.Param(k); vv != v {
|
||||||
t.Fatal("The Rule: " + r.url + "\nThe RequestURL:" + r.requesturl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
|
t.Fatal("The Rule: " + r.pattern + "\nThe RequestURL:" + r.requestUrl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
|
||||||
} else if vv == "" && v != "" {
|
} else if vv == "" && v != "" {
|
||||||
t.Fatal(r.url + " " + r.requesturl + " get param empty:" + k)
|
t.Fatal(r.pattern + " " + r.requestUrl + " get param empty:" + k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,7 +280,6 @@ func TestAddTree5(t *testing.T) {
|
|||||||
t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
|
t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitPath(t *testing.T) {
|
func TestSplitPath(t *testing.T) {
|
||||||
a := splitPath("")
|
a := splitPath("")
|
||||||
if len(a) != 0 {
|
if len(a) != 0 {
|
||||||
@ -292,6 +324,7 @@ func TestSplitSegment(t *testing.T) {
|
|||||||
":id([0-9]+)": {true, []string{":id"}, `([0-9]+)`},
|
":id([0-9]+)": {true, []string{":id"}, `([0-9]+)`},
|
||||||
":id([0-9]+)_:name": {true, []string{":id", ":name"}, `([0-9]+)_(.+)`},
|
":id([0-9]+)_:name": {true, []string{":id", ":name"}, `([0-9]+)_(.+)`},
|
||||||
":id(.+)_cms.html": {true, []string{":id"}, `(.+)_cms.html`},
|
":id(.+)_cms.html": {true, []string{":id"}, `(.+)_cms.html`},
|
||||||
|
":id(.+)_cms\\.html": {true, []string{":id"}, `(.+)_cms\.html`},
|
||||||
"cms_:id(.+)_:page(.+).html": {true, []string{":id", ":page"}, `cms_(.+)_(.+).html`},
|
"cms_:id(.+)_:page(.+).html": {true, []string{":id", ":page"}, `cms_(.+)_(.+).html`},
|
||||||
`:app(a|b|c)`: {true, []string{":app"}, `(a|b|c)`},
|
`:app(a|b|c)`: {true, []string{":app"}, `(a|b|c)`},
|
||||||
`:app\((a|b|c)\)`: {true, []string{":app"}, `(.+)\((a|b|c)\)`},
|
`:app\((a|b|c)\)`: {true, []string{":app"}, `(.+)\((a|b|c)\)`},
|
||||||
|
@ -452,9 +452,11 @@ func (m *taskManager) StartTask() {
|
|||||||
|
|
||||||
func (m *taskManager) run() {
|
func (m *taskManager) run() {
|
||||||
now := time.Now().Local()
|
now := time.Now().Local()
|
||||||
|
m.taskLock.Lock()
|
||||||
for _, t := range m.adminTaskList {
|
for _, t := range m.adminTaskList {
|
||||||
t.SetNext(nil, now)
|
t.SetNext(nil, now)
|
||||||
}
|
}
|
||||||
|
m.taskLock.Unlock()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// we only use RLock here because NewMapSorter copy the reference, do not change any thing
|
// we only use RLock here because NewMapSorter copy the reference, do not change any thing
|
||||||
|
Loading…
Reference in New Issue
Block a user