mirror of
https://github.com/astaxie/beego.git
synced 2025-07-11 13:21:01 +00:00
Compare commits
52 Commits
v2.0.0-bet
...
develop
Author | SHA1 | Date | |
---|---|---|---|
093f976365 | |||
198b9cce5f | |||
1452a75de4 | |||
728296a7ae | |||
e2fc8b93f2 | |||
86620210f8 | |||
64d7d36794 | |||
88bd9f594a | |||
2e1c50253c | |||
a5842e9de2 | |||
40f7a56bf5 | |||
aec5f4b3a5 | |||
9eda707297 | |||
b92edb6587 | |||
53688ce32f | |||
debd68cbe4 | |||
b6d6571e99 | |||
db785479ab | |||
54ab211f00 | |||
c034d3767a | |||
99a47e7644 | |||
59ca0d063f | |||
aa05b66ca1 | |||
8d7f48ea75 | |||
fd48c62873 | |||
7ee5c8e553 | |||
4afa9d2d25 | |||
fad897346f | |||
650fde66aa | |||
359ad7a889 | |||
00ed1c3733 | |||
0958174bc8 | |||
c6282e7b27 | |||
6225f0c1e9 | |||
05d8e293f7 | |||
663e5d728c | |||
26bc9e7264 | |||
0a852912b4 | |||
647e21b0c4 | |||
a00b54d8f6 | |||
8f16098508 | |||
aad80ba4fa | |||
8f3fd317da | |||
c5c03815f3 | |||
0b3bcbd3ec | |||
49d763dc6c | |||
aa2c0ca108 | |||
b3474b20b9 | |||
2a6fadb9ae | |||
e284b0ddae | |||
8ef8fd2606 | |||
0cd80525e7 |
262
README.md
262
README.md
@ -1,42 +1,57 @@
|
|||||||
# Beego [](https://travis-ci.org/astaxie/beego) [](http://godoc.org/github.com/astaxie/beego) [](http://golangfoundation.org) [](https://goreportcard.com/report/github.com/astaxie/beego)
|
# Beego [](https://travis-ci.org/astaxie/beego) [](http://godoc.org/github.com/astaxie/beego) [](http://golangfoundation.org) [](https://goreportcard.com/report/github.com/astaxie/beego)
|
||||||
|
|
||||||
|
Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend
|
||||||
|
services.
|
||||||
|
|
||||||
beego is used for rapid development of RESTful APIs, web apps and backend services in Go.
|
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct
|
||||||
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding.
|
embedding.
|
||||||
|
|
||||||
###### More info at [beego.me](http://beego.me).
|

