mirror of
https://github.com/astaxie/beego.git
synced 2024-11-23 16:40:54 +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).
|
||||
|
||||
> 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
|
||||
|
||||
###### 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
|
||||
|
||||
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`
|
||||
```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.
|
||||
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.
|
||||
|
@ -141,7 +141,7 @@ func (manager *Manager) GC() {
|
||||
|
||||
// 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 {
|
||||
s := (*session.Manager)(manager).SessionRegenerateID(w, r)
|
||||
s, _ := (*session.Manager)(manager).SessionRegenerateID(w, r)
|
||||
return &NewToOldStoreAdapter{
|
||||
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)
|
||||
}
|
||||
|
||||
if err = bm.Incr(context.Background(), "astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
// test different integer type for incr & decr
|
||||
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")
|
||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
||||
t.Error("delete err")
|
||||
@ -120,6 +108,20 @@ func TestCache(t *testing.T) {
|
||||
if vv[1].(string) != "author1" {
|
||||
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) {
|
||||
@ -139,21 +141,9 @@ func TestFileCache(t *testing.T) {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Incr(context.Background(), "astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
// test different integer type for incr & decr
|
||||
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")
|
||||
if res, _ := bm.IsExist(context.Background(), "astaxie"); res {
|
||||
t.Error("delete err")
|
||||
@ -189,5 +179,57 @@ func TestFileCache(t *testing.T) {
|
||||
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")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
99
client/cache/file.go
vendored
99
client/cache/file.go
vendored
@ -26,8 +26,8 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -144,17 +144,22 @@ func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) {
|
||||
// GetMulti gets values from file cache.
|
||||
// if nonexistent or expired return an empty string.
|
||||
func (fc *FileCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||
var rc []interface{}
|
||||
for _, key := range keys {
|
||||
val, err := fc.Get(context.Background(), key)
|
||||
if err != nil {
|
||||
rc = append(rc, err)
|
||||
} else {
|
||||
rc = append(rc, val)
|
||||
}
|
||||
rc := make([]interface{}, len(keys))
|
||||
keysErr := make([]string, 0)
|
||||
|
||||
for i, ki := range keys {
|
||||
val, err := fc.Get(context.Background(), ki)
|
||||
if err != nil {
|
||||
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, err.Error()))
|
||||
continue
|
||||
}
|
||||
rc[i] = val
|
||||
}
|
||||
return rc, nil
|
||||
|
||||
if len(keysErr) == 0 {
|
||||
return rc, nil
|
||||
}
|
||||
return rc, errors.New(strings.Join(keysErr, "; "))
|
||||
}
|
||||
|
||||
// Put value into file cache.
|
||||
@ -189,28 +194,70 @@ func (fc *FileCache) Delete(ctx context.Context, key string) error {
|
||||
// Incr increases cached int value.
|
||||
// fc value is saved forever unless deleted.
|
||||
func (fc *FileCache) Incr(ctx context.Context, key string) error {
|
||||
data, _ := fc.Get(context.Background(), key)
|
||||
var incr int
|
||||
if reflect.TypeOf(data).Name() != "int" {
|
||||
incr = 0
|
||||
} else {
|
||||
incr = data.(int) + 1
|
||||
data, err := fc.Get(context.Background(), key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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.
|
||||
func (fc *FileCache) Decr(ctx context.Context, key string) error {
|
||||
data, _ := fc.Get(context.Background(), key)
|
||||
var decr int
|
||||
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
|
||||
decr = 0
|
||||
} else {
|
||||
decr = data.(int) - 1
|
||||
data, err := fc.Get(context.Background(), key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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.
|
||||
|
25
client/cache/memcache/memcache.go
vendored
25
client/cache/memcache/memcache.go
vendored
@ -33,6 +33,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -68,19 +69,31 @@ func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) {
|
||||
|
||||
// GetMulti gets a value from a key in memcache.
|
||||
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||
var rv []interface{}
|
||||
rv := make([]interface{}, len(keys))
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return rv, err
|
||||
}
|
||||
}
|
||||
|
||||
mv, err := rc.conn.GetMulti(keys)
|
||||
if err == nil {
|
||||
for _, v := range mv {
|
||||
rv = append(rv, v.Value)
|
||||
}
|
||||
if err != nil {
|
||||
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.
|
||||
|
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) {
|
||||
|
||||
addr := os.Getenv("MEMCACHE_ADDR")
|
||||
if addr == "" {
|
||||
addr = "127.0.0.1:11211"
|
||||
@ -114,6 +113,20 @@ func TestMemcacheCache(t *testing.T) {
|
||||
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
|
||||
if err = bm.ClearAll(context.Background()); err != nil {
|
||||
t.Error("clear all err")
|
||||
|
24
client/cache/memory.go
vendored
24
client/cache/memory.go
vendored
@ -18,6 +18,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -68,22 +70,28 @@ func (bc *MemoryCache) Get(ctx context.Context, key string) (interface{}, error)
|
||||
}
|
||||
return itm.val, nil
|
||||
}
|
||||
return nil, nil
|
||||
return nil, errors.New("the key isn't exist")
|
||||
}
|
||||
|
||||
// GetMulti gets caches from memory.
|
||||
// If non-existent or expired, return nil.
|
||||
func (bc *MemoryCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||
var rc []interface{}
|
||||
for _, name := range keys {
|
||||
val, err := bc.Get(context.Background(), name)
|
||||
rc := make([]interface{}, len(keys))
|
||||
keysErr := make([]string, 0)
|
||||
|
||||
for i, ki := range keys {
|
||||
val, err := bc.Get(context.Background(), ki)
|
||||
if err != nil {
|
||||
rc = append(rc, err)
|
||||
} else {
|
||||
rc = append(rc, val)
|
||||
keysErr = append(keysErr, fmt.Sprintf("key [%s] error: %s", ki, err.Error()))
|
||||
continue
|
||||
}
|
||||
rc[i] = val
|
||||
}
|
||||
return rc, nil
|
||||
|
||||
if len(keysErr) == 0 {
|
||||
return rc, nil
|
||||
}
|
||||
return rc, errors.New(strings.Join(keysErr, "; "))
|
||||
}
|
||||
|
||||
// Put puts cache into memory.
|
||||
|
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")
|
||||
}
|
||||
|
||||
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
|
||||
if err = bm.ClearAll(context.Background()); err != nil {
|
||||
t.Error("clear all err")
|
||||
|
33
client/cache/ssdb/ssdb.go
vendored
33
client/cache/ssdb/ssdb.go
vendored
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -28,36 +29,50 @@ func NewSsdbCache() cache.Cache {
|
||||
func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return nil, nil
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
value, err := rc.conn.Get(key)
|
||||
if err == nil {
|
||||
return value, nil
|
||||
}
|
||||
return nil, nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// GetMulti gets one or keys values from ssdb.
|
||||
func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
|
||||
size := len(keys)
|
||||
var values []interface{}
|
||||
values := make([]interface{}, size)
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return values, err
|
||||
}
|
||||
}
|
||||
|
||||
res, err := rc.conn.Do("multi_get", keys)
|
||||
if err != nil {
|
||||
return values, err
|
||||
}
|
||||
|
||||
resSize := len(res)
|
||||
if err == nil {
|
||||
for i := 1; i < resSize; i += 2 {
|
||||
values = append(values, res[i+1])
|
||||
keyIdx := make(map[string]int)
|
||||
for i := 1; i < resSize; i += 2 {
|
||||
keyIdx[res[i]] = i
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
return values, nil
|
||||
values[i] = res[keyIdx[ki]+1]
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
values = append(values, err)
|
||||
|
||||
if len(keysErr) != 0 {
|
||||
return values, fmt.Errorf(strings.Join(keysErr, "; "))
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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
|
||||
if err = ssdb.ClearAll(context.Background()); err != nil {
|
||||
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
|
||||
func (c *Condition) AndCond(cond *Condition) *Condition {
|
||||
c = c.clone()
|
||||
|
||||
if c == cond {
|
||||
panic(fmt.Errorf("<Condition.AndCond> cannot use self as sub cond"))
|
||||
}
|
||||
|
||||
c = c.clone()
|
||||
|
||||
if cond != nil {
|
||||
c.params = append(c.params, condValue{cond: cond, isCond: true})
|
||||
}
|
||||
@ -149,5 +152,8 @@ func (c *Condition) IsEmpty() bool {
|
||||
|
||||
// clone clone a condition
|
||||
func (c Condition) clone() *Condition {
|
||||
params := make([]condValue, len(c.params))
|
||||
copy(params, c.params)
|
||||
c.params = params
|
||||
return &c
|
||||
}
|
||||
|
@ -2668,3 +2668,48 @@ func TestPSQueryBuilder(t *testing.T) {
|
||||
throwFailNow(t, AssertIs(l[0].UserName, "astaxie"))
|
||||
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
|
||||
func (f *StrTo) Clear() {
|
||||
*f = StrTo(0x1E)
|
||||
*f = StrTo(rune(0x1E))
|
||||
}
|
||||
|
||||
// Exist check string exist
|
||||
func (f StrTo) Exist() bool {
|
||||
return string(f) != string(0x1E)
|
||||
return string(f) != string(rune(0x1E))
|
||||
}
|
||||
|
||||
// Bool string to bool
|
||||
|
@ -18,7 +18,6 @@ package config
|
||||
// for most users, they only need to use those methods
|
||||
var globalInstance Configer
|
||||
|
||||
|
||||
// InitGlobalInstance will ini the global instance
|
||||
// If you want to use specific implementation, don't forget to import it.
|
||||
// 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() {
|
||||
Register("ini", &IniConfig{})
|
||||
|
||||
err := InitGlobalInstance("ini", "config/app.conf")
|
||||
err := InitGlobalInstance("ini", "conf/app.conf")
|
||||
if err != nil {
|
||||
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 {
|
||||
return msg
|
||||
}
|
||||
if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
|
||||
// format string
|
||||
} else {
|
||||
if !strings.Contains(msg, "%") {
|
||||
// do not contain format char
|
||||
msg += strings.Repeat(" %v", len(v))
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -25,8 +25,8 @@ func newSLACKWriter() Logger {
|
||||
}
|
||||
|
||||
func (s *SLACKWriter) Format(lm *LogMsg) string {
|
||||
text := fmt.Sprintf("{\"text\": \"%s %s\"}", lm.When.Format("2006-01-02 15:04:05"), lm.OldStyleFormat())
|
||||
return text
|
||||
// text := fmt.Sprintf("{\"text\": \"%s\"}", msg)
|
||||
return lm.When.Format("2006-01-02 15:04:05") + " " + lm.OldStyleFormat()
|
||||
}
|
||||
|
||||
func (s *SLACKWriter) SetFormatter(f LogFormatter) {
|
||||
@ -55,10 +55,12 @@ func (s *SLACKWriter) WriteMsg(lm *LogMsg) error {
|
||||
return nil
|
||||
}
|
||||
msg := s.Format(lm)
|
||||
form := url.Values{}
|
||||
form.Add("payload", msg)
|
||||
m := make(map[string]string, 1)
|
||||
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 {
|
||||
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
|
||||
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")
|
||||
switch accept {
|
||||
case ApplicationYAML:
|
||||
output.YAML(data)
|
||||
return output.YAML(data)
|
||||
case ApplicationXML, TextXML:
|
||||
output.XML(data, hasIndent)
|
||||
return output.XML(data, hasIndent)
|
||||
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 (
|
||||
"bytes"
|
||||
context2 "context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@ -250,13 +251,16 @@ func (c *Controller) Render() error {
|
||||
// RenderString returns the rendered template string. Do not send out response.
|
||||
func (c *Controller) RenderString() (string, error) {
|
||||
b, e := c.RenderBytes()
|
||||
if e != nil {
|
||||
return "", e
|
||||
}
|
||||
return string(b), e
|
||||
}
|
||||
|
||||
// RenderBytes returns the bytes of rendered template string. Do not send out response.
|
||||
func (c *Controller) RenderBytes() ([]byte, error) {
|
||||
buf, err := c.renderTemplate()
|
||||
//if the controller has set layout, then first get the tplName's content set the content to the layout
|
||||
// if the controller has set layout, then first get the tplName's content set the content to the layout
|
||||
if err == nil && c.Layout != "" {
|
||||
c.Data["LayoutContent"] = template.HTML(buf.String())
|
||||
|
||||
@ -276,7 +280,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
|
||||
err = ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
|
||||
}
|
||||
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.
|
||||
func (c *Controller) ServeJSON(encoding ...bool) {
|
||||
func (c *Controller) ServeJSON(encoding ...bool) error {
|
||||
var (
|
||||
hasIndent = BConfig.RunMode != PROD
|
||||
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.
|
||||
func (c *Controller) ServeJSONP() {
|
||||
func (c *Controller) ServeJSONP() error {
|
||||
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.
|
||||
func (c *Controller) ServeXML() {
|
||||
func (c *Controller) ServeXML() error {
|
||||
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.
|
||||
func (c *Controller) ServeYAML() {
|
||||
c.Ctx.Output.YAML(c.Data["yaml"])
|
||||
func (c *Controller) ServeYAML() error {
|
||||
return c.Ctx.Output.YAML(c.Data["yaml"])
|
||||
}
|
||||
|
||||
// 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
|
||||
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.
|
||||
func (c *Controller) Input() url.Values {
|
||||
func (c *Controller) Input() (url.Values, error) {
|
||||
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.
|
||||
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
|
||||
@ -438,7 +449,7 @@ func (c *Controller) GetStrings(key string, def ...[]string) []string {
|
||||
defv = def[0]
|
||||
}
|
||||
|
||||
if f := c.Input(); f == nil {
|
||||
if f, err := c.Input(); f == nil || err != nil {
|
||||
return defv
|
||||
} else if vs := f[key]; len(vs) > 0 {
|
||||
return vs
|
||||
@ -618,11 +629,11 @@ func (c *Controller) StartSession() session.Store {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
c.StartSession()
|
||||
}
|
||||
c.CruSession.Set(nil, name, value)
|
||||
return c.CruSession.Set(context2.Background(), name, value)
|
||||
}
|
||||
|
||||
// GetSession gets value from session.
|
||||
@ -630,32 +641,38 @@ func (c *Controller) GetSession(name interface{}) interface{} {
|
||||
if c.CruSession == nil {
|
||||
c.StartSession()
|
||||
}
|
||||
return c.CruSession.Get(nil, name)
|
||||
return c.CruSession.Get(context2.Background(), name)
|
||||
}
|
||||
|
||||
// DelSession removes value from session.
|
||||
func (c *Controller) DelSession(name interface{}) {
|
||||
func (c *Controller) DelSession(name interface{}) error {
|
||||
if c.CruSession == nil {
|
||||
c.StartSession()
|
||||
}
|
||||
c.CruSession.Delete(nil, name)
|
||||
return c.CruSession.Delete(context2.Background(), name)
|
||||
}
|
||||
|
||||
// SessionRegenerateID regenerates session id for this session.
|
||||
// the session data have no changes.
|
||||
func (c *Controller) SessionRegenerateID() {
|
||||
func (c *Controller) SessionRegenerateID() error {
|
||||
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
|
||||
return err
|
||||
}
|
||||
|
||||
// DestroySession cleans session data and session cookie.
|
||||
func (c *Controller) DestroySession() {
|
||||
c.Ctx.Input.CruSession.Flush(nil)
|
||||
func (c *Controller) DestroySession() error {
|
||||
err := c.Ctx.Input.CruSession.Flush(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Ctx.Input.CruSession = nil
|
||||
GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsAjax returns this request is ajax or not.
|
||||
|
@ -273,7 +273,6 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) {
|
||||
for _, f := range a.Filters {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -298,15 +298,21 @@ func (manager *Manager) GC() {
|
||||
}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var session Store
|
||||
|
||||
cookie, err := r.Cookie(manager.config.CookieName)
|
||||
if err != nil || cookie.Value == "" {
|
||||
//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,
|
||||
Value: url.QueryEscape(sid),
|
||||
Path: "/",
|
||||
@ -315,8 +321,16 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
|
||||
Domain: manager.config.Domain,
|
||||
}
|
||||
} else {
|
||||
oldsid, _ := url.QueryUnescape(cookie.Value)
|
||||
session, _ = manager.provider.SessionRegenerate(nil, oldsid, sid)
|
||||
oldsid, err := url.QueryUnescape(cookie.Value)
|
||||
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.HttpOnly = true
|
||||
cookie.Path = "/"
|
||||
@ -335,7 +349,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
|
||||
w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
|
||||
}
|
||||
|
||||
return
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// GetActiveSession Get all active sessions count number.
|
||||
|
@ -21,76 +21,109 @@ import (
|
||||
"github.com/astaxie/beego/server/web/context"
|
||||
)
|
||||
|
||||
type testinfo struct {
|
||||
url string
|
||||
requesturl string
|
||||
params map[string]string
|
||||
type testInfo struct {
|
||||
pattern string
|
||||
requestUrl 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() {
|
||||
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"}})
|
||||
routers = make([]testInfo, 0)
|
||||
//match example
|
||||
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic", nil))
|
||||
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}))
|
||||
routers = append(routers, matchTestInfo("/topic/:id/?:auth", "/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, matchTestInfo("/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}))
|
||||
routers = append(routers, matchTestInfo("/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}))
|
||||
routers = append(routers, matchTestInfo("/:id", "/123", map[string]string{":id": "123"}))
|
||||
routers = append(routers, matchTestInfo("/hello/?:id", "/hello", map[string]string{":id": ""}))
|
||||
routers = append(routers, matchTestInfo("/", "/", nil))
|
||||
routers = append(routers, matchTestInfo("/customer/login", "/customer/login", nil))
|
||||
routers = append(routers, matchTestInfo("/customer/login", "/customer/login.json", map[string]string{":ext": "json"}))
|
||||
routers = append(routers, matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}))
|
||||
routers = append(routers, matchTestInfo("/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}))
|
||||
routers = append(routers, matchTestInfo("/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}))
|
||||
routers = append(routers, matchTestInfo("/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}))
|
||||
routers = append(routers, matchTestInfo("/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}))
|
||||
routers = append(routers, matchTestInfo("/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}))
|
||||
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"}))
|
||||
routers = append(routers, matchTestInfo("/*.*", "/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, matchTestInfo("/: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, matchTestInfo("/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(a)", map[string]string{":id": "123"}))
|
||||
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", 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, 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, matchTestInfo("/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}))
|
||||
routers = append(routers, matchTestInfo("/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}))
|
||||
routers = append(routers, matchTestInfo("/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}))
|
||||
routers = append(routers, matchTestInfo("/v1/shop/:id([0-9]+)", "/v1/shop//123", 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, matchTestInfo("/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", 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, 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, 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, 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, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}))
|
||||
routers = append(routers, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}))
|
||||
|
||||
//not match example
|
||||
|
||||
// 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) {
|
||||
for _, r := range routers {
|
||||
shouldMatch := r.shouldMatchOrNot
|
||||
|
||||
tr := NewTree()
|
||||
tr.AddRouter(r.url, "astaxie")
|
||||
tr.AddRouter(r.pattern, "astaxie")
|
||||
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" {
|
||||
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 {
|
||||
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)
|
||||
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 != "" {
|
||||
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/ ")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitPath(t *testing.T) {
|
||||
a := splitPath("")
|
||||
if len(a) != 0 {
|
||||
@ -292,6 +324,7 @@ func TestSplitSegment(t *testing.T) {
|
||||
":id([0-9]+)": {true, []string{":id"}, `([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`},
|
||||
"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)\)`},
|
||||
|
@ -452,9 +452,11 @@ func (m *taskManager) StartTask() {
|
||||
|
||||
func (m *taskManager) run() {
|
||||
now := time.Now().Local()
|
||||
m.taskLock.Lock()
|
||||
for _, t := range m.adminTaskList {
|
||||
t.SetNext(nil, now)
|
||||
}
|
||||
m.taskLock.Unlock()
|
||||
|
||||
for {
|
||||
// we only use RLock here because NewMapSorter copy the reference, do not change any thing
|
||||
|
Loading…
Reference in New Issue
Block a user