|
||||||
|
|
||||||
|
Beego is compos of four parts:
|
||||||
|
1. Base modules: including log module, config module, governor module;
|
||||||
|
2. Task: is used for running timed tasks or periodic tasks;
|
||||||
|
3. Client: including ORM module, httplib module, cache module;
|
||||||
|
4. Server: including web module. We will support gRPC in the future;
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
###### Please see [Documentation](http://beego.me/docs) for more.
|
[Officail website](http://beego.me)
|
||||||
|
|
||||||
|
[Example](https://github.com/beego-dev/beego-example)
|
||||||
|
|
||||||
|
> If you could not open official website, go to [beedoc](https://github.com/beego/beedoc)
|
||||||
|
|
||||||
###### [beego-example](https://github.com/beego-dev/beego-example)
|
|
||||||
|
|
||||||
### Web Application
|
### Web Application
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
#### Create `hello` directory, cd `hello` directory
|
#### Create `hello` directory, cd `hello` directory
|
||||||
|
|
||||||
mkdir hello
|
mkdir hello
|
||||||
cd hello
|
cd hello
|
||||||
|
|
||||||
#### Init module
|
#### Init module
|
||||||
|
|
||||||
go mod init
|
go mod init
|
||||||
|
|
||||||
#### Download and install
|
#### Download and install
|
||||||
|
|
||||||
go get github.com/astaxie/beego
|
go get github.com/astaxie/beego@v2.0.0
|
||||||
|
|
||||||
#### Create file `hello.go`
|
#### Create file `hello.go`
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/astaxie/beego/server/web"
|
import "github.com/astaxie/beego/server/web"
|
||||||
|
|
||||||
func main(){
|
func main() {
|
||||||
web.Run()
|
web.Run()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Build and run
|
#### Build and run
|
||||||
|
|
||||||
go build hello.go
|
go build hello.go
|
||||||
@ -46,227 +61,36 @@ func main(){
|
|||||||
|
|
||||||
Congratulations! You've just built your first **beego** app.
|
Congratulations! You've just built your first **beego** app.
|
||||||
|
|
||||||
### Using ORM module
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/astaxie/beego/client/orm"
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
)
|
|
||||||
|
|
||||||
// User -
|
|
||||||
type User struct {
|
|
||||||
ID int `orm:"column(id)"`
|
|
||||||
Name string `orm:"column(name)"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// need to register models in init
|
|
||||||
orm.RegisterModel(new(User))
|
|
||||||
|
|
||||||
// need to register db driver
|
|
||||||
orm.RegisterDriver("mysql", orm.DRMySQL)
|
|
||||||
|
|
||||||
// need to register default database
|
|
||||||
orm.RegisterDataBase("default", "mysql", "beego:test@tcp(192.168.0.105:13306)/orm_test?charset=utf8")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// automatically build table
|
|
||||||
orm.RunSyncdb("default", false, true)
|
|
||||||
|
|
||||||
// create orm object, and it will use `default` database
|
|
||||||
o := orm.NewOrm()
|
|
||||||
|
|
||||||
// data
|
|
||||||
user := new(User)
|
|
||||||
user.Name = "mike"
|
|
||||||
|
|
||||||
// insert data
|
|
||||||
id, err := o.Insert(user)
|
|
||||||
if err != nil {
|
|
||||||
logs.Info(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using httplib as http client
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/astaxie/beego/client/httplib"
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get, more methods please read docs
|
|
||||||
req := httplib.Get("http://beego.me/")
|
|
||||||
str, err := req.String()
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err)
|
|
||||||
}
|
|
||||||
logs.Info(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using config module
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/config"
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ConfigFile = "./app.conf"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cfg, err := config.NewConfig("ini", ConfigFile)
|
|
||||||
if err != nil {
|
|
||||||
logs.Critical("An error occurred:", err)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
res, _ := cfg.String(context.Background(), "name")
|
|
||||||
logs.Info("load config name is", res)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### Using logs module
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
err := logs.SetLogger(logs.AdapterFile, `{"filename":"project.log","level":7,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10,"color":true}`)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
logs.Info("hello beego")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### Using timed task
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
"github.com/astaxie/beego/task"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// create a task
|
|
||||||
tk1 := task.NewTask("tk1", "0/3 * * * * *", func(ctx context.Context) error { logs.Info("tk1"); return nil })
|
|
||||||
|
|
||||||
// check task
|
|
||||||
err := tk1.Run(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add task to global todolist
|
|
||||||
task.AddTask("tk1", tk1)
|
|
||||||
|
|
||||||
// start tasks
|
|
||||||
task.StartTask()
|
|
||||||
|
|
||||||
// wait 12 second
|
|
||||||
time.Sleep(12 * time.Second)
|
|
||||||
defer task.StopTask()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using cache module
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/client/cache"
|
|
||||||
|
|
||||||
// don't forget this
|
|
||||||
_ "github.com/astaxie/beego/client/cache/redis"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/logs"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// create cache
|
|
||||||
bm, err := cache.NewCache("redis", `{"key":"default", "conn":":6379", "password":"123456", "dbNum":"0"}`)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// put
|
|
||||||
isPut := bm.Put(context.Background(), "astaxie", 1, time.Second*10)
|
|
||||||
logs.Info(isPut)
|
|
||||||
|
|
||||||
isPut = bm.Put(context.Background(), "hello", "world", time.Second*10)
|
|
||||||
logs.Info(isPut)
|
|
||||||
|
|
||||||
// get
|
|
||||||
result, _ := bm.Get(context.Background(),"astaxie")
|
|
||||||
logs.Info(string(result.([]byte)))
|
|
||||||
|
|
||||||
multiResult, _ := bm.GetMulti(context.Background(), []string{"astaxie", "hello"})
|
|
||||||
for i := range multiResult {
|
|
||||||
logs.Info(string(multiResult[i].([]byte)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// isExist
|
|
||||||
isExist, _ := bm.IsExist(context.Background(), "astaxie")
|
|
||||||
logs.Info(isExist)
|
|
||||||
|
|
||||||
// delete
|
|
||||||
isDelete := bm.Delete(context.Background(), "astaxie")
|
|
||||||
logs.Info(isDelete)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* RESTful support
|
* RESTful support
|
||||||
* MVC architecture
|
* [MVC architecture](https://github.com/beego/beedoc/tree/master/en-US/mvc)
|
||||||
* Modularity
|
* Modularity
|
||||||
* Auto API documents
|
* [Auto API documents](https://github.com/beego/beedoc/blob/master/en-US/advantage/docs.md)
|
||||||
* Annotation router
|
* [Annotation router](https://github.com/beego/beedoc/blob/master/en-US/mvc/controller/router.md)
|
||||||
* Namespace
|
* [Namespace](https://github.com/beego/beedoc/blob/master/en-US/mvc/controller/router.md#namespace)
|
||||||
* Powerful development tools
|
* [Powerful development tools](https://github.com/beego/bee)
|
||||||
* Full stack for Web & API
|
* Full stack for Web & API
|
||||||
|
|
||||||
## Documentation
|
## Modules
|
||||||
|
* [orm](https://github.com/beego/beedoc/tree/master/en-US/mvc/model)
|
||||||
* [English](http://beego.me/docs/intro/)
|
* [session](https://github.com/beego/beedoc/blob/master/en-US/module/session.md)
|
||||||
* [中文文档](http://beego.me/docs/intro/)
|
* [logs](https://github.com/beego/beedoc/blob/master/en-US/module/logs.md)
|
||||||
* [Русский](http://beego.me/docs/intro/)
|
* [config](https://github.com/beego/beedoc/blob/master/en-US/module/config.md)
|
||||||
|
* [cache](https://github.com/beego/beedoc/blob/master/en-US/module/cache.md)
|
||||||
|
* [context](https://github.com/beego/beedoc/blob/master/en-US/module/context.md)
|
||||||
|
* [governor](https://github.com/beego/beedoc/blob/master/en-US/module/governor.md)
|
||||||
|
* [httplib](https://github.com/beego/beedoc/blob/master/en-US/module/httplib.md)
|
||||||
|
* [task](https://github.com/beego/beedoc/blob/master/en-US/module/task.md)
|
||||||
|
* [i18n](https://github.com/beego/beedoc/blob/master/en-US/module/i18n.md)
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
* [http://beego.me/community](http://beego.me/community)
|
* [http://beego.me/community](http://beego.me/community)
|
||||||
* Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited from [here](https://github.com/beego/beedoc/issues/232)
|
* Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited
|
||||||
|
from [here](https://github.com/beego/beedoc/issues/232)
|
||||||
* QQ Group Group ID:523992905
|
* QQ Group Group ID:523992905
|
||||||
|
* [Contribution Guide](https://github.com/beego/beedoc/blob/master/en-US/intro/contributing.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ package adapter
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/astaxie/beego/core/governor"
|
_ "github.com/astaxie/beego/core/admin"
|
||||||
"github.com/astaxie/beego/server/web"
|
"github.com/astaxie/beego/server/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -31,19 +31,19 @@
|
|||||||
package toolbox
|
package toolbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/core/governor"
|
"github.com/astaxie/beego/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AdminCheckList holds health checker map
|
// AdminCheckList holds health checker map
|
||||||
// Deprecated using governor.AdminCheckList
|
// Deprecated using admin.AdminCheckList
|
||||||
var AdminCheckList map[string]HealthChecker
|
var AdminCheckList map[string]HealthChecker
|
||||||
|
|
||||||
// HealthChecker health checker interface
|
// HealthChecker health checker interface
|
||||||
type HealthChecker governor.HealthChecker
|
type HealthChecker admin.HealthChecker
|
||||||
|
|
||||||
// AddHealthCheck add health checker with name string
|
// AddHealthCheck add health checker with name string
|
||||||
func AddHealthCheck(name string, hc HealthChecker) {
|
func AddHealthCheck(name string, hc HealthChecker) {
|
||||||
governor.AddHealthCheck(name, hc)
|
admin.AddHealthCheck(name, hc)
|
||||||
AdminCheckList[name] = hc
|
AdminCheckList[name] = hc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/governor"
|
"github.com/astaxie/beego/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var startTime = time.Now()
|
var startTime = time.Now()
|
||||||
@ -31,20 +31,20 @@ func init() {
|
|||||||
|
|
||||||
// ProcessInput parse input command string
|
// ProcessInput parse input command string
|
||||||
func ProcessInput(input string, w io.Writer) {
|
func ProcessInput(input string, w io.Writer) {
|
||||||
governor.ProcessInput(input, w)
|
admin.ProcessInput(input, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemProf record memory profile in pprof
|
// MemProf record memory profile in pprof
|
||||||
func MemProf(w io.Writer) {
|
func MemProf(w io.Writer) {
|
||||||
governor.MemProf(w)
|
admin.MemProf(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCPUProfile start cpu profile monitor
|
// GetCPUProfile start cpu profile monitor
|
||||||
func GetCPUProfile(w io.Writer) {
|
func GetCPUProfile(w io.Writer) {
|
||||||
governor.GetCPUProfile(w)
|
admin.GetCPUProfile(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintGCSummary print gc information to io.Writer
|
// PrintGCSummary print gc information to io.Writer
|
||||||
func PrintGCSummary(w io.Writer) {
|
func PrintGCSummary(w io.Writer) {
|
||||||
governor.PrintGCSummary(w)
|
admin.PrintGCSummary(w)
|
||||||
}
|
}
|
||||||
|
@ -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/ ")
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,5 +28,5 @@ var (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// VERSION represent beego web framework version.
|
// VERSION represent beego web framework version.
|
||||||
VERSION = "2.0.0-alpha"
|
VERSION = "2.0.0"
|
||||||
)
|
)
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
99
client/cache/file.go
vendored
99
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,17 +144,22 @@ 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)
|
|
||||||
if err != nil {
|
|
||||||
rc = append(rc, err)
|
|
||||||
} else {
|
|
||||||
rc = append(rc, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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.
|
// Put value into file cache.
|
||||||
@ -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,19 +69,31 @@ 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 {
|
return rv, err
|
||||||
rv = append(rv, v.Value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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.
|
||||||
|
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")
|
||||||
|
24
client/cache/memory.go
vendored
24
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,22 +70,28 @@ 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
|
||||||
}
|
}
|
||||||
return rc, nil
|
|
||||||
|
if len(keysErr) == 0 {
|
||||||
|
return rc, nil
|
||||||
|
}
|
||||||
|
return rc, errors.New(strings.Join(keysErr, "; "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put puts cache into memory.
|
// 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")
|
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")
|
||||||
|
33
client/cache/ssdb/ssdb.go
vendored
33
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
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
|
||||||
|
@ -67,4 +67,4 @@ func TestSnakeStringWithAcronym(t *testing.T) {
|
|||||||
t.Error("Unit Test Fail:", v, res, answer[v])
|
t.Error("Unit Test Fail:", v, res, answer[v])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package governor
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package governor healthcheck
|
// Package admin healthcheck
|
||||||
//
|
//
|
||||||
// type DatabaseCheck struct {
|
// type DatabaseCheck struct {
|
||||||
// }
|
// }
|
||||||
@ -28,7 +28,7 @@
|
|||||||
// AddHealthCheck("database",&DatabaseCheck{})
|
// AddHealthCheck("database",&DatabaseCheck{})
|
||||||
//
|
//
|
||||||
// more docs: http://beego.me/docs/module/toolbox.md
|
// more docs: http://beego.me/docs/module/toolbox.md
|
||||||
package governor
|
package admin
|
||||||
|
|
||||||
// AdminCheckList holds health checker map
|
// AdminCheckList holds health checker map
|
||||||
var AdminCheckList map[string]HealthChecker
|
var AdminCheckList map[string]HealthChecker
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package governor
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package governor
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
@ -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)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/governor"
|
"github.com/astaxie/beego/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type adminController struct {
|
type adminController struct {
|
||||||
@ -51,7 +51,7 @@ func (a *adminController) ProfIndex() {
|
|||||||
data = make(map[interface{}]interface{})
|
data = make(map[interface{}]interface{})
|
||||||
result bytes.Buffer
|
result bytes.Buffer
|
||||||
)
|
)
|
||||||
governor.ProcessInput(command, &result)
|
admin.ProcessInput(command, &result)
|
||||||
data["Content"] = template.HTMLEscapeString(result.String())
|
data["Content"] = template.HTMLEscapeString(result.String())
|
||||||
|
|
||||||
if format == "json" && command == "gc summary" {
|
if format == "json" && command == "gc summary" {
|
||||||
@ -88,7 +88,7 @@ func (a *adminController) TaskStatus() {
|
|||||||
req.ParseForm()
|
req.ParseForm()
|
||||||
taskname := req.Form.Get("taskname")
|
taskname := req.Form.Get("taskname")
|
||||||
if taskname != "" {
|
if taskname != "" {
|
||||||
cmd := governor.GetCommand("task", "run")
|
cmd := admin.GetCommand("task", "run")
|
||||||
res := cmd.Execute(taskname)
|
res := cmd.Execute(taskname)
|
||||||
if res.IsSuccess() {
|
if res.IsSuccess() {
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ func (a *adminController) TaskStatus() {
|
|||||||
|
|
||||||
// List Tasks
|
// List Tasks
|
||||||
content := make(M)
|
content := make(M)
|
||||||
resultList := governor.GetCommand("task", "list").Execute().Content.([][]string)
|
resultList := admin.GetCommand("task", "list").Execute().Content.([][]string)
|
||||||
var fields = []string{
|
var fields = []string{
|
||||||
"Task Name",
|
"Task Name",
|
||||||
"Task Spec",
|
"Task Spec",
|
||||||
@ -141,7 +141,7 @@ func heathCheck(rw http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
for name, h := range governor.AdminCheckList {
|
for name, h := range admin.AdminCheckList {
|
||||||
if err := h.Check(); err != nil {
|
if err := h.Check(); err != nil {
|
||||||
result = []string{
|
result = []string{
|
||||||
"error",
|
"error",
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/governor"
|
"github.com/astaxie/beego/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SampleDatabaseCheck struct {
|
type SampleDatabaseCheck struct {
|
||||||
@ -126,8 +126,8 @@ func TestWriteJSON(t *testing.T) {
|
|||||||
func TestHealthCheckHandlerDefault(t *testing.T) {
|
func TestHealthCheckHandlerDefault(t *testing.T) {
|
||||||
endpointPath := "/healthcheck"
|
endpointPath := "/healthcheck"
|
||||||
|
|
||||||
governor.AddHealthCheck("database", &SampleDatabaseCheck{})
|
admin.AddHealthCheck("database", &SampleDatabaseCheck{})
|
||||||
governor.AddHealthCheck("cache", &SampleCacheCheck{})
|
admin.AddHealthCheck("cache", &SampleCacheCheck{})
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", endpointPath, nil)
|
req, err := http.NewRequest("GET", endpointPath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -187,8 +187,8 @@ func TestBuildHealthCheckResponseList(t *testing.T) {
|
|||||||
|
|
||||||
func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
|
func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
|
||||||
|
|
||||||
governor.AddHealthCheck("database", &SampleDatabaseCheck{})
|
admin.AddHealthCheck("database", &SampleDatabaseCheck{})
|
||||||
governor.AddHealthCheck("cache", &SampleCacheCheck{})
|
admin.AddHealthCheck("cache", &SampleCacheCheck{})
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/healthcheck?json=true", nil)
|
req, err := http.NewRequest("GET", "/healthcheck?json=true", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,7 +21,7 @@ var indexTpl = `
|
|||||||
For detail usage please check our document:
|
For detail usage please check our document:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a target="_blank" href="http://beego.me/docs/module/governor.md">Toolbox</a>
|
<a target="_blank" href="http://beego.me/docs/module/admin.md">Toolbox</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<a target="_blank" href="http://beego.me/docs/advantage/monitor.md">Live Monitor</a>
|
<a target="_blank" href="http://beego.me/docs/advantage/monitor.md">Live Monitor</a>
|
||||||
|
@ -149,7 +149,8 @@ func (ctx *Context) XSRFToken(key string, expire int64) string {
|
|||||||
token, ok := ctx.GetSecureCookie(key, "_xsrf")
|
token, ok := ctx.GetSecureCookie(key, "_xsrf")
|
||||||
if !ok {
|
if !ok {
|
||||||
token = string(utils.RandomCreateBytes(32))
|
token = string(utils.RandomCreateBytes(32))
|
||||||
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "", true, true)
|
// TODO make it configurable
|
||||||
|
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "")
|
||||||
}
|
}
|
||||||
ctx._xsrfToken = token
|
ctx._xsrfToken = token
|
||||||
}
|
}
|
||||||
|
@ -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,13 +251,16 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderBytes returns the bytes of rendered template string. Do not send out response.
|
// RenderBytes returns the bytes of rendered template string. Do not send out response.
|
||||||
func (c *Controller) RenderBytes() ([]byte, error) {
|
func (c *Controller) RenderBytes() ([]byte, error) {
|
||||||
buf, err := c.renderTemplate()
|
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 != "" {
|
if err == nil && c.Layout != "" {
|
||||||
c.Data["LayoutContent"] = template.HTML(buf.String())
|
c.Data["LayoutContent"] = template.HTML(buf.String())
|
||||||
|
|
||||||
@ -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)\)`},
|
||||||
@ -303,4 +336,4 @@ func TestSplitSegment(t *testing.T) {
|
|||||||
t.Fatalf("%s should return %t,%s,%q, got %t,%s,%q", pattern, v.isReg, v.params, v.regStr, b, w, r)
|
t.Fatalf("%s should return %t,%s,%q, got %t,%s,%q", pattern, v.isReg, v.params, v.regStr, b, w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,13 +21,13 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/astaxie/beego/core/governor"
|
"github.com/astaxie/beego/core/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type listTaskCommand struct {
|
type listTaskCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listTaskCommand) Execute(params ...interface{}) *governor.Result {
|
func (l *listTaskCommand) Execute(params ...interface{}) *admin.Result {
|
||||||
resultList := make([][]string, 0, len(globalTaskManager.adminTaskList))
|
resultList := make([][]string, 0, len(globalTaskManager.adminTaskList))
|
||||||
for tname, tk := range globalTaskManager.adminTaskList {
|
for tname, tk := range globalTaskManager.adminTaskList {
|
||||||
result := []string{
|
result := []string{
|
||||||
@ -39,7 +39,7 @@ func (l *listTaskCommand) Execute(params ...interface{}) *governor.Result {
|
|||||||
resultList = append(resultList, result)
|
resultList = append(resultList, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 200,
|
Status: 200,
|
||||||
Content: resultList,
|
Content: resultList,
|
||||||
}
|
}
|
||||||
@ -48,9 +48,9 @@ func (l *listTaskCommand) Execute(params ...interface{}) *governor.Result {
|
|||||||
type runTaskCommand struct {
|
type runTaskCommand struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
|
func (r *runTaskCommand) Execute(params ...interface{}) *admin.Result {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 400,
|
Status: 400,
|
||||||
Error: errors.New("task name not passed"),
|
Error: errors.New("task name not passed"),
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
|
|||||||
tn, ok := params[0].(string)
|
tn, ok := params[0].(string)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 400,
|
Status: 400,
|
||||||
Error: errors.New("parameter is invalid"),
|
Error: errors.New("parameter is invalid"),
|
||||||
}
|
}
|
||||||
@ -68,17 +68,17 @@ func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
|
|||||||
if t, ok := globalTaskManager.adminTaskList[tn]; ok {
|
if t, ok := globalTaskManager.adminTaskList[tn]; ok {
|
||||||
err := t.Run(context.Background())
|
err := t.Run(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 500,
|
Status: 500,
|
||||||
Error: err,
|
Error: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 200,
|
Status: 200,
|
||||||
Content: t.GetStatus(context.Background()),
|
Content: t.GetStatus(context.Background()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return &governor.Result{
|
return &admin.Result{
|
||||||
Status: 400,
|
Status: 400,
|
||||||
Error: errors.New(fmt.Sprintf("task with name %s not found", tn)),
|
Error: errors.New(fmt.Sprintf("task with name %s not found", tn)),
|
||||||
}
|
}
|
||||||
@ -87,6 +87,6 @@ func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func registerCommands() {
|
func registerCommands() {
|
||||||
governor.RegisterCommand("task", "list", &listTaskCommand{})
|
admin.RegisterCommand("task", "list", &listTaskCommand{})
|
||||||
governor.RegisterCommand("task", "run", &runTaskCommand{})
|
admin.RegisterCommand("task", "run", &runTaskCommand{})
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user