1
0
mirror of https://github.com/astaxie/beego.git synced 2025-07-11 13:51:02 +00:00

77 Commits

Author SHA1 Message Date
7452151bee Merge pull request #2611 from astaxie/develop
1.8.2
2017-05-01 13:01:59 +08:00
e76423e6dc revert #2518, fix #2605 2017-04-30 23:59:38 +08:00
947980b5eb beego 1.8.2 2017-04-30 23:43:46 +08:00
44bdf1df63 ignore NilErr 2017-04-30 23:38:48 +08:00
79b66ef053 fix the beego ORM test 2017-04-30 22:55:39 +08:00
a91e2e9950 add golint check and fix all golints 2017-04-30 22:41:23 +08:00
ea3d0690cf golint 2017-04-29 09:13:28 +08:00
1c32c011a1 fix misspell 2017-04-28 23:37:40 +08:00
64b475d7d6 fix ReadOrCreate test case 2017-04-28 22:58:17 +08:00
aa8f7bc146 fix ineffectual 2017-04-28 22:36:28 +08:00
3e29078f68 add check ineffect and gofmt 2017-04-28 21:38:08 +08:00
f311ae9ebe feature: Export function printTree (#2597)
This exports PrintTree function which allow to set Role Based Access Control, Create our own requests statistics...etc
2017-04-25 18:12:03 +02:00
522b3a4a70 Merge pull request #2596 from astaxie/develop
beego 1.8.1
2017-04-25 22:51:23 +08:00
cd67f13bf9 add template layout test #2481 2017-04-25 22:21:27 +08:00
0f554d9b1a update travis to latest go version 2017-04-25 22:21:08 +08:00
3742d1178c httplib support delete params fix #2593 2017-04-25 20:42:43 +08:00
d03285a0ee Merge pull request #2555 from Liaodd/master
Update ini.go: change the key to lowercase when set a new key for ini configer
2017-04-24 22:37:25 +08:00
e810f2e930 add more oracle alias 2017-04-24 21:36:07 +08:00
41aac79ac0 Merge pull request #2590 from amrfaissal/fix-2587
Fix warnings raised by gometalinter and gosimple
2017-04-24 21:14:00 +08:00
52f916a28a support Go1.8 default GOPATH 2017-04-24 21:10:03 +08:00
bf6bd6b292 Fixes #2587
Fixes warnings and errors raised by gometalinter and gosimple.
2017-04-23 19:19:05 +02:00
3bb4ca5adc Merge pull request #2583 from OlegFX/develop
Fixed InsertOrUpdate bug
2017-04-22 11:19:15 +08:00
712df81c99 Fixed InsertOrUpdate bug 2017-04-21 19:57:04 +03:00
3d7ef599cc Merge pull request #2 from astaxie/develop
Update
2017-04-21 19:50:33 +03:00
453691728a gofmt simplify 2017-04-20 10:56:09 +08:00
e7e3ca77ad Merge pull request #2491 from chendx79/master
Fix routing bug for splat matching
2017-04-19 21:20:30 +08:00
d3f3956def Merge pull request #2574 from extrlibs/master
Fix the following template reference
2017-04-19 21:18:26 +08:00
7206214105 Merge pull request #2575 from PaulChen2016/master
Beego 运行过程中动态增减定时任务时,now的时间需要更新,否则等待时间会不正确
2017-04-19 21:17:38 +08:00
b08ace7532 Merge pull request #2577 from ggicci/develop
Fix ini parsing error for multiple users on one machine.
2017-04-19 20:17:45 +08:00
d1a2583972 Fix ini parsing error for multiple users on one machine.
If there were multiple users working on one machine, it's common that
"/tmp/beego" will be owned by one of them, and the others won't be able
to access to it. So, it's better to add an "id-like" postfix to the
temporary directory.
2017-04-19 19:50:11 +08:00
0cb8de4218 Beego 运行过程中动态增减定时任务时,now的时间需要更新,否则等待时间会不正确
beego 启动时,执行toolbox.StartTask()
运行过程中,动态添加定时任务(这个是now时间已经不是starttask的时间了,需要刷新)     
     case <-changed:
			now = time.Now().Local()
			continue
2017-04-19 16:22:58 +08:00
0cd31a247f fix Template nesting problem 2017-04-19 07:47:05 +08:00
405c170d45 Merge pull request #2556 from zjjott/master
fix: log mode should be 0440 should not be 440
2017-04-10 21:14:34 +08:00
932019770d fix: log mode 0440 should not be 440 2017-04-10 17:37:55 +08:00
d5c03f5b8f Update ini.go
change the key to lowercase when set a new key for ini configer
2017-04-10 11:30:23 +08:00
3d20c0b8f4 Merge pull request #2543 from Bobochka/fix_route_hander_docs
Fix example for Hander func
2017-04-07 23:04:38 +08:00
a4fb4c6a03 Merge pull request #2547 from TrueFurby/patch-1
Update README.md
2017-04-03 20:25:41 +02:00
a9941b6edc Merge branch 'develop' into patch-1 2017-04-02 13:46:06 +02:00
6a32b048bd Update README.md 2017-04-02 11:04:08 +02:00
fb04d3cff1 Fix example for Hander func 2017-03-30 12:53:12 +03:00
5c7673e73d update to 1.8.1 2017-03-29 10:22:27 +08:00
54b05377d9 Merge pull request #2466 from gouyang/gouyang/develop
Parse form time by its length
2017-03-29 10:01:03 +08:00
f49f3f92ec Merge pull request #2533 from cnxh/redis-session-poolsize
redis poolsize could set to zero
2017-03-29 10:00:28 +08:00
b18b94f03b Merge pull request #2539 from astaxie/revert-2421-develop
Revert "close mysql connection"
2017-03-29 09:57:54 +08:00
bf469f0b55 Revert "close mysql connection" 2017-03-29 09:57:18 +08:00
c12709dbc9 Merge pull request #2536 from ChristophPech/master
Fix for IndexExists in SQLite driver
2017-03-29 09:53:55 +08:00
2808a13f07 Fix for IndexExists in SQLite driver, they added the "origin" and "partial" columns to the index_list pragma.
see: https://www.sqlite.org/src/info/2743846cdba572f6
2017-03-28 12:38:27 +02:00
a8d48aa5ea Merge pull request #2535 from ketanhwr/patch-1
Update README.md
2017-03-28 10:49:52 +02:00
fdb2660a2a Update README.md 2017-03-28 11:29:20 +05:30
7c3a997735 poolsize could set to zero
sometimes we may want disable the redis pool
2017-03-27 23:34:58 +08:00
1760f0ceca Merge pull request #2532 from vbalien/patch-1
Fix markdown formatting
2017-03-27 13:34:19 +08:00
c387aeeb36 fix markdown formatting 2017-03-27 14:30:42 +09:00
83d4385f1f Support time.RFC3339
Signed-off-by: Guohua Ouyang <guohuaouyang@gmail.com>
2017-03-25 07:52:43 +08:00
ae0a75c464 console debug use diffrent color 2017-03-21 23:55:40 +08:00
a05e5a7c09 Merge branches 'master' and 'develop' of https://github.com/astaxie/beego into develop 2017-03-21 23:47:32 +08:00
75ca7b77b6 Merge pull request #2518 from sicojuy/develop
Fix set cookie bug, zero max age is not valid.
2017-03-21 09:44:37 +08:00
b0e2012a17 Fix set cookie bug, zero max age is not valid. 2017-03-21 09:15:30 +08:00
12dff072fa Merge pull request #2509 from sergeylanzman/add-gosimple
add go simple support
2017-03-18 13:37:31 +08:00
d956444965 Merge branch 'develop' into add-gosimple 2017-03-18 11:20:30 +08:00
8dbf9eb0bf Merge pull request #2512 from sergeylanzman/add-unconvert
add unconverted support
2017-03-18 11:05:28 +08:00
faa981fb6a Merge pull request #2511 from sergeylanzman/drop-go1.4-1.5-travis
drop support go1.4/5 in travis yml
2017-03-18 11:02:39 +08:00
1ea3c13ff5 Merge branch 'develop' into drop-go1.4-1.5-travis 2017-03-18 11:02:15 +08:00
46d8fef0ad Merge pull request #2510 from sergeylanzman/travis-add-1.7-1.8
add support go1.7/8 to travis yml
2017-03-18 11:01:27 +08:00
37c1ffc57a add go simple support 2017-03-17 20:22:20 +02:00
856fde28dc add unconverted support 2017-03-17 19:45:30 +02:00
3204d7631b drop support go1.4/5 in travis yml 2017-03-17 19:33:54 +02:00
f5fc2edfd3 add support go1.7/8 to travis yml 2017-03-17 19:32:31 +02:00
21d1267c14 Merge pull request #2501 from sergeylanzman/change-template-error-log
temple parse error write in log as trace. change to error
2017-03-14 20:04:42 +08:00
3e37b97549 temple parse error write in log as trace. change to error 2017-03-14 12:55:40 +02:00
206f736819 Merge pull request #2496 from eyalpost/develop
Don't panic during AddViewPath if adding the same path twice
2017-03-14 12:54:48 +08:00
24d4a27842 Don't panic during AddViewPath if adding the same path twice 2017-03-13 08:46:57 +02:00
46f3ea4f43 Merge pull request #2494 from miraclesu/develop
validation: fix email valid
2017-03-12 22:26:25 +08:00
c9cc642d37 validation: amend email test case 2017-03-12 20:27:09 +08:00
b34853f8cc validattion: add test case for email valid 2017-03-12 19:30:23 +08:00
d41f4c0a3a validation: fix email valid 2017-03-12 19:23:46 +08:00
8e46decc8e fix routing bug for splat 2017-03-10 09:28:25 +08:00
49fffe3ebe Parse form time by its length
Fix #2451

Signed-off-by: Guohua Ouyang <guohuaouyang@gmail.com>
2017-02-27 14:43:16 +08:00
91 changed files with 912 additions and 680 deletions

4
.gosimpleignore Normal file
View File

@ -0,0 +1,4 @@
github.com/astaxie/beego/*/*:S1012
github.com/astaxie/beego/*:S1012
github.com/astaxie/beego/*/*:S1007
github.com/astaxie/beego/*:S1007

View File

@ -1,9 +1,9 @@
language: go language: go
go: go:
- 1.6 - 1.6.4
- 1.5.3 - 1.7.5
- 1.4.3 - 1.8.1
services: services:
- redis-server - redis-server
- mysql - mysql
@ -33,6 +33,10 @@ install:
- go get github.com/ssdb/gossdb/ssdb - go get github.com/ssdb/gossdb/ssdb
- go get github.com/cloudflare/golz4 - go get github.com/cloudflare/golz4
- go get github.com/gogo/protobuf/proto - go get github.com/gogo/protobuf/proto
- go get -u honnef.co/go/tools/cmd/gosimple
- go get -u github.com/mdempsky/unconvert
- go get -u github.com/gordonklaus/ineffassign
- go get -u github.com/golang/lint/golint
before_script: before_script:
- psql --version - psql --version
- sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
@ -47,5 +51,10 @@ after_script:
- rm -rf ./res/var/* - rm -rf ./res/var/*
script: script:
- go test -v ./... - go test -v ./...
- gosimple -ignore "$(cat .gosimpleignore)" $(go list ./... | grep -v /vendor/)
- unconvert $(go list ./... | grep -v /vendor/)
- ineffassign .
- find . ! \( -path './vendor' -prune \) -type f -name '*.go' -print0 | xargs -0 gofmt -l -s
- golint ./...
addons: addons:
postgresql: "9.4" postgresql: "9.4"

View File

@ -1,20 +1,17 @@
## Beego # Beego [![Build Status](https://travis-ci.org/astaxie/beego.svg?branch=master)](https://travis-ci.org/astaxie/beego) [![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego) [![Foundation](https://img.shields.io/badge/Golang-Foundation-green.svg)](http://golangfoundation.org)
[![Build Status](https://travis-ci.org/astaxie/beego.svg?branch=master)](https://travis-ci.org/astaxie/beego)
[![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego)
[![Foundation](https://img.shields.io/badge/Golang-Foundation-green.svg)](http://golangfoundation.org)
beego is used for rapid development of RESTful APIs, web apps and backend services in Go. 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 embedding. It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding.
More info [beego.me](http://beego.me) ###### More info at [beego.me](http://beego.me).
##Quick Start ## Quick Start
######Download and install
#### Download and install
go get github.com/astaxie/beego go get github.com/astaxie/beego
######Create file `hello.go` #### Create file `hello.go`
```go ```go
package main package main
@ -24,15 +21,16 @@ func main(){
beego.Run() beego.Run()
} }
``` ```
######Build and run #### Build and run
```bash
go build hello.go go build hello.go
./hello ./hello
```
######Congratulations! #### Go to [http://localhost:8080](http://localhost:8080)
You just built your first beego app.
Open your browser and visit `http://localhost:8080`. Congratulations! You've just built your first **beego** app.
Please see [Documentation](http://beego.me/docs) for more.
###### Please see [Documentation](http://beego.me/docs) for more.
## Features ## Features
@ -56,7 +54,7 @@ Please see [Documentation](http://beego.me/docs) for more.
* [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)
## LICENSE ## License
beego source code is licensed under the Apache Licence, Version 2.0 beego source code is licensed under the Apache Licence, Version 2.0
(http://www.apache.org/licenses/LICENSE-2.0.html). (http://www.apache.org/licenses/LICENSE-2.0.html).

View File

@ -105,29 +105,12 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
tmpl.Execute(rw, data) tmpl.Execute(rw, data)
case "router": case "router":
var ( content := PrintTree()
content = map[string]interface{}{ content["Fields"] = []string{
"Fields": []string{ "Router Pattern",
"Router Pattern", "Methods",
"Methods", "Controller",
"Controller",
},
}
methods = []string{}
methodsData = make(map[string]interface{})
)
for method, t := range BeeApp.Handlers.routers {
resultList := new([][]string)
printTree(resultList, t)
methods = append(methods, method)
methodsData[method] = resultList
} }
content["Data"] = methodsData
content["Methods"] = methods
data["Content"] = content data["Content"] = content
data["Title"] = "Routers" data["Title"] = "Routers"
execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl) execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl)
@ -157,8 +140,8 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
resultList := new([][]string) resultList := new([][]string)
for _, f := range bf { for _, f := range bf {
var result = []string{ var result = []string{
fmt.Sprintf("%s", f.pattern), f.pattern,
fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)), utils.GetFuncName(f.filterFunc),
} }
*resultList = append(*resultList, result) *resultList = append(*resultList, result)
} }
@ -200,6 +183,28 @@ func list(root string, p interface{}, m map[string]interface{}) {
} }
} }
// PrintTree prints all registered routers.
func PrintTree() map[string]interface{} {
var (
content = map[string]interface{}{}
methods = []string{}
methodsData = make(map[string]interface{})
)
for method, t := range BeeApp.Handlers.routers {
resultList := new([][]string)
printTree(resultList, t)
methods = append(methods, method)
methodsData[method] = resultList
}
content["Data"] = methodsData
content["Methods"] = methods
return content
}
func printTree(resultList *[][]string, t *Tree) { func printTree(resultList *[][]string, t *Tree) {
for _, tr := range t.fixrouters { for _, tr := range t.fixrouters {
printTree(resultList, tr) printTree(resultList, tr)
@ -208,12 +213,12 @@ func printTree(resultList *[][]string, t *Tree) {
printTree(resultList, t.wildcard) printTree(resultList, t.wildcard)
} }
for _, l := range t.leaves { for _, l := range t.leaves {
if v, ok := l.runObject.(*controllerInfo); ok { if v, ok := l.runObject.(*ControllerInfo); ok {
if v.routerType == routerTypeBeego { if v.routerType == routerTypeBeego {
var result = []string{ var result = []string{
v.pattern, v.pattern,
fmt.Sprintf("%s", v.methods), fmt.Sprintf("%s", v.methods),
fmt.Sprintf("%s", v.controllerType), v.controllerType.String(),
} }
*resultList = append(*resultList, result) *resultList = append(*resultList, result)
} else if v.routerType == routerTypeRESTFul { } else if v.routerType == routerTypeRESTFul {
@ -276,8 +281,8 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
// it's in "/healthcheck" pattern in admin module. // it's in "/healthcheck" pattern in admin module.
func healthcheck(rw http.ResponseWriter, req *http.Request) { func healthcheck(rw http.ResponseWriter, req *http.Request) {
var ( var (
result []string
data = make(map[interface{}]interface{}) data = make(map[interface{}]interface{})
result = []string{}
resultList = new([][]string) resultList = new([][]string)
content = map[string]interface{}{ content = map[string]interface{}{
"Fields": []string{"Name", "Message", "Status"}, "Fields": []string{"Name", "Message", "Status"},
@ -287,21 +292,20 @@ func healthcheck(rw http.ResponseWriter, req *http.Request) {
for name, h := range toolbox.AdminCheckList { for name, h := range toolbox.AdminCheckList {
if err := h.Check(); err != nil { if err := h.Check(); err != nil {
result = []string{ result = []string{
fmt.Sprintf("error"), "error",
fmt.Sprintf("%s", name), name,
fmt.Sprintf("%s", err.Error()), err.Error(),
} }
} else { } else {
result = []string{ result = []string{
fmt.Sprintf("success"), "success",
fmt.Sprintf("%s", name), name,
fmt.Sprintf("OK"), "OK",
} }
} }
*resultList = append(*resultList, result) *resultList = append(*resultList, result)
} }
content["Data"] = resultList content["Data"] = resultList
data["Content"] = content data["Content"] = content
data["Title"] = "Health Check" data["Title"] = "Health Check"
@ -330,7 +334,6 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
// List Tasks // List Tasks
content := make(map[string]interface{}) content := make(map[string]interface{})
resultList := new([][]string) resultList := new([][]string)
var result = []string{}
var fields = []string{ var fields = []string{
"Task Name", "Task Name",
"Task Spec", "Task Spec",
@ -339,10 +342,10 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
"", "",
} }
for tname, tk := range toolbox.AdminTaskList { for tname, tk := range toolbox.AdminTaskList {
result = []string{ result := []string{
tname, tname,
fmt.Sprintf("%s", tk.GetSpec()), tk.GetSpec(),
fmt.Sprintf("%s", tk.GetStatus()), tk.GetStatus(),
tk.GetPrev().String(), tk.GetPrev().String(),
} }
*resultList = append(*resultList, result) *resultList = append(*resultList, result)

6
app.go
View File

@ -348,9 +348,9 @@ func Any(rootpath string, f FilterFunc) *App {
// Handler used to register a Handler router // Handler used to register a Handler router
// usage: // usage:
// beego.Handler("/api", func(ctx *context.Context){ // beego.Handler("/api", http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
// ctx.Output.Body("hello world") // fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
// }) // }))
func Handler(rootpath string, h http.Handler, options ...interface{}) *App { func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
BeeApp.Handlers.Handler(rootpath, h, options...) BeeApp.Handlers.Handler(rootpath, h, options...)
return BeeApp return BeeApp

View File

@ -23,7 +23,7 @@ import (
const ( const (
// VERSION represent beego web framework version. // VERSION represent beego web framework version.
VERSION = "1.8.0" VERSION = "1.8.2"
// DEV is for develop // DEV is for develop
DEV = "dev" DEV = "dev"

6
cache/conv_test.go vendored
View File

@ -118,14 +118,14 @@ func TestGetFloat64(t *testing.T) {
func TestGetBool(t *testing.T) { func TestGetBool(t *testing.T) {
var t1 = true var t1 = true
if true != GetBool(t1) { if !GetBool(t1) {
t.Error("get bool from bool error") t.Error("get bool from bool error")
} }
var t2 = "true" var t2 = "true"
if true != GetBool(t2) { if !GetBool(t2) {
t.Error("get bool from string error") t.Error("get bool from string error")
} }
if false != GetBool(nil) { if GetBool(nil) {
t.Error("get bool from nil error") t.Error("get bool from nil error")
} }
} }

View File

@ -146,10 +146,7 @@ func (rc *Cache) IsExist(key string) bool {
} }
} }
_, err := rc.conn.Get(key) _, err := rc.conn.Get(key)
if err != nil { return !(err != nil)
return false
}
return true
} }
// ClearAll clear all cached in memcache. // ClearAll clear all cached in memcache.

View File

@ -137,7 +137,7 @@ func (rc *Cache) IsExist(key string) bool {
if err != nil { if err != nil {
return false return false
} }
if v == false { if !v {
if _, err = rc.do("HDEL", rc.key, key); err != nil { if _, err = rc.do("HDEL", rc.key, key); err != nil {
return false return false
} }

19
cache/ssdb/ssdb.go vendored
View File

@ -53,7 +53,7 @@ func (rc *Cache) GetMulti(keys []string) []interface{} {
resSize := len(res) resSize := len(res)
if err == nil { if err == nil {
for i := 1; i < resSize; i += 2 { for i := 1; i < resSize; i += 2 {
values = append(values, string(res[i+1])) values = append(values, res[i+1])
} }
return values return values
} }
@ -71,10 +71,7 @@ func (rc *Cache) DelMulti(keys []string) error {
} }
} }
_, err := rc.conn.Do("multi_del", keys) _, err := rc.conn.Do("multi_del", keys)
if err != nil { return err
return err
}
return nil
} }
// Put put value to memcache. only support string. // Put put value to memcache. only support string.
@ -113,10 +110,7 @@ func (rc *Cache) Delete(key string) error {
} }
} }
_, err := rc.conn.Del(key) _, err := rc.conn.Del(key)
if err != nil { return err
return err
}
return nil
} }
// Incr increase counter. // Incr increase counter.
@ -175,7 +169,7 @@ func (rc *Cache) ClearAll() error {
} }
keys := []string{} keys := []string{}
for i := 1; i < size; i += 2 { for i := 1; i < size; i += 2 {
keys = append(keys, string(resp[i])) keys = append(keys, resp[i])
} }
_, e := rc.conn.Do("multi_del", keys) _, e := rc.conn.Do("multi_del", keys)
if e != nil { if e != nil {
@ -229,10 +223,7 @@ func (rc *Cache) connectInit() error {
} }
var err error var err error
rc.conn, err = ssdb.Connect(host, port) rc.conn, err = ssdb.Connect(host, port)
if err != nil { return err
return err
}
return nil
} }
func init() { func init() {

View File

@ -345,7 +345,7 @@ func assignSingleConfig(p interface{}, ac config.Configer) {
case reflect.String: case reflect.String:
pf.SetString(ac.DefaultString(name, pf.String())) pf.SetString(ac.DefaultString(name, pf.String()))
case reflect.Int, reflect.Int64: case reflect.Int, reflect.Int64:
pf.SetInt(int64(ac.DefaultInt64(name, pf.Int()))) pf.SetInt(ac.DefaultInt64(name, pf.Int()))
case reflect.Bool: case reflect.Bool:
pf.SetBool(ac.DefaultBool(name, pf.Bool())) pf.SetBool(ac.DefaultBool(name, pf.Bool()))
case reflect.Struct: case reflect.Struct:

2
config/env/env.go vendored
View File

@ -12,6 +12,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// 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 env is used to parse environment.
package env package env
import ( import (

View File

@ -21,6 +21,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/user"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -184,10 +185,17 @@ func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, e
// ParseData parse ini the data // ParseData parse ini the data
// When include other.conf,other.conf is either absolute directory // When include other.conf,other.conf is either absolute directory
// or under beego in default temporary directory(/tmp/beego). // or under beego in default temporary directory(/tmp/beego[-username]).
func (ini *IniConfig) ParseData(data []byte) (Configer, error) { func (ini *IniConfig) ParseData(data []byte) (Configer, error) {
dir := filepath.Join(os.TempDir(), "beego") dir := "beego"
os.MkdirAll(dir, os.ModePerm) currentUser, err := user.Current()
if err == nil {
dir = "beego-" + currentUser.Username
}
dir = filepath.Join(os.TempDir(), dir)
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
return nil, err
}
return ini.parseData(dir, data) return ini.parseData(dir, data)
} }
@ -317,7 +325,10 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
// Get section or key comments. Fixed #1607 // Get section or key comments. Fixed #1607
getCommentStr := func(section, key string) string { getCommentStr := func(section, key string) string {
comment, ok := "", false var (
comment string
ok bool
)
if len(key) == 0 { if len(key) == 0 {
comment, ok = c.sectionComment[section] comment, ok = c.sectionComment[section]
} else { } else {
@ -397,11 +408,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
} }
} }
} }
_, err = buf.WriteTo(f)
if _, err = buf.WriteTo(f); err != nil { return err
return err
}
return nil
} }
// Set writes a new value for key. // Set writes a new value for key.
@ -416,7 +424,7 @@ func (c *IniConfigContainer) Set(key, value string) error {
var ( var (
section, k string section, k string
sectionKey = strings.Split(key, "::") sectionKey = strings.Split(strings.ToLower(key), "::")
) )
if len(sectionKey) >= 2 { if len(sectionKey) >= 2 {

View File

@ -181,7 +181,7 @@ name=mysql
cfgData := string(data) cfgData := string(data)
datas := strings.Split(saveResult, "\n") datas := strings.Split(saveResult, "\n")
for _, line := range datas { for _, line := range datas {
if strings.Contains(cfgData, line+"\n") == false { if !strings.Contains(cfgData, line+"\n") {
t.Fatalf("different after save ini config file. need contains %q", line) t.Fatalf("different after save ini config file. need contains %q", line)
} }
} }

View File

@ -39,6 +39,7 @@ var (
getMethodOnly bool getMethodOnly bool
) )
// InitGzip init the gzipcompress
func InitGzip(minLength, compressLevel int, methods []string) { func InitGzip(minLength, compressLevel int, methods []string) {
if minLength >= 0 { if minLength >= 0 {
gzipMinLength = minLength gzipMinLength = minLength

View File

@ -73,8 +73,8 @@ func TestBind(t *testing.T) {
{"/?human.ID=888&human.Nick=astaxie&human.Ms=true&human[Pwd]=pass", []testItem{{"human", Human{}, Human{ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass"}}}}, {"/?human.ID=888&human.Nick=astaxie&human.Ms=true&human[Pwd]=pass", []testItem{{"human", Human{}, Human{ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass"}}}},
{"/?human[0].ID=888&human[0].Nick=astaxie&human[0].Ms=true&human[0][Pwd]=pass01&human[1].ID=999&human[1].Nick=ysqi&human[1].Ms=On&human[1].Pwd=pass02", {"/?human[0].ID=888&human[0].Nick=astaxie&human[0].Ms=true&human[0][Pwd]=pass01&human[1].ID=999&human[1].Nick=ysqi&human[1].Ms=On&human[1].Pwd=pass02",
[]testItem{{"human", []Human{}, []Human{ []testItem{{"human", []Human{}, []Human{
Human{ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass01"}, {ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass01"},
Human{ID: 999, Nick: "ysqi", Ms: true, Pwd: "pass02"}, {ID: 999, Nick: "ysqi", Ms: true, Pwd: "pass02"},
}}}}, }}}},
{ {

View File

@ -223,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
} }
buf.Reset() buf.Reset()
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath() ,c.Data) ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
} }
return buf.Bytes(), err return buf.Bytes(), err
} }
@ -249,7 +249,7 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) {
} }
} }
} }
BuildTemplate(c.viewPath() , buildFiles...) BuildTemplate(c.viewPath(), buildFiles...)
} }
return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data) return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data)
} }
@ -314,7 +314,7 @@ func (c *Controller) ServeJSON(encoding ...bool) {
if BConfig.RunMode == PROD { if BConfig.RunMode == PROD {
hasIndent = false hasIndent = false
} }
if len(encoding) > 0 && encoding[0] == true { if len(encoding) > 0 && encoding[0] {
hasEncoding = true hasEncoding = true
} }
c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding) c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)

View File

@ -172,10 +172,10 @@ func TestAdditionalViewPaths(t *testing.T) {
t.Fatal("TestAdditionalViewPaths expected error") t.Fatal("TestAdditionalViewPaths expected error")
} }
}() }()
ctrl.RenderString(); ctrl.RenderString()
}() }()
ctrl.TplName = "file2.tpl" ctrl.TplName = "file2.tpl"
ctrl.ViewPath = dir2 ctrl.ViewPath = dir2
ctrl.RenderString(); ctrl.RenderString()
} }

View File

@ -48,7 +48,7 @@ func TestFlashHeader(t *testing.T) {
// match for the expected header // match for the expected header
res := strings.Contains(sc, "BEEGO_FLASH=%00notice%23BEEGOFLASH%23TestFlashString%00") res := strings.Contains(sc, "BEEGO_FLASH=%00notice%23BEEGOFLASH%23TestFlashString%00")
// validate the assertion // validate the assertion
if res != true { if !res {
t.Errorf("TestFlashHeader() unable to validate flash message") t.Errorf("TestFlashHeader() unable to validate flash message")
} }
} }

View File

@ -21,7 +21,7 @@ func newGraceListener(l net.Listener, srv *Server) (el *graceListener) {
server: srv, server: srv,
} }
go func() { go func() {
_ = <-el.stop <-el.stop
el.stopped = true el.stopped = true
el.stop <- el.Listener.Close() el.stop <- el.Listener.Close()
}() }()

View File

@ -196,7 +196,6 @@ func (srv *Server) signalHooks(ppFlag int, sig os.Signal) {
for _, f := range srv.SignalHooks[ppFlag][sig] { for _, f := range srv.SignalHooks[ppFlag][sig] {
f() f()
} }
return
} }
// shutdown closes the listener so that no new connections are accepted. it also // shutdown closes the listener so that no new connections are accepted. it also
@ -292,7 +291,7 @@ func (srv *Server) fork() (err error) {
// RegisterSignalHook registers a function to be run PreSignal or PostSignal for a given signal. // RegisterSignalHook registers a function to be run PreSignal or PostSignal for a given signal.
func (srv *Server) RegisterSignalHook(ppFlag int, sig os.Signal, f func()) (err error) { func (srv *Server) RegisterSignalHook(ppFlag int, sig os.Signal, f func()) (err error) {
if ppFlag != PreSignal && ppFlag != PostSignal { if ppFlag != PreSignal && ppFlag != PostSignal {
err = fmt.Errorf("Invalid ppFlag argument. Must be either grace.PreSignal or grace.PostSignal.") err = fmt.Errorf("Invalid ppFlag argument. Must be either grace.PreSignal or grace.PostSignal")
return return
} }
for _, s := range hookableSignals { for _, s := range hookableSignals {
@ -301,6 +300,6 @@ func (srv *Server) RegisterSignalHook(ppFlag int, sig os.Signal, f func()) (err
return return
} }
} }
err = fmt.Errorf("Signal '%v' is not supported.", sig) err = fmt.Errorf("Signal '%v' is not supported", sig)
return return
} }

View File

@ -55,9 +55,9 @@ func registerSession() error {
conf.ProviderConfig = filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig) conf.ProviderConfig = filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig)
conf.DisableHTTPOnly = BConfig.WebConfig.Session.SessionDisableHTTPOnly conf.DisableHTTPOnly = BConfig.WebConfig.Session.SessionDisableHTTPOnly
conf.Domain = BConfig.WebConfig.Session.SessionDomain conf.Domain = BConfig.WebConfig.Session.SessionDomain
conf.EnableSidInHttpHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader conf.EnableSidInHTTPHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader
conf.SessionNameInHttpHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader conf.SessionNameInHTTPHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader
conf.EnableSidInUrlQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery conf.EnableSidInURLQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery
} else { } else {
if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil { if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil {
return err return err

View File

@ -32,7 +32,7 @@ The default timeout is `60` seconds, function prototype:
SetTimeout(connectTimeout, readWriteTimeout time.Duration) SetTimeout(connectTimeout, readWriteTimeout time.Duration)
Exmaple: Example:
// GET // GET
httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second) httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)

View File

@ -335,7 +335,7 @@ func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error)
func (b *BeegoHTTPRequest) buildURL(paramBody string) { func (b *BeegoHTTPRequest) buildURL(paramBody string) {
// build GET url with query string // build GET url with query string
if b.req.Method == "GET" && len(paramBody) > 0 { if b.req.Method == "GET" && len(paramBody) > 0 {
if strings.Index(b.url, "?") != -1 { if strings.Contains(b.url, "?") {
b.url += "&" + paramBody b.url += "&" + paramBody
} else { } else {
b.url = b.url + "?" + paramBody b.url = b.url + "?" + paramBody
@ -344,7 +344,7 @@ func (b *BeegoHTTPRequest) buildURL(paramBody string) {
} }
// build POST/PUT/PATCH url and body // build POST/PUT/PATCH url and body
if (b.req.Method == "POST" || b.req.Method == "PUT" || b.req.Method == "PATCH") && b.req.Body == nil { if (b.req.Method == "POST" || b.req.Method == "PUT" || b.req.Method == "PATCH" || b.req.Method == "DELETE") && b.req.Body == nil {
// with files // with files
if len(b.files) > 0 { if len(b.files) > 0 {
pr, pw := io.Pipe() pr, pw := io.Pipe()
@ -520,9 +520,9 @@ func (b *BeegoHTTPRequest) Bytes() ([]byte, error) {
return nil, err return nil, err
} }
b.body, err = ioutil.ReadAll(reader) b.body, err = ioutil.ReadAll(reader)
} else { return b.body, err
b.body, err = ioutil.ReadAll(resp.Body)
} }
b.body, err = ioutil.ReadAll(resp.Body)
return b.body, err return b.body, err
} }

View File

@ -102,6 +102,14 @@ func TestSimpleDelete(t *testing.T) {
t.Log(str) t.Log(str)
} }
func TestSimpleDeleteParam(t *testing.T) {
str, err := Delete("http://httpbin.org/delete").Param("key", "val").String()
if err != nil {
t.Fatal(err)
}
t.Log(str)
}
func TestWithCookie(t *testing.T) { func TestWithCookie(t *testing.T) {
v := "smallfish" v := "smallfish"
str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String() str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String()

View File

@ -2,19 +2,23 @@ package alils
import ( import (
"encoding/json" "encoding/json"
"github.com/astaxie/beego/logs"
"github.com/gogo/protobuf/proto"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/astaxie/beego/logs"
"github.com/gogo/protobuf/proto"
) )
const ( const (
CacheSize int = 64 // CacheSize set the flush size
CacheSize int = 64
// Delimiter define the topic delimiter
Delimiter string = "##" Delimiter string = "##"
) )
type AliLSConfig struct { // Config is the Config for Ali Log
type Config struct {
Project string `json:"project"` Project string `json:"project"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
KeyID string `json:"key_id"` KeyID string `json:"key_id"`
@ -34,18 +38,17 @@ type aliLSWriter struct {
withMap bool withMap bool
groupMap map[string]*LogGroup groupMap map[string]*LogGroup
lock *sync.Mutex lock *sync.Mutex
AliLSConfig Config
} }
// 创建提供Logger接口的日志服务 // NewAliLS create a new Logger
func NewAliLS() logs.Logger { func NewAliLS() logs.Logger {
alils := new(aliLSWriter) alils := new(aliLSWriter)
alils.Level = logs.LevelTrace alils.Level = logs.LevelTrace
return alils return alils
} }
// 读取配置 // Init parse config and init struct
// 初始化必要的数据结构
func (c *aliLSWriter) Init(jsonConfig string) (err error) { func (c *aliLSWriter) Init(jsonConfig string) (err error) {
json.Unmarshal([]byte(jsonConfig), c) json.Unmarshal([]byte(jsonConfig), c)
@ -54,28 +57,26 @@ func (c *aliLSWriter) Init(jsonConfig string) (err error) {
c.FlushWhen = CacheSize c.FlushWhen = CacheSize
} }
// 初始化Project
prj := &LogProject{ prj := &LogProject{
Name: c.Project, Name: c.Project,
Endpoint: c.Endpoint, Endpoint: c.Endpoint,
AccessKeyId: c.KeyID, AccessKeyID: c.KeyID,
AccessKeySecret: c.KeySecret, AccessKeySecret: c.KeySecret,
} }
// 获取logstore
c.store, err = prj.GetLogStore(c.LogStore) c.store, err = prj.GetLogStore(c.LogStore)
if err != nil { if err != nil {
return err return err
} }
// 创建默认Log Group // Create default Log Group
c.group = append(c.group, &LogGroup{ c.group = append(c.group, &LogGroup{
Topic: proto.String(""), Topic: proto.String(""),
Source: proto.String(c.Source), Source: proto.String(c.Source),
Logs: make([]*Log, 0, c.FlushWhen), Logs: make([]*Log, 0, c.FlushWhen),
}) })
// 创建其它Log Group // Create other Log Group
c.groupMap = make(map[string]*LogGroup) c.groupMap = make(map[string]*LogGroup)
for _, topic := range c.Topics { for _, topic := range c.Topics {
@ -113,7 +114,7 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
var lg *LogGroup var lg *LogGroup
if c.withMap { if c.withMap {
// 解析出Topic并匹配LogGroup // TopicLogGroup
strs := strings.SplitN(msg, Delimiter, 2) strs := strings.SplitN(msg, Delimiter, 2)
if len(strs) == 2 { if len(strs) == 2 {
pos := strings.LastIndex(strs[0], " ") pos := strings.LastIndex(strs[0], " ")
@ -122,27 +123,24 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
lg = c.groupMap[topic] lg = c.groupMap[topic]
} }
// 默认发到空Topic // send to empty Topic
if lg == nil { if lg == nil {
topic = ""
content = msg content = msg
lg = c.group[0] lg = c.group[0]
} }
} else { } else {
topic = ""
content = msg content = msg
lg = c.group[0] lg = c.group[0]
} }
// 生成日志 c1 := &LogContent{
c1 := &Log_Content{
Key: proto.String("msg"), Key: proto.String("msg"),
Value: proto.String(content), Value: proto.String(content),
} }
l := &Log{ l := &Log{
Time: proto.Uint32(uint32(when.Unix())), // 填写日志时间 Time: proto.Uint32(uint32(when.Unix())),
Contents: []*Log_Content{ Contents: []*LogContent{
c1, c1,
}, },
} }
@ -151,7 +149,6 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
lg.Logs = append(lg.Logs, l) lg.Logs = append(lg.Logs, l)
c.lock.Unlock() c.lock.Unlock()
// 满足条件则Flush
if len(lg.Logs) >= c.FlushWhen { if len(lg.Logs) >= c.FlushWhen {
c.flush(lg) c.flush(lg)
} }
@ -162,7 +159,7 @@ func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error
// Flush implementing method. empty. // Flush implementing method. empty.
func (c *aliLSWriter) Flush() { func (c *aliLSWriter) Flush() {
// flush所有group // flush all group
for _, lg := range c.group { for _, lg := range c.group {
c.flush(lg) c.flush(lg)
} }
@ -176,9 +173,6 @@ func (c *aliLSWriter) flush(lg *LogGroup) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
// 把以上的LogGroup推送到SLS服务器
// SLS服务器会根据该logstore的shard个数自动进行负载均衡。
err := c.store.PutLogs(lg) err := c.store.PutLogs(lg)
if err != nil { if err != nil {
return return

View File

@ -1,30 +1,43 @@
package alils package alils
import "github.com/gogo/protobuf/proto" import (
import "fmt" "fmt"
import "math" "io"
"math"
// discarding unused import gogoproto "." "github.com/gogo/protobuf/proto"
github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" )
import "io"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
var (
// ErrInvalidLengthLog invalid proto
ErrInvalidLengthLog = fmt.Errorf("proto: negative length found during unmarshaling")
// ErrIntOverflowLog overflow
ErrIntOverflowLog = fmt.Errorf("proto: integer overflow")
)
// Log define the proto Log
type Log struct { type Log struct {
Time *uint32 `protobuf:"varint,1,req,name=Time" json:"Time,omitempty"` Time *uint32 `protobuf:"varint,1,req,name=Time" json:"Time,omitempty"`
Contents []*Log_Content `protobuf:"bytes,2,rep,name=Contents" json:"Contents,omitempty"` Contents []*LogContent `protobuf:"bytes,2,rep,name=Contents" json:"Contents,omitempty"`
XXX_unrecognized []byte `json:"-"` XXXUnrecognized []byte `json:"-"`
} }
func (m *Log) Reset() { *m = Log{} } // Reset the Log
func (m *Log) String() string { return proto.CompactTextString(m) } func (m *Log) Reset() { *m = Log{} }
func (*Log) ProtoMessage() {}
// String return the Compact Log
func (m *Log) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*Log) ProtoMessage() {}
// GetTime return the Log's Time
func (m *Log) GetTime() uint32 { func (m *Log) GetTime() uint32 {
if m != nil && m.Time != nil { if m != nil && m.Time != nil {
return *m.Time return *m.Time
@ -32,49 +45,65 @@ func (m *Log) GetTime() uint32 {
return 0 return 0
} }
func (m *Log) GetContents() []*Log_Content { // GetContents return the Log's Contents
func (m *Log) GetContents() []*LogContent {
if m != nil { if m != nil {
return m.Contents return m.Contents
} }
return nil return nil
} }
type Log_Content struct { // LogContent define the Log content struct
Key *string `protobuf:"bytes,1,req,name=Key" json:"Key,omitempty"` type LogContent struct {
Value *string `protobuf:"bytes,2,req,name=Value" json:"Value,omitempty"` Key *string `protobuf:"bytes,1,req,name=Key" json:"Key,omitempty"`
XXX_unrecognized []byte `json:"-"` Value *string `protobuf:"bytes,2,req,name=Value" json:"Value,omitempty"`
XXXUnrecognized []byte `json:"-"`
} }
func (m *Log_Content) Reset() { *m = Log_Content{} } // Reset LogContent
func (m *Log_Content) String() string { return proto.CompactTextString(m) } func (m *LogContent) Reset() { *m = LogContent{} }
func (*Log_Content) ProtoMessage() {}
func (m *Log_Content) GetKey() string { // String return the compact text
func (m *LogContent) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogContent) ProtoMessage() {}
// GetKey return the Key
func (m *LogContent) GetKey() string {
if m != nil && m.Key != nil { if m != nil && m.Key != nil {
return *m.Key return *m.Key
} }
return "" return ""
} }
func (m *Log_Content) GetValue() string { // GetValue return the Value
func (m *LogContent) GetValue() string {
if m != nil && m.Value != nil { if m != nil && m.Value != nil {
return *m.Value return *m.Value
} }
return "" return ""
} }
// LogGroup define the logs struct
type LogGroup struct { type LogGroup struct {
Logs []*Log `protobuf:"bytes,1,rep,name=Logs" json:"Logs,omitempty"` Logs []*Log `protobuf:"bytes,1,rep,name=Logs" json:"Logs,omitempty"`
Reserved *string `protobuf:"bytes,2,opt,name=Reserved" json:"Reserved,omitempty"` Reserved *string `protobuf:"bytes,2,opt,name=Reserved" json:"Reserved,omitempty"`
Topic *string `protobuf:"bytes,3,opt,name=Topic" json:"Topic,omitempty"` Topic *string `protobuf:"bytes,3,opt,name=Topic" json:"Topic,omitempty"`
Source *string `protobuf:"bytes,4,opt,name=Source" json:"Source,omitempty"` Source *string `protobuf:"bytes,4,opt,name=Source" json:"Source,omitempty"`
XXX_unrecognized []byte `json:"-"` XXXUnrecognized []byte `json:"-"`
} }
func (m *LogGroup) Reset() { *m = LogGroup{} } // Reset LogGroup
func (m *LogGroup) String() string { return proto.CompactTextString(m) } func (m *LogGroup) Reset() { *m = LogGroup{} }
func (*LogGroup) ProtoMessage() {}
// String return the compact text
func (m *LogGroup) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogGroup) ProtoMessage() {}
// GetLogs return the loggroup logs
func (m *LogGroup) GetLogs() []*Log { func (m *LogGroup) GetLogs() []*Log {
if m != nil { if m != nil {
return m.Logs return m.Logs
@ -82,6 +111,7 @@ func (m *LogGroup) GetLogs() []*Log {
return nil return nil
} }
// GetReserved return Reserved
func (m *LogGroup) GetReserved() string { func (m *LogGroup) GetReserved() string {
if m != nil && m.Reserved != nil { if m != nil && m.Reserved != nil {
return *m.Reserved return *m.Reserved
@ -89,6 +119,7 @@ func (m *LogGroup) GetReserved() string {
return "" return ""
} }
// GetTopic return Topic
func (m *LogGroup) GetTopic() string { func (m *LogGroup) GetTopic() string {
if m != nil && m.Topic != nil { if m != nil && m.Topic != nil {
return *m.Topic return *m.Topic
@ -96,6 +127,7 @@ func (m *LogGroup) GetTopic() string {
return "" return ""
} }
// GetSource return Source
func (m *LogGroup) GetSource() string { func (m *LogGroup) GetSource() string {
if m != nil && m.Source != nil { if m != nil && m.Source != nil {
return *m.Source return *m.Source
@ -103,15 +135,22 @@ func (m *LogGroup) GetSource() string {
return "" return ""
} }
// LogGroupList define the LogGroups
type LogGroupList struct { type LogGroupList struct {
LogGroups []*LogGroup `protobuf:"bytes,1,rep,name=logGroups" json:"logGroups,omitempty"` LogGroups []*LogGroup `protobuf:"bytes,1,rep,name=logGroups" json:"logGroups,omitempty"`
XXX_unrecognized []byte `json:"-"` XXXUnrecognized []byte `json:"-"`
} }
func (m *LogGroupList) Reset() { *m = LogGroupList{} } // Reset LogGroupList
func (m *LogGroupList) String() string { return proto.CompactTextString(m) } func (m *LogGroupList) Reset() { *m = LogGroupList{} }
func (*LogGroupList) ProtoMessage() {}
// String return compact text
func (m *LogGroupList) String() string { return proto.CompactTextString(m) }
// ProtoMessage not implemented
func (*LogGroupList) ProtoMessage() {}
// GetLogGroups return the LogGroups
func (m *LogGroupList) GetLogGroups() []*LogGroup { func (m *LogGroupList) GetLogGroups() []*LogGroup {
if m != nil { if m != nil {
return m.LogGroups return m.LogGroups
@ -119,6 +158,7 @@ func (m *LogGroupList) GetLogGroups() []*LogGroup {
return nil return nil
} }
// Marshal the logs to byte slice
func (m *Log) Marshal() (data []byte, err error) { func (m *Log) Marshal() (data []byte, err error) {
size := m.Size() size := m.Size()
data = make([]byte, size) data = make([]byte, size)
@ -129,6 +169,7 @@ func (m *Log) Marshal() (data []byte, err error) {
return data[:n], nil return data[:n], nil
} }
// MarshalTo data
func (m *Log) MarshalTo(data []byte) (int, error) { func (m *Log) MarshalTo(data []byte) (int, error) {
var i int var i int
_ = i _ = i
@ -136,11 +177,10 @@ func (m *Log) MarshalTo(data []byte) (int, error) {
_ = l _ = l
if m.Time == nil { if m.Time == nil {
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Time") return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Time")
} else {
data[i] = 0x8
i++
i = encodeVarintLog(data, i, uint64(*m.Time))
} }
data[i] = 0x8
i++
i = encodeVarintLog(data, i, uint64(*m.Time))
if len(m.Contents) > 0 { if len(m.Contents) > 0 {
for _, msg := range m.Contents { for _, msg := range m.Contents {
data[i] = 0x12 data[i] = 0x12
@ -153,13 +193,14 @@ func (m *Log) MarshalTo(data []byte) (int, error) {
i += n i += n
} }
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
i += copy(data[i:], m.XXX_unrecognized) i += copy(data[i:], m.XXXUnrecognized)
} }
return i, nil return i, nil
} }
func (m *Log_Content) Marshal() (data []byte, err error) { // Marshal LogContent
func (m *LogContent) Marshal() (data []byte, err error) {
size := m.Size() size := m.Size()
data = make([]byte, size) data = make([]byte, size)
n, err := m.MarshalTo(data) n, err := m.MarshalTo(data)
@ -169,33 +210,34 @@ func (m *Log_Content) Marshal() (data []byte, err error) {
return data[:n], nil return data[:n], nil
} }
func (m *Log_Content) MarshalTo(data []byte) (int, error) { // MarshalTo logcontent to data
func (m *LogContent) MarshalTo(data []byte) (int, error) {
var i int var i int
_ = i _ = i
var l int var l int
_ = l _ = l
if m.Key == nil { if m.Key == nil {
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Key") return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Key")
} else {
data[i] = 0xa
i++
i = encodeVarintLog(data, i, uint64(len(*m.Key)))
i += copy(data[i:], *m.Key)
} }
data[i] = 0xa
i++
i = encodeVarintLog(data, i, uint64(len(*m.Key)))
i += copy(data[i:], *m.Key)
if m.Value == nil { if m.Value == nil {
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Value") return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Value")
} else {
data[i] = 0x12
i++
i = encodeVarintLog(data, i, uint64(len(*m.Value)))
i += copy(data[i:], *m.Value)
} }
if m.XXX_unrecognized != nil { data[i] = 0x12
i += copy(data[i:], m.XXX_unrecognized) i++
i = encodeVarintLog(data, i, uint64(len(*m.Value)))
i += copy(data[i:], *m.Value)
if m.XXXUnrecognized != nil {
i += copy(data[i:], m.XXXUnrecognized)
} }
return i, nil return i, nil
} }
// Marshal LogGroup
func (m *LogGroup) Marshal() (data []byte, err error) { func (m *LogGroup) Marshal() (data []byte, err error) {
size := m.Size() size := m.Size()
data = make([]byte, size) data = make([]byte, size)
@ -206,6 +248,7 @@ func (m *LogGroup) Marshal() (data []byte, err error) {
return data[:n], nil return data[:n], nil
} }
// MarshalTo LogGroup to data
func (m *LogGroup) MarshalTo(data []byte) (int, error) { func (m *LogGroup) MarshalTo(data []byte) (int, error) {
var i int var i int
_ = i _ = i
@ -241,12 +284,13 @@ func (m *LogGroup) MarshalTo(data []byte) (int, error) {
i = encodeVarintLog(data, i, uint64(len(*m.Source))) i = encodeVarintLog(data, i, uint64(len(*m.Source)))
i += copy(data[i:], *m.Source) i += copy(data[i:], *m.Source)
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
i += copy(data[i:], m.XXX_unrecognized) i += copy(data[i:], m.XXXUnrecognized)
} }
return i, nil return i, nil
} }
// Marshal LogGroupList
func (m *LogGroupList) Marshal() (data []byte, err error) { func (m *LogGroupList) Marshal() (data []byte, err error) {
size := m.Size() size := m.Size()
data = make([]byte, size) data = make([]byte, size)
@ -257,6 +301,7 @@ func (m *LogGroupList) Marshal() (data []byte, err error) {
return data[:n], nil return data[:n], nil
} }
// MarshalTo LogGroupList to data
func (m *LogGroupList) MarshalTo(data []byte) (int, error) { func (m *LogGroupList) MarshalTo(data []byte) (int, error) {
var i int var i int
_ = i _ = i
@ -274,8 +319,8 @@ func (m *LogGroupList) MarshalTo(data []byte) (int, error) {
i += n i += n
} }
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
i += copy(data[i:], m.XXX_unrecognized) i += copy(data[i:], m.XXXUnrecognized)
} }
return i, nil return i, nil
} }
@ -307,6 +352,8 @@ func encodeVarintLog(data []byte, offset int, v uint64) int {
data[offset] = uint8(v) data[offset] = uint8(v)
return offset + 1 return offset + 1
} }
// Size return the log's size
func (m *Log) Size() (n int) { func (m *Log) Size() (n int) {
var l int var l int
_ = l _ = l
@ -319,13 +366,14 @@ func (m *Log) Size() (n int) {
n += 1 + l + sovLog(uint64(l)) n += 1 + l + sovLog(uint64(l))
} }
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
n += len(m.XXX_unrecognized) n += len(m.XXXUnrecognized)
} }
return n return n
} }
func (m *Log_Content) Size() (n int) { // Size return LogContent size based on Key and Value
func (m *LogContent) Size() (n int) {
var l int var l int
_ = l _ = l
if m.Key != nil { if m.Key != nil {
@ -336,12 +384,13 @@ func (m *Log_Content) Size() (n int) {
l = len(*m.Value) l = len(*m.Value)
n += 1 + l + sovLog(uint64(l)) n += 1 + l + sovLog(uint64(l))
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
n += len(m.XXX_unrecognized) n += len(m.XXXUnrecognized)
} }
return n return n
} }
// Size return LogGroup size based on Logs
func (m *LogGroup) Size() (n int) { func (m *LogGroup) Size() (n int) {
var l int var l int
_ = l _ = l
@ -363,12 +412,13 @@ func (m *LogGroup) Size() (n int) {
l = len(*m.Source) l = len(*m.Source)
n += 1 + l + sovLog(uint64(l)) n += 1 + l + sovLog(uint64(l))
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
n += len(m.XXX_unrecognized) n += len(m.XXXUnrecognized)
} }
return n return n
} }
// Size return LogGroupList size
func (m *LogGroupList) Size() (n int) { func (m *LogGroupList) Size() (n int) {
var l int var l int
_ = l _ = l
@ -378,8 +428,8 @@ func (m *LogGroupList) Size() (n int) {
n += 1 + l + sovLog(uint64(l)) n += 1 + l + sovLog(uint64(l))
} }
} }
if m.XXX_unrecognized != nil { if m.XXXUnrecognized != nil {
n += len(m.XXX_unrecognized) n += len(m.XXXUnrecognized)
} }
return n return n
} }
@ -395,8 +445,10 @@ func sovLog(x uint64) (n int) {
return n return n
} }
func sozLog(x uint64) (n int) { func sozLog(x uint64) (n int) {
return sovLog(uint64((x << 1) ^ uint64((int64(x) >> 63)))) return sovLog((x << 1) ^ (x >> 63))
} }
// Unmarshal data to log
func (m *Log) Unmarshal(data []byte) error { func (m *Log) Unmarshal(data []byte) error {
var hasFields [1]uint64 var hasFields [1]uint64
l := len(data) l := len(data)
@ -474,7 +526,7 @@ func (m *Log) Unmarshal(data []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Contents = append(m.Contents, &Log_Content{}) m.Contents = append(m.Contents, &LogContent{})
if err := m.Contents[len(m.Contents)-1].Unmarshal(data[iNdEx:postIndex]); err != nil { if err := m.Contents[len(m.Contents)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -491,7 +543,7 @@ func (m *Log) Unmarshal(data []byte) error {
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...) m.XXXUnrecognized = append(m.XXXUnrecognized, data[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -504,7 +556,9 @@ func (m *Log) Unmarshal(data []byte) error {
} }
return nil return nil
} }
func (m *Log_Content) Unmarshal(data []byte) error {
// Unmarshal data to LogContent
func (m *LogContent) Unmarshal(data []byte) error {
var hasFields [1]uint64 var hasFields [1]uint64
l := len(data) l := len(data)
iNdEx := 0 iNdEx := 0
@ -608,7 +662,7 @@ func (m *Log_Content) Unmarshal(data []byte) error {
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...) m.XXXUnrecognized = append(m.XXXUnrecognized, data[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -624,6 +678,8 @@ func (m *Log_Content) Unmarshal(data []byte) error {
} }
return nil return nil
} }
// Unmarshal data to LogGroup
func (m *LogGroup) Unmarshal(data []byte) error { func (m *LogGroup) Unmarshal(data []byte) error {
l := len(data) l := len(data)
iNdEx := 0 iNdEx := 0
@ -786,7 +842,7 @@ func (m *LogGroup) Unmarshal(data []byte) error {
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...) m.XXXUnrecognized = append(m.XXXUnrecognized, data[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -796,6 +852,8 @@ func (m *LogGroup) Unmarshal(data []byte) error {
} }
return nil return nil
} }
// Unmarshal data to LogGroupList
func (m *LogGroupList) Unmarshal(data []byte) error { func (m *LogGroupList) Unmarshal(data []byte) error {
l := len(data) l := len(data)
iNdEx := 0 iNdEx := 0
@ -868,7 +926,7 @@ func (m *LogGroupList) Unmarshal(data []byte) error {
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...) m.XXXUnrecognized = append(m.XXXUnrecognized, data[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -878,6 +936,7 @@ func (m *LogGroupList) Unmarshal(data []byte) error {
} }
return nil return nil
} }
func skipLog(data []byte) (n int, err error) { func skipLog(data []byte) (n int, err error) {
l := len(data) l := len(data)
iNdEx := 0 iNdEx := 0
@ -940,7 +999,7 @@ func skipLog(data []byte) (n int, err error) {
case 3: case 3:
for { for {
var innerWire uint64 var innerWire uint64
var start int = iNdEx var start = iNdEx
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return 0, ErrIntOverflowLog return 0, ErrIntOverflowLog
@ -977,8 +1036,3 @@ func skipLog(data []byte) (n int, err error) {
} }
panic("unreachable") panic("unreachable")
} }
var (
ErrInvalidLengthLog = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowLog = fmt.Errorf("proto: integer overflow")
)

View File

@ -1,5 +1,6 @@
package alils package alils
// InputDetail define log detail
type InputDetail struct { type InputDetail struct {
LogType string `json:"logType"` LogType string `json:"logType"`
LogPath string `json:"logPath"` LogPath string `json:"logPath"`
@ -14,11 +15,13 @@ type InputDetail struct {
TopicFormat string `json:"topicFormat"` TopicFormat string `json:"topicFormat"`
} }
// OutputDetail define the output detail
type OutputDetail struct { type OutputDetail struct {
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
LogStoreName string `json:"logstoreName"` LogStoreName string `json:"logstoreName"`
} }
// LogConfig define Log Config
type LogConfig struct { type LogConfig struct {
Name string `json:"configName"` Name string `json:"configName"`
InputType string `json:"inputType"` InputType string `json:"inputType"`

View File

@ -1,5 +1,5 @@
/* /*
Package sls implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS). Package alils implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS).
For more description about SLS, please read this article: For more description about SLS, please read this article:
http://gitlab.alibaba-inc.com/sls/doc. http://gitlab.alibaba-inc.com/sls/doc.
@ -20,19 +20,20 @@ type errorMessage struct {
Message string `json:"errorMessage"` Message string `json:"errorMessage"`
} }
// LogProject Define the Ali Project detail
type LogProject struct { type LogProject struct {
Name string // Project name Name string // Project name
Endpoint string // IP or hostname of SLS endpoint Endpoint string // IP or hostname of SLS endpoint
AccessKeyId string AccessKeyID string
AccessKeySecret string AccessKeySecret string
} }
// NewLogProject creates a new SLS project. // NewLogProject creates a new SLS project.
func NewLogProject(name, endpoint, accessKeyId, accessKeySecret string) (p *LogProject, err error) { func NewLogProject(name, endpoint, AccessKeyID, accessKeySecret string) (p *LogProject, err error) {
p = &LogProject{ p = &LogProject{
Name: name, Name: name,
Endpoint: endpoint, Endpoint: endpoint,
AccessKeyId: accessKeyId, AccessKeyID: AccessKeyID,
AccessKeySecret: accessKeySecret, AccessKeySecret: accessKeySecret,
} }
return p, nil return p, nil

View File

@ -12,6 +12,7 @@ import (
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
) )
// LogStore Store the logs
type LogStore struct { type LogStore struct {
Name string `json:"logstoreName"` Name string `json:"logstoreName"`
TTL int TTL int
@ -23,6 +24,7 @@ type LogStore struct {
project *LogProject project *LogProject
} }
// Shard define the Log Shard
type Shard struct { type Shard struct {
ShardID int `json:"shardID"` ShardID int `json:"shardID"`
} }
@ -116,16 +118,16 @@ func (s *LogStore) PutLogs(lg *LogGroup) (err error) {
return return
} }
// GetCursor gets log cursor of one shard specified by shardId. // GetCursor gets log cursor of one shard specified by shardID.
// The from can be in three form: a) unix timestamp in seccond, b) "begin", c) "end". // The from can be in three form: a) unix timestamp in seccond, b) "begin", c) "end".
// For more detail please read: http://gitlab.alibaba-inc.com/sls/doc/blob/master/api/shard.md#logstore // For more detail please read: http://gitlab.alibaba-inc.com/sls/doc/blob/master/api/shard.md#logstore
func (s *LogStore) GetCursor(shardId int, from string) (cursor string, err error) { func (s *LogStore) GetCursor(shardID int, from string) (cursor string, err error) {
h := map[string]string{ h := map[string]string{
"x-sls-bodyrawsize": "0", "x-sls-bodyrawsize": "0",
} }
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=cursor&from=%v", uri := fmt.Sprintf("/logstores/%v/shards/%v?type=cursor&from=%v",
s.Name, shardId, from) s.Name, shardID, from)
r, err := request(s.project, "GET", uri, h, nil) r, err := request(s.project, "GET", uri, h, nil)
if err != nil { if err != nil {
@ -163,10 +165,10 @@ func (s *LogStore) GetCursor(shardId int, from string) (cursor string, err error
return return
} }
// GetLogsBytes gets logs binary data from shard specified by shardId according cursor. // GetLogsBytes gets logs binary data from shard specified by shardID according cursor.
// The logGroupMaxCount is the max number of logGroup could be returned. // The logGroupMaxCount is the max number of logGroup could be returned.
// The nextCursor is the next curosr can be used to read logs at next time. // The nextCursor is the next curosr can be used to read logs at next time.
func (s *LogStore) GetLogsBytes(shardId int, cursor string, func (s *LogStore) GetLogsBytes(shardID int, cursor string,
logGroupMaxCount int) (out []byte, nextCursor string, err error) { logGroupMaxCount int) (out []byte, nextCursor string, err error) {
h := map[string]string{ h := map[string]string{
@ -176,7 +178,7 @@ func (s *LogStore) GetLogsBytes(shardId int, cursor string,
} }
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=logs&cursor=%v&count=%v", uri := fmt.Sprintf("/logstores/%v/shards/%v?type=logs&cursor=%v&count=%v",
s.Name, shardId, cursor, logGroupMaxCount) s.Name, shardID, cursor, logGroupMaxCount)
r, err := request(s.project, "GET", uri, h, nil) r, err := request(s.project, "GET", uri, h, nil)
if err != nil { if err != nil {
@ -249,13 +251,13 @@ func LogsBytesDecode(data []byte) (gl *LogGroupList, err error) {
return return
} }
// GetLogs gets logs from shard specified by shardId according cursor. // GetLogs gets logs from shard specified by shardID according cursor.
// The logGroupMaxCount is the max number of logGroup could be returned. // The logGroupMaxCount is the max number of logGroup could be returned.
// The nextCursor is the next curosr can be used to read logs at next time. // The nextCursor is the next curosr can be used to read logs at next time.
func (s *LogStore) GetLogs(shardId int, cursor string, func (s *LogStore) GetLogs(shardID int, cursor string,
logGroupMaxCount int) (gl *LogGroupList, nextCursor string, err error) { logGroupMaxCount int) (gl *LogGroupList, nextCursor string, err error) {
out, nextCursor, err := s.GetLogsBytes(shardId, cursor, logGroupMaxCount) out, nextCursor, err := s.GetLogsBytes(shardID, cursor, logGroupMaxCount)
if err != nil { if err != nil {
return return
} }

View File

@ -8,18 +8,20 @@ import (
"net/http/httputil" "net/http/httputil"
) )
type MachinGroupAttribute struct { // MachineGroupAttribute define the Attribute
type MachineGroupAttribute struct {
ExternalName string `json:"externalName"` ExternalName string `json:"externalName"`
TopicName string `json:"groupTopic"` TopicName string `json:"groupTopic"`
} }
// MachineGroup define the machine Group
type MachineGroup struct { type MachineGroup struct {
Name string `json:"groupName"` Name string `json:"groupName"`
Type string `json:"groupType"` Type string `json:"groupType"`
MachineIdType string `json:"machineIdentifyType"` MachineIDType string `json:"machineIdentifyType"`
MachineIdList []string `json:"machineList"` MachineIDList []string `json:"machineList"`
Attribute MachinGroupAttribute `json:"groupAttribute"` Attribute MachineGroupAttribute `json:"groupAttribute"`
CreateTime uint32 CreateTime uint32
LastModifyTime uint32 LastModifyTime uint32
@ -27,12 +29,14 @@ type MachineGroup struct {
project *LogProject project *LogProject
} }
// Machine define the Machine
type Machine struct { type Machine struct {
IP string IP string
UniqueId string `json:"machine-uniqueid"` UniqueID string `json:"machine-uniqueid"`
UserdefinedId string `json:"userdefined-id"` UserdefinedID string `json:"userdefined-id"`
} }
// MachineList define the Machine List
type MachineList struct { type MachineList struct {
Total int Total int
Machines []*Machine Machines []*Machine

View File

@ -33,12 +33,12 @@ func request(project *LogProject, method, uri string, headers map[string]string,
} }
// Calc Authorization // Calc Authorization
// Authorization = "SLS <AccessKeyId>:<Signature>" // Authorization = "SLS <AccessKeyID>:<Signature>"
digest, err := signature(project, method, uri, headers) digest, err := signature(project, method, uri, headers)
if err != nil { if err != nil {
return return
} }
auth := fmt.Sprintf("SLS %v:%v", project.AccessKeyId, digest) auth := fmt.Sprintf("SLS %v:%v", project.AccessKeyID, digest)
headers["Authorization"] = auth headers["Authorization"] = auth
// Initialize http request // Initialize http request

View File

@ -76,7 +76,7 @@ func signature(project *LogProject, method, uri string,
var keys sort.StringSlice var keys sort.StringSlice
vals := u.Query() vals := u.Query()
for k, _ := range vals { for k := range vals {
keys = append(keys, k) keys = append(keys, k)
} }
@ -109,4 +109,3 @@ func signature(project *LogProject, method, uri string,
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil)) digest = base64.StdEncoding.EncodeToString(mac.Sum(nil))
return return
} }

View File

@ -361,7 +361,7 @@ func isParameterChar(b byte) bool {
} }
func (cw *ansiColorWriter) Write(p []byte) (int, error) { func (cw *ansiColorWriter) Write(p []byte) (int, error) {
r, nw, first, last := 0, 0, 0, 0 var r, nw, first, last int
if cw.mode != DiscardNonColorEscSeq { if cw.mode != DiscardNonColorEscSeq {
cw.state = outsideCsiCode cw.state = outsideCsiCode
cw.resetBuffer() cw.resetBuffer()

View File

@ -41,7 +41,7 @@ var colors = []brush{
newBrush("1;33"), // Warning yellow newBrush("1;33"), // Warning yellow
newBrush("1;32"), // Notice green newBrush("1;32"), // Notice green
newBrush("1;34"), // Informational blue newBrush("1;34"), // Informational blue
newBrush("1;34"), // Debug blue newBrush("1;44"), // Debug Background blue
} }
// consoleWriter implements LoggerInterface and writes messages to terminal. // consoleWriter implements LoggerInterface and writes messages to terminal.

View File

@ -170,7 +170,7 @@ func (w *fileLogWriter) initFd() error {
fd := w.fileWriter fd := w.fileWriter
fInfo, err := fd.Stat() fInfo, err := fd.Stat()
if err != nil { if err != nil {
return fmt.Errorf("get stat err: %s\n", err) return fmt.Errorf("get stat err: %s", err)
} }
w.maxSizeCurSize = int(fInfo.Size()) w.maxSizeCurSize = int(fInfo.Size())
w.dailyOpenTime = time.Now() w.dailyOpenTime = time.Now()
@ -193,16 +193,14 @@ func (w *fileLogWriter) dailyRotate(openTime time.Time) {
y, m, d := openTime.Add(24 * time.Hour).Date() y, m, d := openTime.Add(24 * time.Hour).Date()
nextDay := time.Date(y, m, d, 0, 0, 0, 0, openTime.Location()) nextDay := time.Date(y, m, d, 0, 0, 0, 0, openTime.Location())
tm := time.NewTimer(time.Duration(nextDay.UnixNano() - openTime.UnixNano() + 100)) tm := time.NewTimer(time.Duration(nextDay.UnixNano() - openTime.UnixNano() + 100))
select { <-tm.C
case <-tm.C: w.Lock()
w.Lock() if w.needRotate(0, time.Now().Day()) {
if w.needRotate(0, time.Now().Day()) { if err := w.doRotate(time.Now()); err != nil {
if err := w.doRotate(time.Now()); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err)
}
} }
w.Unlock()
} }
w.Unlock()
} }
func (w *fileLogWriter) lines() (int, error) { func (w *fileLogWriter) lines() (int, error) {
@ -261,7 +259,7 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error {
} }
// return error if the last file checked still existed // return error if the last file checked still existed
if err == nil { if err == nil {
return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.Filename) return fmt.Errorf("Rotate: Cannot find free log number to rename %s", w.Filename)
} }
// close fileWriter before rename // close fileWriter before rename
@ -270,7 +268,10 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error {
// Rename the file to its new found name // Rename the file to its new found name
// even if occurs error,we MUST guarantee to restart new logger // even if occurs error,we MUST guarantee to restart new logger
err = os.Rename(w.Filename, fName) err = os.Rename(w.Filename, fName)
err = os.Chmod(fName, os.FileMode(440)) if err != nil {
goto RESTART_LOGGER
}
err = os.Chmod(fName, os.FileMode(0440))
// re-start logger // re-start logger
RESTART_LOGGER: RESTART_LOGGER:
@ -278,13 +279,12 @@ RESTART_LOGGER:
go w.deleteOldLog() go w.deleteOldLog()
if startLoggerErr != nil { if startLoggerErr != nil {
return fmt.Errorf("Rotate StartLogger: %s\n", startLoggerErr) return fmt.Errorf("Rotate StartLogger: %s", startLoggerErr)
} }
if err != nil { if err != nil {
return fmt.Errorf("Rotate: %s\n", err) return fmt.Errorf("Rotate: %s", err)
} }
return nil return nil
} }
func (w *fileLogWriter) deleteOldLog() { func (w *fileLogWriter) deleteOldLog() {

View File

@ -162,7 +162,27 @@ func TestFileRotate_05(t *testing.T) {
testFileDailyRotate(t, fn1, fn2) testFileDailyRotate(t, fn1, fn2)
os.Remove(fn) os.Remove(fn)
} }
func TestFileRotate_06(t *testing.T) { //test file mode
log := NewLogger(10000)
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
log.Debug("debug")
log.Info("info")
log.Notice("notice")
log.Warning("warning")
log.Error("error")
log.Alert("alert")
log.Critical("critical")
log.Emergency("emergency")
rotateName := "test3" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log"
s, _ := os.Lstat(rotateName)
if s.Mode() != 0440 {
os.Remove(rotateName)
os.Remove("test3.log")
t.Fatal("rotate file mode error")
}
os.Remove(rotateName)
os.Remove("test3.log")
}
func testFileRotate(t *testing.T, fn1, fn2 string) { func testFileRotate(t *testing.T, fn1, fn2 string) {
fw := &fileLogWriter{ fw := &fileLogWriter{
Daily: true, Daily: true,

View File

@ -25,11 +25,7 @@ func newJLWriter() Logger {
// Init JLWriter with json config string // Init JLWriter with json config string
func (s *JLWriter) Init(jsonconfig string) error { func (s *JLWriter) Init(jsonconfig string) error {
err := json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
if err != nil {
return err
}
return nil
} }
// WriteMsg write message in smtp writer. // WriteMsg write message in smtp writer.
@ -65,12 +61,10 @@ func (s *JLWriter) WriteMsg(when time.Time, msg string, level int) error {
// Flush implementing method. empty. // Flush implementing method. empty.
func (s *JLWriter) Flush() { func (s *JLWriter) Flush() {
return
} }
// Destroy implementing method. empty. // Destroy implementing method. empty.
func (s *JLWriter) Destroy() { func (s *JLWriter) Destroy() {
return
} }
func init() { func init() {

View File

@ -275,7 +275,7 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string, v ...interface{}) error
line = 0 line = 0
} }
_, filename := path.Split(file) _, filename := path.Split(file)
msg = "[" + filename + ":" + strconv.FormatInt(int64(line), 10) + "] " + msg msg = "[" + filename + ":" + strconv.Itoa(line) + "] " + msg
} }
//set level info in front of filename info //set level info in front of filename info
@ -492,9 +492,9 @@ func (bl *BeeLogger) flush() {
} }
// beeLogger references the used application logger. // beeLogger references the used application logger.
var beeLogger *BeeLogger = NewLogger() var beeLogger = NewLogger()
// GetLogger returns the default BeeLogger // GetBeeLogger returns the default BeeLogger
func GetBeeLogger() *BeeLogger { func GetBeeLogger() *BeeLogger {
return beeLogger return beeLogger
} }
@ -534,6 +534,7 @@ func Reset() {
beeLogger.Reset() beeLogger.Reset()
} }
// Async set the beelogger with Async mode and hold msglen messages
func Async(msgLen ...int64) *BeeLogger { func Async(msgLen ...int64) *BeeLogger {
return beeLogger.Async(msgLen...) return beeLogger.Async(msgLen...)
} }
@ -561,11 +562,7 @@ func SetLogFuncCallDepth(d int) {
// SetLogger sets a new logger. // SetLogger sets a new logger.
func SetLogger(adapter string, config ...string) error { func SetLogger(adapter string, config ...string) error {
err := beeLogger.SetLogger(adapter, config...) return beeLogger.SetLogger(adapter, config...)
if err != nil {
return err
}
return nil
} }
// Emergency logs a message at emergency level. // Emergency logs a message at emergency level.

View File

@ -139,6 +139,11 @@ var (
reset = string([]byte{27, 91, 48, 109}) reset = string([]byte{27, 91, 48, 109})
) )
// ColorByStatus return color by http code
// 2xx return Green
// 3xx return White
// 4xx return Yellow
// 5xx return Red
func ColorByStatus(cond bool, code int) string { func ColorByStatus(cond bool, code int) string {
switch { switch {
case code >= 200 && code < 300: case code >= 200 && code < 300:
@ -152,6 +157,14 @@ func ColorByStatus(cond bool, code int) string {
} }
} }
// ColorByMethod return color by http code
// GET return Blue
// POST return Cyan
// PUT return Yellow
// DELETE return Red
// PATCH return Green
// HEAD return Magenta
// OPTIONS return WHITE
func ColorByMethod(cond bool, method string) string { func ColorByMethod(cond bool, method string) string {
switch method { switch method {
case "GET": case "GET":
@ -173,10 +186,10 @@ func ColorByMethod(cond bool, method string) string {
} }
} }
// Guard Mutex to guarantee atomicity of W32Debug(string) function // Guard Mutex to guarantee atomic of W32Debug(string) function
var mu sync.Mutex var mu sync.Mutex
// Helper method to output colored logs in Windows terminals // W32Debug Helper method to output colored logs in Windows terminals
func W32Debug(msg string) { func W32Debug(msg string) {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()

View File

@ -21,11 +21,7 @@ func newSLACKWriter() Logger {
// Init SLACKWriter with json config string // Init SLACKWriter with json config string
func (s *SLACKWriter) Init(jsonconfig string) error { func (s *SLACKWriter) Init(jsonconfig string) error {
err := json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
if err != nil {
return err
}
return nil
} }
// WriteMsg write message in smtp writer. // WriteMsg write message in smtp writer.
@ -53,12 +49,10 @@ func (s *SLACKWriter) WriteMsg(when time.Time, msg string, level int) error {
// Flush implementing method. empty. // Flush implementing method. empty.
func (s *SLACKWriter) Flush() { func (s *SLACKWriter) Flush() {
return
} }
// Destroy implementing method. empty. // Destroy implementing method. empty.
func (s *SLACKWriter) Destroy() { func (s *SLACKWriter) Destroy() {
return
} }
func init() { func init() {

View File

@ -52,11 +52,7 @@ func newSMTPWriter() Logger {
// "level":LevelError // "level":LevelError
// } // }
func (s *SMTPWriter) Init(jsonconfig string) error { func (s *SMTPWriter) Init(jsonconfig string) error {
err := json.Unmarshal([]byte(jsonconfig), s) return json.Unmarshal([]byte(jsonconfig), s)
if err != nil {
return err
}
return nil
} }
func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth { func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth {
@ -106,7 +102,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
if err != nil { if err != nil {
return err return err
} }
_, err = w.Write([]byte(msgContent)) _, err = w.Write(msgContent)
if err != nil { if err != nil {
return err return err
} }
@ -116,12 +112,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
return err return err
} }
err = client.Quit() return client.Quit()
if err != nil {
return err
}
return nil
} }
// WriteMsg write message in smtp writer. // WriteMsg write message in smtp writer.
@ -147,12 +138,10 @@ func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error {
// Flush implementing method. empty. // Flush implementing method. empty.
func (s *SMTPWriter) Flush() { func (s *SMTPWriter) Flush() {
return
} }
// Destroy implementing method. empty. // Destroy implementing method. empty.
func (s *SMTPWriter) Destroy() { func (s *SMTPWriter) Destroy() {
return
} }
func init() { func init() {

View File

@ -267,13 +267,12 @@ func addPrefix(t *Tree, prefix string) {
addPrefix(t.wildcard, prefix) addPrefix(t.wildcard, prefix)
} }
for _, l := range t.leaves { for _, l := range t.leaves {
if c, ok := l.runObject.(*controllerInfo); ok { if c, ok := l.runObject.(*ControllerInfo); ok {
if !strings.HasPrefix(c.pattern, prefix) { if !strings.HasPrefix(c.pattern, prefix) {
c.pattern = prefix + c.pattern c.pattern = prefix + c.pattern
} }
} }
} }
} }
// NSCond is Namespace Condition // NSCond is Namespace Condition
@ -284,16 +283,16 @@ func NSCond(cond namespaceCond) LinkNamespace {
} }
// NSBefore Namespace BeforeRouter filter // NSBefore Namespace BeforeRouter filter
func NSBefore(filiterList ...FilterFunc) LinkNamespace { func NSBefore(filterList ...FilterFunc) LinkNamespace {
return func(ns *Namespace) { return func(ns *Namespace) {
ns.Filter("before", filiterList...) ns.Filter("before", filterList...)
} }
} }
// NSAfter add Namespace FinishRouter filter // NSAfter add Namespace FinishRouter filter
func NSAfter(filiterList ...FilterFunc) LinkNamespace { func NSAfter(filterList ...FilterFunc) LinkNamespace {
return func(ns *Namespace) { return func(ns *Namespace) {
ns.Filter("after", filiterList...) ns.Filter("after", filterList...)
} }
} }

View File

@ -139,10 +139,7 @@ func TestNamespaceCond(t *testing.T) {
ns := NewNamespace("/v2") ns := NewNamespace("/v2")
ns.Cond(func(ctx *context.Context) bool { ns.Cond(func(ctx *context.Context) bool {
if ctx.Input.Domain() == "beego.me" { return ctx.Input.Domain() == "beego.me"
return true
}
return false
}). }).
AutoRouter(&TestController{}) AutoRouter(&TestController{})
AddNamespace(ns) AddNamespace(ns)

View File

@ -150,7 +150,7 @@ func (d *commandSyncDb) Run() error {
} }
for _, fi := range mi.fields.fieldsDB { for _, fi := range mi.fields.fieldsDB {
if _, ok := columns[fi.column]; ok == false { if _, ok := columns[fi.column]; !ok {
fields = append(fields, fi) fields = append(fields, fi)
} }
} }
@ -175,7 +175,7 @@ func (d *commandSyncDb) Run() error {
} }
for _, idx := range indexes[mi.table] { for _, idx := range indexes[mi.table] {
if d.al.DbBaser.IndexExists(db, idx.Table, idx.Name) == false { if !d.al.DbBaser.IndexExists(db, idx.Table, idx.Name) {
if !d.noInfo { if !d.noInfo {
fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table) fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table)
} }

View File

@ -89,7 +89,7 @@ checkColumn:
col = T["float64"] col = T["float64"]
case TypeDecimalField: case TypeDecimalField:
s := T["float64-decimal"] s := T["float64-decimal"]
if strings.Index(s, "%d") == -1 { if !strings.Contains(s, "%d") {
col = s col = s
} else { } else {
col = fmt.Sprintf(s, fi.digits, fi.decimals) col = fmt.Sprintf(s, fi.digits, fi.decimals)
@ -120,7 +120,7 @@ func getColumnAddQuery(al *alias, fi *fieldInfo) string {
Q := al.DbBaser.TableQuote() Q := al.DbBaser.TableQuote()
typ := getColumnTyp(al, fi) typ := getColumnTyp(al, fi)
if fi.null == false { if !fi.null {
typ += " " + "NOT NULL" typ += " " + "NOT NULL"
} }
@ -172,7 +172,7 @@ func getDbCreateSQL(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
} else { } else {
column += col column += col
if fi.null == false { if !fi.null {
column += " " + "NOT NULL" column += " " + "NOT NULL"
} }
@ -192,7 +192,7 @@ func getDbCreateSQL(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
} }
} }
if strings.Index(column, "%COL%") != -1 { if strings.Contains(column, "%COL%") {
column = strings.Replace(column, "%COL%", fi.column, -1) column = strings.Replace(column, "%COL%", fi.column, -1)
} }

View File

@ -48,7 +48,7 @@ var (
"lte": true, "lte": true,
"eq": true, "eq": true,
"nq": true, "nq": true,
"ne": true, "ne": true,
"startswith": true, "startswith": true,
"endswith": true, "endswith": true,
"istartswith": true, "istartswith": true,
@ -87,7 +87,7 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string,
} else { } else {
panic(fmt.Errorf("wrong db field/column name `%s` for model `%s`", column, mi.fullName)) panic(fmt.Errorf("wrong db field/column name `%s` for model `%s`", column, mi.fullName))
} }
if fi.dbcol == false || fi.auto && skipAuto { if !fi.dbcol || fi.auto && skipAuto {
continue continue
} }
value, err := d.collectFieldValue(mi, fi, ind, insert, tz) value, err := d.collectFieldValue(mi, fi, ind, insert, tz)
@ -224,7 +224,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val
value = nil value = nil
} }
} }
if fi.null == false && value == nil { if !fi.null && value == nil {
return nil, fmt.Errorf("field `%s` cannot be NULL", fi.fullName) return nil, fmt.Errorf("field `%s` cannot be NULL", fi.fullName)
} }
} }
@ -271,7 +271,7 @@ func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string,
dbcols := make([]string, 0, len(mi.fields.dbcols)) dbcols := make([]string, 0, len(mi.fields.dbcols))
marks := make([]string, 0, len(mi.fields.dbcols)) marks := make([]string, 0, len(mi.fields.dbcols))
for _, fi := range mi.fields.fieldsDB { for _, fi := range mi.fields.fieldsDB {
if fi.auto == false { if !fi.auto {
dbcols = append(dbcols, fi.column) dbcols = append(dbcols, fi.column)
marks = append(marks, "?") marks = append(marks, "?")
} }
@ -326,7 +326,7 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Lo
} else { } else {
// default use pk value as where condtion. // default use pk value as where condtion.
pkColumn, pkValue, ok := getExistPk(mi, ind) pkColumn, pkValue, ok := getExistPk(mi, ind)
if ok == false { if !ok {
return ErrMissPK return ErrMissPK
} }
whereCols = []string{pkColumn} whereCols = []string{pkColumn}
@ -507,10 +507,9 @@ func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a
case DRPostgres: case DRPostgres:
if len(args) == 0 { if len(args) == 0 {
return 0, fmt.Errorf("`%s` use InsertOrUpdate must have a conflict column", a.DriverName) return 0, fmt.Errorf("`%s` use InsertOrUpdate must have a conflict column", a.DriverName)
} else {
args0 = strings.ToLower(args[0])
iouStr = fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET", args0)
} }
args0 = strings.ToLower(args[0])
iouStr = fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET", args0)
default: default:
return 0, fmt.Errorf("`%s` nonsupport InsertOrUpdate in beego", a.DriverName) return 0, fmt.Errorf("`%s` nonsupport InsertOrUpdate in beego", a.DriverName)
} }
@ -592,7 +591,7 @@ func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a
row := q.QueryRow(query, values...) row := q.QueryRow(query, values...)
var id int64 var id int64
err = row.Scan(&id) err = row.Scan(&id)
if err.Error() == `pq: syntax error at or near "ON"` { if err != nil && err.Error() == `pq: syntax error at or near "ON"` {
err = fmt.Errorf("postgres version must 9.5 or higher") err = fmt.Errorf("postgres version must 9.5 or higher")
} }
return id, err return id, err
@ -601,7 +600,7 @@ func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a
// execute update sql dbQuerier with given struct reflect.Value. // execute update sql dbQuerier with given struct reflect.Value.
func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) {
pkName, pkValue, ok := getExistPk(mi, ind) pkName, pkValue, ok := getExistPk(mi, ind)
if ok == false { if !ok {
return 0, ErrMissPK return 0, ErrMissPK
} }
@ -654,7 +653,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.
} else { } else {
// default use pk value as where condtion. // default use pk value as where condtion.
pkColumn, pkValue, ok := getExistPk(mi, ind) pkColumn, pkValue, ok := getExistPk(mi, ind)
if ok == false { if !ok {
return 0, ErrMissPK return 0, ErrMissPK
} }
whereCols = []string{pkColumn} whereCols = []string{pkColumn}
@ -699,7 +698,7 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
columns := make([]string, 0, len(params)) columns := make([]string, 0, len(params))
values := make([]interface{}, 0, len(params)) values := make([]interface{}, 0, len(params))
for col, val := range params { for col, val := range params {
if fi, ok := mi.fields.GetByAny(col); ok == false || fi.dbcol == false { if fi, ok := mi.fields.GetByAny(col); !ok || !fi.dbcol {
panic(fmt.Errorf("wrong field/column name `%s`", col)) panic(fmt.Errorf("wrong field/column name `%s`", col))
} else { } else {
columns = append(columns, fi.column) columns = append(columns, fi.column)
@ -929,7 +928,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
if hasRel { if hasRel {
for _, fi := range mi.fields.fieldsDB { for _, fi := range mi.fields.fieldsDB {
if fi.fieldType&IsRelField > 0 { if fi.fieldType&IsRelField > 0 {
if maps[fi.column] == false { if !maps[fi.column] {
tCols = append(tCols, fi.column) tCols = append(tCols, fi.column)
} }
} }
@ -987,7 +986,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
var cnt int64 var cnt int64
for rs.Next() { for rs.Next() {
if one && cnt == 0 || one == false { if one && cnt == 0 || !one {
if err := rs.Scan(refs...); err != nil { if err := rs.Scan(refs...); err != nil {
return 0, err return 0, err
} }
@ -1067,7 +1066,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
cnt++ cnt++
} }
if one == false { if !one {
if cnt > 0 { if cnt > 0 {
ind.Set(slice) ind.Set(slice)
} else { } else {
@ -1110,7 +1109,7 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition
// generate sql with replacing operator string placeholders and replaced values. // generate sql with replacing operator string placeholders and replaced values.
func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) {
sql := "" var sql string
params := getFlatParams(fi, args, tz) params := getFlatParams(fi, args, tz)
if len(params) == 0 { if len(params) == 0 {
@ -1357,7 +1356,7 @@ end:
func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field reflect.Value) (interface{}, error) { func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field reflect.Value) (interface{}, error) {
fieldType := fi.fieldType fieldType := fi.fieldType
isNative := fi.isFielder == false isNative := !fi.isFielder
setValue: setValue:
switch { switch {
@ -1533,7 +1532,7 @@ setValue:
} }
} }
if isNative == false { if !isNative {
fd := field.Addr().Interface().(Fielder) fd := field.Addr().Interface().(Fielder)
err := fd.SetRaw(value) err := fd.SetRaw(value)
if err != nil { if err != nil {
@ -1594,7 +1593,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
infos = make([]*fieldInfo, 0, len(exprs)) infos = make([]*fieldInfo, 0, len(exprs))
for _, ex := range exprs { for _, ex := range exprs {
index, name, fi, suc := tables.parseExprs(mi, strings.Split(ex, ExprSep)) index, name, fi, suc := tables.parseExprs(mi, strings.Split(ex, ExprSep))
if suc == false { if !suc {
panic(fmt.Errorf("unknown field/column name `%s`", ex)) panic(fmt.Errorf("unknown field/column name `%s`", ex))
} }
cols = append(cols, fmt.Sprintf("%s.%s%s%s %s%s%s", index, Q, fi.column, Q, Q, name, Q)) cols = append(cols, fmt.Sprintf("%s.%s%s%s %s%s%s", index, Q, fi.column, Q, Q, name, Q))
@ -1733,7 +1732,7 @@ func (d *dbBase) TableQuote() string {
return "`" return "`"
} }
// replace value placeholer in parametered sql string. // replace value placeholder in parametered sql string.
func (d *dbBase) ReplaceMarks(query *string) { func (d *dbBase) ReplaceMarks(query *string) {
// default use `?` as mark, do nothing // default use `?` as mark, do nothing
} }

View File

@ -60,6 +60,8 @@ var (
"sqlite3": DRSqlite, "sqlite3": DRSqlite,
"tidb": DRTiDB, "tidb": DRTiDB,
"oracle": DROracle, "oracle": DROracle,
"oci8": DROracle, // github.com/mattn/go-oci8
"ora": DROracle, //https://github.com/rana/ora
} }
dbBasers = map[DriverType]dbBaser{ dbBasers = map[DriverType]dbBaser{
DRMySQL: newdbBaseMysql(), DRMySQL: newdbBaseMysql(),
@ -186,7 +188,7 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
return nil, fmt.Errorf("register db Ping `%s`, %s", aliasName, err.Error()) return nil, fmt.Errorf("register db Ping `%s`, %s", aliasName, err.Error())
} }
if dataBaseCache.add(aliasName, al) == false { if !dataBaseCache.add(aliasName, al) {
return nil, fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName) return nil, fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName)
} }
@ -244,11 +246,11 @@ end:
// RegisterDriver Register a database driver use specify driver name, this can be definition the driver is which database type. // RegisterDriver Register a database driver use specify driver name, this can be definition the driver is which database type.
func RegisterDriver(driverName string, typ DriverType) error { func RegisterDriver(driverName string, typ DriverType) error {
if t, ok := drivers[driverName]; ok == false { if t, ok := drivers[driverName]; !ok {
drivers[driverName] = typ drivers[driverName] = typ
} else { } else {
if t != typ { if t != typ {
return fmt.Errorf("driverName `%s` db driver already registered and is other type\n", driverName) return fmt.Errorf("driverName `%s` db driver already registered and is other type", driverName)
} }
} }
return nil return nil
@ -259,7 +261,7 @@ func SetDataBaseTZ(aliasName string, tz *time.Location) error {
if al, ok := dataBaseCache.get(aliasName); ok { if al, ok := dataBaseCache.get(aliasName); ok {
al.TZ = tz al.TZ = tz
} else { } else {
return fmt.Errorf("DataBase alias name `%s` not registered\n", aliasName) return fmt.Errorf("DataBase alias name `%s` not registered", aliasName)
} }
return nil return nil
} }
@ -294,5 +296,5 @@ func GetDB(aliasNames ...string) (*sql.DB, error) {
if ok { if ok {
return al.DB, nil return al.DB, nil
} }
return nil, fmt.Errorf("DataBase of alias name `%s` not found\n", name) return nil, fmt.Errorf("DataBase of alias name `%s` not found", name)
} }

View File

@ -103,8 +103,7 @@ func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool
// If no will insert // If no will insert
// Add "`" for mysql sql building // Add "`" for mysql sql building
func (d *dbBaseMysql) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) { func (d *dbBaseMysql) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) {
var iouStr string
iouStr := ""
argsMap := map[string]string{} argsMap := map[string]string{}
iouStr = "ON DUPLICATE KEY UPDATE" iouStr = "ON DUPLICATE KEY UPDATE"

View File

@ -134,7 +134,7 @@ func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var tmp, index sql.NullString var tmp, index sql.NullString
rows.Scan(&tmp, &index, &tmp) rows.Scan(&tmp, &index, &tmp, &tmp, &tmp)
if name == index.String { if name == index.String {
return true return true
} }

View File

@ -63,7 +63,7 @@ func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool)
// add table info to collection. // add table info to collection.
func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) { func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) {
name := strings.Join(names, ExprSep) name := strings.Join(names, ExprSep)
if _, ok := t.tablesM[name]; ok == false { if _, ok := t.tablesM[name]; !ok {
i := len(t.tables) + 1 i := len(t.tables) + 1
jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil} jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil}
t.tablesM[name] = jt t.tablesM[name] = jt
@ -261,7 +261,7 @@ loopFor:
fiN, okN = mmi.fields.GetByAny(exprs[i+1]) fiN, okN = mmi.fields.GetByAny(exprs[i+1])
} }
if isRel && (fi.mi.isThrough == false || num != i) { if isRel && (!fi.mi.isThrough || num != i) {
if fi.null || t.skipEnd { if fi.null || t.skipEnd {
inner = false inner = false
} }
@ -364,7 +364,7 @@ func (t *dbTables) getCondSQL(cond *Condition, sub bool, tz *time.Location) (whe
} }
index, _, fi, suc := t.parseExprs(mi, exprs) index, _, fi, suc := t.parseExprs(mi, exprs)
if suc == false { if !suc {
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(p.exprs, ExprSep))) panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(p.exprs, ExprSep)))
} }
@ -383,7 +383,7 @@ func (t *dbTables) getCondSQL(cond *Condition, sub bool, tz *time.Location) (whe
} }
} }
if sub == false && where != "" { if !sub && where != "" {
where = "WHERE " + where where = "WHERE " + where
} }
@ -403,7 +403,7 @@ func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) {
exprs := strings.Split(group, ExprSep) exprs := strings.Split(group, ExprSep)
index, _, fi, suc := t.parseExprs(t.mi, exprs) index, _, fi, suc := t.parseExprs(t.mi, exprs)
if suc == false { if !suc {
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep))) panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
} }
@ -432,7 +432,7 @@ func (t *dbTables) getOrderSQL(orders []string) (orderSQL string) {
exprs := strings.Split(order, ExprSep) exprs := strings.Split(order, ExprSep)
index, _, fi, suc := t.parseExprs(t.mi, exprs) index, _, fi, suc := t.parseExprs(t.mi, exprs)
if suc == false { if !suc {
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep))) panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
} }

View File

@ -128,7 +128,7 @@ func bootStrap() {
if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) { if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) {
pn := fi.relThrough[:i] pn := fi.relThrough[:i]
rmi, ok := modelCache.getByFullName(fi.relThrough) rmi, ok := modelCache.getByFullName(fi.relThrough)
if ok == false || pn != rmi.pkg { if !ok || pn != rmi.pkg {
err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.fullName, fi.relThrough) err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.fullName, fi.relThrough)
goto end goto end
} }
@ -171,7 +171,7 @@ func bootStrap() {
break break
} }
} }
if inModel == false { if !inModel {
rmi := fi.relModelInfo rmi := fi.relModelInfo
ffi := new(fieldInfo) ffi := new(fieldInfo)
ffi.name = mi.name ffi.name = mi.name
@ -185,7 +185,7 @@ func bootStrap() {
} else { } else {
ffi.fieldType = RelReverseMany ffi.fieldType = RelReverseMany
} }
if rmi.fields.Add(ffi) == false { if !rmi.fields.Add(ffi) {
added := false added := false
for cnt := 0; cnt < 5; cnt++ { for cnt := 0; cnt < 5; cnt++ {
ffi.name = fmt.Sprintf("%s%d", mi.name, cnt) ffi.name = fmt.Sprintf("%s%d", mi.name, cnt)
@ -195,7 +195,7 @@ func bootStrap() {
break break
} }
} }
if added == false { if !added {
panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName)) panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName))
} }
} }
@ -248,7 +248,7 @@ func bootStrap() {
break mForA break mForA
} }
} }
if found == false { if !found {
err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
goto end goto end
} }
@ -267,7 +267,7 @@ func bootStrap() {
break mForB break mForB
} }
} }
if found == false { if !found {
mForC: mForC:
for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] { for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] {
conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough || conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough ||
@ -287,7 +287,7 @@ func bootStrap() {
} }
} }
} }
if found == false { if !found {
err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
goto end goto end
} }

View File

@ -47,7 +47,7 @@ func (f *fields) Add(fi *fieldInfo) (added bool) {
} else { } else {
return return
} }
if _, ok := f.fieldsByType[fi.fieldType]; ok == false { if _, ok := f.fieldsByType[fi.fieldType]; !ok {
f.fieldsByType[fi.fieldType] = make([]*fieldInfo, 0) f.fieldsByType[fi.fieldType] = make([]*fieldInfo, 0)
} }
f.fieldsByType[fi.fieldType] = append(f.fieldsByType[fi.fieldType], fi) f.fieldsByType[fi.fieldType] = append(f.fieldsByType[fi.fieldType], fi)
@ -334,12 +334,12 @@ checkType:
switch onDelete { switch onDelete {
case odCascade, odDoNothing: case odCascade, odDoNothing:
case odSetDefault: case odSetDefault:
if initial.Exist() == false { if !initial.Exist() {
err = errors.New("on_delete: set_default need set field a default value") err = errors.New("on_delete: set_default need set field a default value")
goto end goto end
} }
case odSetNULL: case odSetNULL:
if fi.null == false { if !fi.null {
err = errors.New("on_delete: set_null need set field null") err = errors.New("on_delete: set_null need set field null")
goto end goto end
} }

View File

@ -78,7 +78,7 @@ func addModelFields(mi *modelInfo, ind reflect.Value, mName string, index []int)
fi.fieldIndex = append(index, i) fi.fieldIndex = append(index, i)
fi.mi = mi fi.mi = mi
fi.inModel = true fi.inModel = true
if mi.fields.Add(fi) == false { if !mi.fields.Add(fi) {
err = fmt.Errorf("duplicate column name: %s", fi.column) err = fmt.Errorf("duplicate column name: %s", fi.column)
break break
} }

View File

@ -122,21 +122,13 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo {
// read data to model // read data to model
func (o *orm) Read(md interface{}, cols ...string) error { func (o *orm) Read(md interface{}, cols ...string) error {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, false) return o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, false)
if err != nil {
return err
}
return nil
} }
// read data to model, like Read(), but use "SELECT FOR UPDATE" form // read data to model, like Read(), but use "SELECT FOR UPDATE" form
func (o *orm) ReadForUpdate(md interface{}, cols ...string) error { func (o *orm) ReadForUpdate(md interface{}, cols ...string) error {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, true) return o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols, true)
if err != nil {
return err
}
return nil
} }
// Try to read a row from the database, or insert one if it doesn't exist // Try to read a row from the database, or insert one if it doesn't exist
@ -238,15 +230,11 @@ func (o *orm) InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64
// cols set the columns those want to update. // cols set the columns those want to update.
func (o *orm) Update(md interface{}, cols ...string) (int64, error) { func (o *orm) Update(md interface{}, cols ...string) (int64, error) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols) return o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols)
if err != nil {
return num, err
}
return num, nil
} }
// delete model in database // delete model in database
// cols shows the delete conditions values read from. deafult is pk // cols shows the delete conditions values read from. default is pk
func (o *orm) Delete(md interface{}, cols ...string) (int64, error) { func (o *orm) Delete(md interface{}, cols ...string) (int64, error) {
mi, ind := o.getMiInd(md, true) mi, ind := o.getMiInd(md, true)
num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ, cols) num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ, cols)
@ -361,7 +349,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo,
fi := o.getFieldInfo(mi, name) fi := o.getFieldInfo(mi, name)
_, _, exist := getExistPk(mi, ind) _, _, exist := getExistPk(mi, ind)
if exist == false { if !exist {
panic(ErrMissPK) panic(ErrMissPK)
} }
@ -432,7 +420,7 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet {
// table name can be string or struct. // table name can be string or struct.
// e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)),
func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
name := "" var name string
if table, ok := ptrStructOrTableName.(string); ok { if table, ok := ptrStructOrTableName.(string); ok {
name = snakeString(table) name = snakeString(table)
if mi, ok := modelCache.get(name); ok { if mi, ok := modelCache.get(name); ok {
@ -489,7 +477,7 @@ func (o *orm) Begin() error {
// commit transaction // commit transaction
func (o *orm) Commit() error { func (o *orm) Commit() error {
if o.isTx == false { if !o.isTx {
return ErrTxDone return ErrTxDone
} }
err := o.db.(txEnder).Commit() err := o.db.(txEnder).Commit()
@ -504,7 +492,7 @@ func (o *orm) Commit() error {
// rollback transaction // rollback transaction
func (o *orm) Rollback() error { func (o *orm) Rollback() error {
if o.isTx == false { if !o.isTx {
return ErrTxDone return ErrTxDone
} }
err := o.db.(txEnder).Rollback() err := o.db.(txEnder).Rollback()

View File

@ -72,7 +72,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
} }
_, v1, exist := getExistPk(o.mi, o.ind) _, v1, exist := getExistPk(o.mi, o.ind)
if exist == false { if !exist {
panic(ErrMissPK) panic(ErrMissPK)
} }
@ -87,7 +87,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) {
v2 = ind.Interface() v2 = ind.Interface()
} else { } else {
_, v2, exist = getExistPk(fi.relModelInfo, ind) _, v2, exist = getExistPk(fi.relModelInfo, ind)
if exist == false { if !exist {
panic(ErrMissPK) panic(ErrMissPK)
} }
} }
@ -104,11 +104,7 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) {
fi := o.fi fi := o.fi
qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md)
nums, err := qs.Filter(fi.reverseFieldInfoTwo.name+ExprSep+"in", mds).Delete() return qs.Filter(fi.reverseFieldInfoTwo.name+ExprSep+"in", mds).Delete()
if err != nil {
return nums, err
}
return nums, nil
} }
// check model is existed in relationship of origin model // check model is existed in relationship of origin model

View File

@ -671,7 +671,7 @@ func (o *rawSet) queryRowsTo(container interface{}, keyCol, valueCol string) (in
ind *reflect.Value ind *reflect.Value
) )
typ := 0 var typ int
switch container.(type) { switch container.(type) {
case *Params: case *Params:
typ = 1 typ = 1

View File

@ -93,14 +93,14 @@ wrongArg:
} }
func AssertIs(a interface{}, args ...interface{}) error { func AssertIs(a interface{}, args ...interface{}) error {
if ok, err := ValuesCompare(true, a, args...); ok == false { if ok, err := ValuesCompare(true, a, args...); !ok {
return err return err
} }
return nil return nil
} }
func AssertNot(a interface{}, args ...interface{}) error { func AssertNot(a interface{}, args ...interface{}) error {
if ok, err := ValuesCompare(false, a, args...); ok == false { if ok, err := ValuesCompare(false, a, args...); !ok {
return err return err
} }
return nil return nil
@ -135,7 +135,7 @@ func getCaller(skip int) string {
if i := strings.LastIndex(funName, "."); i > -1 { if i := strings.LastIndex(funName, "."); i > -1 {
funName = funName[i+1:] funName = funName[i+1:]
} }
return fmt.Sprintf("%s:%d: \n%s", fn, line, strings.Join(codes, "\n")) return fmt.Sprintf("%s:%s:%d: \n%s", fn, funName, line, strings.Join(codes, "\n"))
} }
func throwFail(t *testing.T, err error, args ...interface{}) { func throwFail(t *testing.T, err error, args ...interface{}) {
@ -1014,6 +1014,8 @@ func TestAll(t *testing.T) {
var users3 []*User var users3 []*User
qs = dORM.QueryTable("user") qs = dORM.QueryTable("user")
num, err = qs.Filter("user_name", "nothing").All(&users3) num, err = qs.Filter("user_name", "nothing").All(&users3)
throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 0))
throwFailNow(t, AssertIs(users3 == nil, false)) throwFailNow(t, AssertIs(users3 == nil, false))
} }
@ -1138,6 +1140,7 @@ func TestRelatedSel(t *testing.T) {
} }
err = qs.Filter("user_name", "nobody").RelatedSel("profile").One(&user) err = qs.Filter("user_name", "nobody").RelatedSel("profile").One(&user)
throwFail(t, err)
throwFail(t, AssertIs(num, 1)) throwFail(t, AssertIs(num, 1))
throwFail(t, AssertIs(user.Profile, nil)) throwFail(t, AssertIs(user.Profile, nil))
@ -1246,20 +1249,24 @@ func TestLoadRelated(t *testing.T) {
num, err = dORM.LoadRelated(&user, "Posts", true) num, err = dORM.LoadRelated(&user, "Posts", true)
throwFailNow(t, err) throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 2))
throwFailNow(t, AssertIs(len(user.Posts), 2)) throwFailNow(t, AssertIs(len(user.Posts), 2))
throwFailNow(t, AssertIs(user.Posts[0].User.UserName, "astaxie")) throwFailNow(t, AssertIs(user.Posts[0].User.UserName, "astaxie"))
num, err = dORM.LoadRelated(&user, "Posts", true, 1) num, err = dORM.LoadRelated(&user, "Posts", true, 1)
throwFailNow(t, err) throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(len(user.Posts), 1)) throwFailNow(t, AssertIs(len(user.Posts), 1))
num, err = dORM.LoadRelated(&user, "Posts", true, 0, 0, "-Id") num, err = dORM.LoadRelated(&user, "Posts", true, 0, 0, "-Id")
throwFailNow(t, err) throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 2))
throwFailNow(t, AssertIs(len(user.Posts), 2)) throwFailNow(t, AssertIs(len(user.Posts), 2))
throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting")) throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting"))
num, err = dORM.LoadRelated(&user, "Posts", true, 1, 1, "Id") num, err = dORM.LoadRelated(&user, "Posts", true, 1, 1, "Id")
throwFailNow(t, err) throwFailNow(t, err)
throwFailNow(t, AssertIs(num, 1))
throwFailNow(t, AssertIs(len(user.Posts), 1)) throwFailNow(t, AssertIs(len(user.Posts), 1))
throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting")) throwFailNow(t, AssertIs(user.Posts[0].Title, "Formatting"))
@ -1976,6 +1983,7 @@ func TestReadOrCreate(t *testing.T) {
created, pk, err := dORM.ReadOrCreate(u, "UserName") created, pk, err := dORM.ReadOrCreate(u, "UserName")
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(created, true)) throwFail(t, AssertIs(created, true))
throwFail(t, AssertIs(u.ID, pk))
throwFail(t, AssertIs(u.UserName, "Kyle")) throwFail(t, AssertIs(u.UserName, "Kyle"))
throwFail(t, AssertIs(u.Email, "kylemcc@gmail.com")) throwFail(t, AssertIs(u.Email, "kylemcc@gmail.com"))
throwFail(t, AssertIs(u.Password, "other_pass")) throwFail(t, AssertIs(u.Password, "other_pass"))
@ -2130,13 +2138,13 @@ func TestUintPk(t *testing.T) {
Name: name, Name: name,
} }
created, pk, err := dORM.ReadOrCreate(u, "ID") created, _, err := dORM.ReadOrCreate(u, "ID")
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(created, true)) throwFail(t, AssertIs(created, true))
throwFail(t, AssertIs(u.Name, name)) throwFail(t, AssertIs(u.Name, name))
nu := &UintPk{ID: 8} nu := &UintPk{ID: 8}
created, pk, err = dORM.ReadOrCreate(nu, "ID") created, pk, err := dORM.ReadOrCreate(nu, "ID")
throwFail(t, err) throwFail(t, err)
throwFail(t, AssertIs(created, false)) throwFail(t, AssertIs(created, false))
throwFail(t, AssertIs(nu.ID, u.ID)) throwFail(t, AssertIs(nu.ID, u.ID))

View File

@ -92,11 +92,11 @@ func (f StrTo) Int64() (int64, error) {
i := new(big.Int) i := new(big.Int)
ni, ok := i.SetString(f.String(), 10) // octal ni, ok := i.SetString(f.String(), 10) // octal
if !ok { if !ok {
return int64(v), err return v, err
} }
return ni.Int64(), nil return ni.Int64(), nil
} }
return int64(v), err return v, err
} }
// Uint string to uint // Uint string to uint
@ -130,11 +130,11 @@ func (f StrTo) Uint64() (uint64, error) {
i := new(big.Int) i := new(big.Int)
ni, ok := i.SetString(f.String(), 10) ni, ok := i.SetString(f.String(), 10)
if !ok { if !ok {
return uint64(v), err return v, err
} }
return ni.Uint64(), nil return ni.Uint64(), nil
} }
return uint64(v), err return v, err
} }
// String string to string // String string to string
@ -225,7 +225,7 @@ func camelString(s string) string {
if d == '_' { if d == '_' {
flag = true flag = true
continue continue
} else if flag == true { } else if flag {
if d >= 'a' && d <= 'z' { if d >= 'a' && d <= 'z' {
d = d - 32 d = d - 32
} }

View File

@ -23,7 +23,7 @@ import (
// PolicyFunc defines a policy function which is invoked before the controller handler is executed. // PolicyFunc defines a policy function which is invoked before the controller handler is executed.
type PolicyFunc func(*context.Context) type PolicyFunc func(*context.Context)
// FindRouter Find Router info for URL // FindPolicy Find Router info for URL
func (p *ControllerRegister) FindPolicy(cont *context.Context) []PolicyFunc { func (p *ControllerRegister) FindPolicy(cont *context.Context) []PolicyFunc {
var urlPath = cont.Input.URL() var urlPath = cont.Input.URL()
if !BConfig.RouterCaseSensitive { if !BConfig.RouterCaseSensitive {
@ -71,7 +71,7 @@ func (p *ControllerRegister) addToPolicy(method, pattern string, r ...PolicyFunc
} }
} }
// Register new policy in beego // Policy Register new policy in beego
func Policy(pattern, method string, policy ...PolicyFunc) { func Policy(pattern, method string, policy ...PolicyFunc) {
BeeApp.Handlers.addToPolicy(method, pattern, policy...) BeeApp.Handlers.addToPolicy(method, pattern, policy...)
} }

View File

@ -17,7 +17,6 @@ package beego
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"os"
"path" "path"
"path/filepath" "path/filepath"
"reflect" "reflect"
@ -109,7 +108,8 @@ func ExceptMethodAppend(action string) {
exceptMethod = append(exceptMethod, action) exceptMethod = append(exceptMethod, action)
} }
type controllerInfo struct { // ControllerInfo holds information about the controller.
type ControllerInfo struct {
pattern string pattern string
controllerType reflect.Type controllerType reflect.Type
methods map[string]string methods map[string]string
@ -176,7 +176,7 @@ func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingM
} }
} }
route := &controllerInfo{} route := &ControllerInfo{}
route.pattern = pattern route.pattern = pattern
route.methods = methods route.methods = methods
route.routerType = routerTypeBeego route.routerType = routerTypeBeego
@ -198,7 +198,7 @@ func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingM
} }
} }
func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerInfo) { func (p *ControllerRegister) addToRouter(method, pattern string, r *ControllerInfo) {
if !BConfig.RouterCaseSensitive { if !BConfig.RouterCaseSensitive {
pattern = strings.ToLower(pattern) pattern = strings.ToLower(pattern)
} }
@ -219,13 +219,11 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) {
for _, c := range cList { for _, c := range cList {
reflectVal := reflect.ValueOf(c) reflectVal := reflect.ValueOf(c)
t := reflect.Indirect(reflectVal).Type() t := reflect.Indirect(reflectVal).Type()
gopath := os.Getenv("GOPATH") wgopath := utils.GetGOPATHs()
if gopath == "" { if len(wgopath) == 0 {
panic("you are in dev mode. So please set gopath") panic("you are in dev mode. So please set gopath")
} }
pkgpath := "" pkgpath := ""
wgopath := filepath.SplitList(gopath)
for _, wg := range wgopath { for _, wg := range wgopath {
wg, _ = filepath.EvalSymlinks(filepath.Join(wg, "src", t.PkgPath())) wg, _ = filepath.EvalSymlinks(filepath.Join(wg, "src", t.PkgPath()))
if utils.FileExists(wg) { if utils.FileExists(wg) {
@ -335,7 +333,7 @@ func (p *ControllerRegister) AddMethod(method, pattern string, f FilterFunc) {
if _, ok := HTTPMETHOD[method]; method != "*" && !ok { if _, ok := HTTPMETHOD[method]; method != "*" && !ok {
panic("not support http method: " + method) panic("not support http method: " + method)
} }
route := &controllerInfo{} route := &ControllerInfo{}
route.pattern = pattern route.pattern = pattern
route.routerType = routerTypeRESTFul route.routerType = routerTypeRESTFul
route.runFunction = f route.runFunction = f
@ -361,7 +359,7 @@ func (p *ControllerRegister) AddMethod(method, pattern string, f FilterFunc) {
// Handler add user defined Handler // Handler add user defined Handler
func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...interface{}) { func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...interface{}) {
route := &controllerInfo{} route := &ControllerInfo{}
route.pattern = pattern route.pattern = pattern
route.routerType = routerTypeHandler route.routerType = routerTypeHandler
route.handler = h route.handler = h
@ -396,7 +394,7 @@ func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface)
controllerName := strings.TrimSuffix(ct.Name(), "Controller") controllerName := strings.TrimSuffix(ct.Name(), "Controller")
for i := 0; i < rt.NumMethod(); i++ { for i := 0; i < rt.NumMethod(); i++ {
if !utils.InSlice(rt.Method(i).Name, exceptMethod) { if !utils.InSlice(rt.Method(i).Name, exceptMethod) {
route := &controllerInfo{} route := &ControllerInfo{}
route.routerType = routerTypeBeego route.routerType = routerTypeBeego
route.methods = map[string]string{"*": rt.Method(i).Name} route.methods = map[string]string{"*": rt.Method(i).Name}
route.controllerType = ct route.controllerType = ct
@ -502,7 +500,7 @@ func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName strin
} }
} }
for _, l := range t.leaves { for _, l := range t.leaves {
if c, ok := l.runObject.(*controllerInfo); ok { if c, ok := l.runObject.(*ControllerInfo); ok {
if c.routerType == routerTypeBeego && if c.routerType == routerTypeBeego &&
strings.HasSuffix(path.Join(c.controllerType.PkgPath(), c.controllerType.Name()), controllName) { strings.HasSuffix(path.Join(c.controllerType.PkgPath(), c.controllerType.Name()), controllName) {
find := false find := false
@ -629,7 +627,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
runRouter reflect.Type runRouter reflect.Type
findRouter bool findRouter bool
runMethod string runMethod string
routerInfo *controllerInfo routerInfo *ControllerInfo
isRunnable bool isRunnable bool
) )
context := p.pool.Get().(*beecontext.Context) context := p.pool.Get().(*beecontext.Context)
@ -670,7 +668,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
goto Admin goto Admin
} }
if r.Method != "GET" && r.Method != "HEAD" { if r.Method != http.MethodGet && r.Method != http.MethodHead {
if BConfig.CopyRequestBody && !context.Input.IsUpload() { if BConfig.CopyRequestBody && !context.Input.IsUpload() {
context.Input.CopyBody(BConfig.MaxMemory) context.Input.CopyBody(BConfig.MaxMemory)
} }
@ -743,11 +741,11 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
} else { } else {
runRouter = routerInfo.controllerType runRouter = routerInfo.controllerType
method := r.Method method := r.Method
if r.Method == "POST" && context.Input.Query("_method") == "PUT" { if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodPost {
method = "PUT" method = http.MethodPut
} }
if r.Method == "POST" && context.Input.Query("_method") == "DELETE" { if r.Method == http.MethodPost && context.Input.Query("_method") == http.MethodDelete {
method = "DELETE" method = http.MethodDelete
} }
if m, ok := routerInfo.methods[method]; ok { if m, ok := routerInfo.methods[method]; ok {
runMethod = m runMethod = m
@ -777,8 +775,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
//if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
if BConfig.WebConfig.EnableXSRF { if BConfig.WebConfig.EnableXSRF {
execController.XSRFToken() execController.XSRFToken()
if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" || if r.Method == http.MethodPost || r.Method == http.MethodDelete || r.Method == http.MethodPut ||
(r.Method == "POST" && (context.Input.Query("_method") == "DELETE" || context.Input.Query("_method") == "PUT")) { (r.Method == http.MethodPost && (context.Input.Query("_method") == http.MethodDelete || context.Input.Query("_method") == http.MethodPut)) {
execController.CheckXSRFCookie() execController.CheckXSRFCookie()
} }
} }
@ -788,19 +786,19 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
if !context.ResponseWriter.Started { if !context.ResponseWriter.Started {
//exec main logic //exec main logic
switch runMethod { switch runMethod {
case "GET": case http.MethodGet:
execController.Get() execController.Get()
case "POST": case http.MethodPost:
execController.Post() execController.Post()
case "DELETE": case http.MethodDelete:
execController.Delete() execController.Delete()
case "PUT": case http.MethodPut:
execController.Put() execController.Put()
case "HEAD": case http.MethodHead:
execController.Head() execController.Head()
case "PATCH": case http.MethodPatch:
execController.Patch() execController.Patch()
case "OPTIONS": case http.MethodOptions:
execController.Options() execController.Options()
default: default:
if !execController.HandlerFunc(runMethod) { if !execController.HandlerFunc(runMethod) {
@ -887,7 +885,7 @@ Admin:
} }
// FindRouter Find Router info for URL // FindRouter Find Router info for URL
func (p *ControllerRegister) FindRouter(context *beecontext.Context) (routerInfo *controllerInfo, isFind bool) { func (p *ControllerRegister) FindRouter(context *beecontext.Context) (routerInfo *ControllerInfo, isFind bool) {
var urlPath = context.Input.URL() var urlPath = context.Input.URL()
if !BConfig.RouterCaseSensitive { if !BConfig.RouterCaseSensitive {
urlPath = strings.ToLower(urlPath) urlPath = strings.ToLower(urlPath)
@ -895,7 +893,7 @@ func (p *ControllerRegister) FindRouter(context *beecontext.Context) (routerInfo
httpMethod := context.Input.Method() httpMethod := context.Input.Method()
if t, ok := p.routers[httpMethod]; ok { if t, ok := p.routers[httpMethod]; ok {
runObject := t.Match(urlPath, context) runObject := t.Match(urlPath, context)
if r, ok := runObject.(*controllerInfo); ok { if r, ok := runObject.(*ControllerInfo); ok {
return r, true return r, true
} }
} }

View File

@ -502,10 +502,10 @@ func TestFilterBeforeRouter(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "BeforeRouter1") == false { if !strings.Contains(rw.Body.String(), "BeforeRouter1") {
t.Errorf(testName + " BeforeRouter did not run") t.Errorf(testName + " BeforeRouter did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == true { if strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " BeforeRouter did not return properly") t.Errorf(testName + " BeforeRouter did not return properly")
} }
} }
@ -525,13 +525,13 @@ func TestFilterBeforeExec(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "BeforeExec1") == false { if !strings.Contains(rw.Body.String(), "BeforeExec1") {
t.Errorf(testName + " BeforeExec did not run") t.Errorf(testName + " BeforeExec did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == true { if strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " BeforeExec did not return properly") t.Errorf(testName + " BeforeExec did not return properly")
} }
if strings.Contains(rw.Body.String(), "BeforeRouter") == true { if strings.Contains(rw.Body.String(), "BeforeRouter") {
t.Errorf(testName + " BeforeRouter ran in error") t.Errorf(testName + " BeforeRouter ran in error")
} }
} }
@ -552,16 +552,16 @@ func TestFilterAfterExec(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "AfterExec1") == false { if !strings.Contains(rw.Body.String(), "AfterExec1") {
t.Errorf(testName + " AfterExec did not run") t.Errorf(testName + " AfterExec did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == false { if !strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " handler did not run properly") t.Errorf(testName + " handler did not run properly")
} }
if strings.Contains(rw.Body.String(), "BeforeRouter") == true { if strings.Contains(rw.Body.String(), "BeforeRouter") {
t.Errorf(testName + " BeforeRouter ran in error") t.Errorf(testName + " BeforeRouter ran in error")
} }
if strings.Contains(rw.Body.String(), "BeforeExec") == true { if strings.Contains(rw.Body.String(), "BeforeExec") {
t.Errorf(testName + " BeforeExec ran in error") t.Errorf(testName + " BeforeExec ran in error")
} }
} }
@ -583,19 +583,19 @@ func TestFilterFinishRouter(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "FinishRouter1") == true { if strings.Contains(rw.Body.String(), "FinishRouter1") {
t.Errorf(testName + " FinishRouter did not run") t.Errorf(testName + " FinishRouter did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == false { if !strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " handler did not run properly") t.Errorf(testName + " handler did not run properly")
} }
if strings.Contains(rw.Body.String(), "AfterExec1") == true { if strings.Contains(rw.Body.String(), "AfterExec1") {
t.Errorf(testName + " AfterExec ran in error") t.Errorf(testName + " AfterExec ran in error")
} }
if strings.Contains(rw.Body.String(), "BeforeRouter") == true { if strings.Contains(rw.Body.String(), "BeforeRouter") {
t.Errorf(testName + " BeforeRouter ran in error") t.Errorf(testName + " BeforeRouter ran in error")
} }
if strings.Contains(rw.Body.String(), "BeforeExec") == true { if strings.Contains(rw.Body.String(), "BeforeExec") {
t.Errorf(testName + " BeforeExec ran in error") t.Errorf(testName + " BeforeExec ran in error")
} }
} }
@ -615,14 +615,14 @@ func TestFilterFinishRouterMultiFirstOnly(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "FinishRouter1") == false { if !strings.Contains(rw.Body.String(), "FinishRouter1") {
t.Errorf(testName + " FinishRouter1 did not run") t.Errorf(testName + " FinishRouter1 did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == false { if !strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " handler did not run properly") t.Errorf(testName + " handler did not run properly")
} }
// not expected in body // not expected in body
if strings.Contains(rw.Body.String(), "FinishRouter2") == true { if strings.Contains(rw.Body.String(), "FinishRouter2") {
t.Errorf(testName + " FinishRouter2 did run") t.Errorf(testName + " FinishRouter2 did run")
} }
} }
@ -642,44 +642,52 @@ func TestFilterFinishRouterMulti(t *testing.T) {
rw, r := testRequest("GET", url) rw, r := testRequest("GET", url)
mux.ServeHTTP(rw, r) mux.ServeHTTP(rw, r)
if strings.Contains(rw.Body.String(), "FinishRouter1") == false { if !strings.Contains(rw.Body.String(), "FinishRouter1") {
t.Errorf(testName + " FinishRouter1 did not run") t.Errorf(testName + " FinishRouter1 did not run")
} }
if strings.Contains(rw.Body.String(), "hello") == false { if !strings.Contains(rw.Body.String(), "hello") {
t.Errorf(testName + " handler did not run properly") t.Errorf(testName + " handler did not run properly")
} }
if strings.Contains(rw.Body.String(), "FinishRouter2") == false { if !strings.Contains(rw.Body.String(), "FinishRouter2") {
t.Errorf(testName + " FinishRouter2 did not run properly") t.Errorf(testName + " FinishRouter2 did not run properly")
} }
} }
func beegoFilterNoOutput(ctx *context.Context) { func beegoFilterNoOutput(ctx *context.Context) {
return
} }
func beegoBeforeRouter1(ctx *context.Context) { func beegoBeforeRouter1(ctx *context.Context) {
ctx.WriteString("|BeforeRouter1") ctx.WriteString("|BeforeRouter1")
} }
func beegoBeforeRouter2(ctx *context.Context) { func beegoBeforeRouter2(ctx *context.Context) {
ctx.WriteString("|BeforeRouter2") ctx.WriteString("|BeforeRouter2")
} }
func beegoBeforeExec1(ctx *context.Context) { func beegoBeforeExec1(ctx *context.Context) {
ctx.WriteString("|BeforeExec1") ctx.WriteString("|BeforeExec1")
} }
func beegoBeforeExec2(ctx *context.Context) { func beegoBeforeExec2(ctx *context.Context) {
ctx.WriteString("|BeforeExec2") ctx.WriteString("|BeforeExec2")
} }
func beegoAfterExec1(ctx *context.Context) { func beegoAfterExec1(ctx *context.Context) {
ctx.WriteString("|AfterExec1") ctx.WriteString("|AfterExec1")
} }
func beegoAfterExec2(ctx *context.Context) { func beegoAfterExec2(ctx *context.Context) {
ctx.WriteString("|AfterExec2") ctx.WriteString("|AfterExec2")
} }
func beegoFinishRouter1(ctx *context.Context) { func beegoFinishRouter1(ctx *context.Context) {
ctx.WriteString("|FinishRouter1") ctx.WriteString("|FinishRouter1")
} }
func beegoFinishRouter2(ctx *context.Context) { func beegoFinishRouter2(ctx *context.Context) {
ctx.WriteString("|FinishRouter2") ctx.WriteString("|FinishRouter2")
} }
func beegoResetParams(ctx *context.Context) { func beegoResetParams(ctx *context.Context) {
ctx.ResponseWriter.Header().Set("splat", ctx.Input.Param(":splat")) ctx.ResponseWriter.Header().Set("splat", ctx.Input.Param(":splat"))
} }

View File

@ -155,11 +155,16 @@ func (cp *Provider) SessionInit(maxlifetime int64, savePath string) error {
func (cp *Provider) SessionRead(sid string) (session.Store, error) { func (cp *Provider) SessionRead(sid string) (session.Store, error) {
cp.b = cp.getBucket() cp.b = cp.getBucket()
var doc []byte var (
kv map[interface{}]interface{}
err error
doc []byte
)
err := cp.b.Get(sid, &doc) err = cp.b.Get(sid, &doc)
var kv map[interface{}]interface{} if err != nil {
if doc == nil { return nil, err
} else if doc == nil {
kv = make(map[interface{}]interface{}) kv = make(map[interface{}]interface{})
} else { } else {
kv, err = session.DecodeGob(doc) kv, err = session.DecodeGob(doc)
@ -230,7 +235,6 @@ func (cp *Provider) SessionDestroy(sid string) error {
// SessionGC Recycle // SessionGC Recycle
func (cp *Provider) SessionGC() { func (cp *Provider) SessionGC() {
return
} }
// SessionAll return all active session // SessionAll return all active session

View File

@ -12,8 +12,10 @@ import (
"github.com/siddontang/ledisdb/ledis" "github.com/siddontang/ledisdb/ledis"
) )
var ledispder = &Provider{} var (
var c *ledis.DB ledispder = &Provider{}
c *ledis.DB
)
// SessionStore ledis session store // SessionStore ledis session store
type SessionStore struct { type SessionStore struct {
@ -97,27 +99,33 @@ func (lp *Provider) SessionInit(maxlifetime int64, savePath string) error {
} }
cfg := new(config.Config) cfg := new(config.Config)
cfg.DataDir = lp.savePath cfg.DataDir = lp.savePath
nowLedis, err := ledis.Open(cfg)
c, err = nowLedis.Select(lp.db) var ledisInstance *ledis.Ledis
ledisInstance, err = ledis.Open(cfg)
if err != nil { if err != nil {
println(err) return err
return nil
} }
return nil c, err = ledisInstance.Select(lp.db)
return err
} }
// SessionRead read ledis session by sid // SessionRead read ledis session by sid
func (lp *Provider) SessionRead(sid string) (session.Store, error) { func (lp *Provider) SessionRead(sid string) (session.Store, error) {
kvs, err := c.Get([]byte(sid)) var (
var kv map[interface{}]interface{} kv map[interface{}]interface{}
err error
)
kvs, _ := c.Get([]byte(sid))
if len(kvs) == 0 { if len(kvs) == 0 {
kv = make(map[interface{}]interface{}) kv = make(map[interface{}]interface{})
} else { } else {
kv, err = session.DecodeGob(kvs) if kv, err = session.DecodeGob(kvs); err != nil {
if err != nil {
return nil, err return nil, err
} }
} }
ls := &SessionStore{sid: sid, values: kv, maxlifetime: lp.maxlifetime} ls := &SessionStore{sid: sid, values: kv, maxlifetime: lp.maxlifetime}
return ls, nil return ls, nil
} }
@ -125,10 +133,7 @@ func (lp *Provider) SessionRead(sid string) (session.Store, error) {
// SessionExist check ledis session exist by sid // SessionExist check ledis session exist by sid
func (lp *Provider) SessionExist(sid string) bool { func (lp *Provider) SessionExist(sid string) bool {
count, _ := c.Exists([]byte(sid)) count, _ := c.Exists([]byte(sid))
if count == 0 { return !(count == 0)
return false
}
return true
} }
// SessionRegenerate generate new sid for ledis session // SessionRegenerate generate new sid for ledis session
@ -145,18 +150,7 @@ func (lp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error)
c.Set([]byte(sid), data) c.Set([]byte(sid), data)
c.Expire([]byte(sid), lp.maxlifetime) c.Expire([]byte(sid), lp.maxlifetime)
} }
kvs, err := c.Get([]byte(sid)) return lp.SessionRead(sid)
var kv map[interface{}]interface{}
if len(kvs) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob([]byte(kvs))
if err != nil {
return nil, err
}
}
ls := &SessionStore{sid: sid, values: kv, maxlifetime: lp.maxlifetime}
return ls, nil
} }
// SessionDestroy delete ledis session by id // SessionDestroy delete ledis session by id
@ -167,7 +161,6 @@ func (lp *Provider) SessionDestroy(sid string) error {
// SessionGC Impelment method, no used. // SessionGC Impelment method, no used.
func (lp *Provider) SessionGC() { func (lp *Provider) SessionGC() {
return
} }
// SessionAll return all active session // SessionAll return all active session

View File

@ -205,11 +205,7 @@ func (rp *MemProvider) SessionDestroy(sid string) error {
} }
} }
err := client.Delete(sid) return client.Delete(sid)
if err != nil {
return err
}
return nil
} }
func (rp *MemProvider) connectInit() error { func (rp *MemProvider) connectInit() error {
@ -219,7 +215,6 @@ func (rp *MemProvider) connectInit() error {
// SessionGC Impelment method, no used. // SessionGC Impelment method, no used.
func (rp *MemProvider) SessionGC() { func (rp *MemProvider) SessionGC() {
return
} }
// SessionAll return all activeSession // SessionAll return all activeSession

View File

@ -143,7 +143,6 @@ func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error {
// SessionRead get mysql session by sid // SessionRead get mysql session by sid
func (mp *Provider) SessionRead(sid string) (session.Store, error) { func (mp *Provider) SessionRead(sid string) (session.Store, error) {
c := mp.connectInit() c := mp.connectInit()
defer c.Close()
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid) row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
var sessiondata []byte var sessiondata []byte
err := row.Scan(&sessiondata) err := row.Scan(&sessiondata)
@ -171,16 +170,12 @@ func (mp *Provider) SessionExist(sid string) bool {
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid) row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
var sessiondata []byte var sessiondata []byte
err := row.Scan(&sessiondata) err := row.Scan(&sessiondata)
if err == sql.ErrNoRows { return !(err == sql.ErrNoRows)
return false
}
return true
} }
// SessionRegenerate generate new sid for mysql session // SessionRegenerate generate new sid for mysql session
func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) { func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
c := mp.connectInit() c := mp.connectInit()
defer c.Close()
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid) row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid)
var sessiondata []byte var sessiondata []byte
err := row.Scan(&sessiondata) err := row.Scan(&sessiondata)
@ -214,7 +209,6 @@ func (mp *Provider) SessionGC() {
c := mp.connectInit() c := mp.connectInit()
c.Exec("DELETE from "+TableName+" where session_expiry < ?", time.Now().Unix()-mp.maxlifetime) c.Exec("DELETE from "+TableName+" where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
c.Close() c.Close()
return
} }
// SessionAll count values in mysql session // SessionAll count values in mysql session

View File

@ -184,11 +184,7 @@ func (mp *Provider) SessionExist(sid string) bool {
row := c.QueryRow("select session_data from session where session_key=$1", sid) row := c.QueryRow("select session_data from session where session_key=$1", sid)
var sessiondata []byte var sessiondata []byte
err := row.Scan(&sessiondata) err := row.Scan(&sessiondata)
return !(err == sql.ErrNoRows)
if err == sql.ErrNoRows {
return false
}
return true
} }
// SessionRegenerate generate new sid for postgresql session // SessionRegenerate generate new sid for postgresql session
@ -228,7 +224,6 @@ func (mp *Provider) SessionGC() {
c := mp.connectInit() c := mp.connectInit()
c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime) c.Exec("DELETE from session where EXTRACT(EPOCH FROM (current_timestamp - session_expiry)) > $1", mp.maxlifetime)
c.Close() c.Close()
return
} }
// SessionAll count values in postgresql session // SessionAll count values in postgresql session

View File

@ -128,7 +128,7 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
} }
if len(configs) > 1 { if len(configs) > 1 {
poolsize, err := strconv.Atoi(configs[1]) poolsize, err := strconv.Atoi(configs[1])
if err != nil || poolsize <= 0 { if err != nil || poolsize < 0 {
rp.poolsize = MaxPoolSize rp.poolsize = MaxPoolSize
} else { } else {
rp.poolsize = poolsize rp.poolsize = poolsize
@ -155,7 +155,7 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
return nil, err return nil, err
} }
if rp.password != "" { if rp.password != "" {
if _, err := c.Do("AUTH", rp.password); err != nil { if _, err = c.Do("AUTH", rp.password); err != nil {
c.Close() c.Close()
return nil, err return nil, err
} }
@ -176,13 +176,16 @@ func (rp *Provider) SessionRead(sid string) (session.Store, error) {
c := rp.poollist.Get() c := rp.poollist.Get()
defer c.Close() defer c.Close()
kvs, err := redis.String(c.Do("GET", sid))
var kv map[interface{}]interface{} var kv map[interface{}]interface{}
kvs, err := redis.String(c.Do("GET", sid))
if err != redis.ErrNil {
return nil, err
}
if len(kvs) == 0 { if len(kvs) == 0 {
kv = make(map[interface{}]interface{}) kv = make(map[interface{}]interface{})
} else { } else {
kv, err = session.DecodeGob([]byte(kvs)) if kv, err = session.DecodeGob([]byte(kvs)); err != nil {
if err != nil {
return nil, err return nil, err
} }
} }
@ -216,20 +219,7 @@ func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error)
c.Do("RENAME", oldsid, sid) c.Do("RENAME", oldsid, sid)
c.Do("EXPIRE", sid, rp.maxlifetime) c.Do("EXPIRE", sid, rp.maxlifetime)
} }
return rp.SessionRead(sid)
kvs, err := redis.String(c.Do("GET", sid))
var kv map[interface{}]interface{}
if len(kvs) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob([]byte(kvs))
if err != nil {
return nil, err
}
}
rs := &SessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
return rs, nil
} }
// SessionDestroy delete redis session by id // SessionDestroy delete redis session by id
@ -243,7 +233,6 @@ func (rp *Provider) SessionDestroy(sid string) error {
// SessionGC Impelment method, no used. // SessionGC Impelment method, no used.
func (rp *Provider) SessionGC() { func (rp *Provider) SessionGC() {
return
} }
// SessionAll return all activeSession // SessionAll return all activeSession

View File

@ -74,21 +74,16 @@ func (st *CookieSessionStore) SessionID() string {
// SessionRelease Write cookie session to http response cookie // SessionRelease Write cookie session to http response cookie
func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
str, err := encodeCookie(cookiepder.block, encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values)
cookiepder.config.SecurityKey, if err == nil {
cookiepder.config.SecurityName, cookie := &http.Cookie{Name: cookiepder.config.CookieName,
st.values) Value: url.QueryEscape(encodedCookie),
if err != nil { Path: "/",
return HttpOnly: true,
Secure: cookiepder.config.Secure,
MaxAge: cookiepder.config.Maxage}
http.SetCookie(w, cookie)
} }
cookie := &http.Cookie{Name: cookiepder.config.CookieName,
Value: url.QueryEscape(str),
Path: "/",
HttpOnly: true,
Secure: cookiepder.config.Secure,
MaxAge: cookiepder.config.Maxage}
http.SetCookie(w, cookie)
return
} }
type cookieConfig struct { type cookieConfig struct {
@ -166,7 +161,6 @@ func (pder *CookieProvider) SessionDestroy(sid string) error {
// SessionGC Implement method, no used. // SessionGC Implement method, no used.
func (pder *CookieProvider) SessionGC() { func (pder *CookieProvider) SessionGC() {
return
} }
// SessionAll Implement method, return 0. // SessionAll Implement method, return 0.

View File

@ -87,9 +87,16 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
var f *os.File var f *os.File
if err == nil { if err == nil {
f, err = os.OpenFile(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0777) f, err = os.OpenFile(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0777)
if err != nil {
SLogger.Println(err)
return
}
} else if os.IsNotExist(err) { } else if os.IsNotExist(err) {
f, err = os.Create(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid)) f, err = os.Create(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid))
if err != nil {
SLogger.Println(err)
return
}
} else { } else {
return return
} }
@ -163,10 +170,7 @@ func (fp *FileProvider) SessionExist(sid string) bool {
defer filepder.lock.Unlock() defer filepder.lock.Unlock()
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid)) _, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
if err == nil { return err == nil
return true
}
return false
} }
// SessionDestroy Remove all files in this save path // SessionDestroy Remove all files in this save path

View File

@ -74,8 +74,7 @@ func TestCookieEncodeDecode(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("encodeCookie:", err) t.Fatal("encodeCookie:", err)
} }
dst := make(map[interface{}]interface{}) dst, err := decodeCookie(block, hashKey, securityName, str, 3600)
dst, err = decodeCookie(block, hashKey, securityName, str, 3600)
if err != nil { if err != nil {
t.Fatal("decodeCookie", err) t.Fatal("decodeCookie", err)
} }
@ -115,7 +114,7 @@ func TestParseConfig(t *testing.T) {
if cf2.Gclifetime != 3600 { if cf2.Gclifetime != 3600 {
t.Fatal("parseconfig get gclifetime error") t.Fatal("parseconfig get gclifetime error")
} }
if cf2.EnableSetCookie != false { if cf2.EnableSetCookie {
t.Fatal("parseconfig get enableSetCookie error") t.Fatal("parseconfig get enableSetCookie error")
} }
cconfig := new(cookieConfig) cconfig := new(cookieConfig)

View File

@ -81,6 +81,7 @@ func Register(name string, provide Provider) {
provides[name] = provide provides[name] = provide
} }
// ManagerConfig define the session config
type ManagerConfig struct { type ManagerConfig struct {
CookieName string `json:"cookieName"` CookieName string `json:"cookieName"`
EnableSetCookie bool `json:"enableSetCookie,omitempty"` EnableSetCookie bool `json:"enableSetCookie,omitempty"`
@ -92,9 +93,9 @@ type ManagerConfig struct {
ProviderConfig string `json:"providerConfig"` ProviderConfig string `json:"providerConfig"`
Domain string `json:"domain"` Domain string `json:"domain"`
SessionIDLength int64 `json:"sessionIDLength"` SessionIDLength int64 `json:"sessionIDLength"`
EnableSidInHttpHeader bool `json:"enableSidInHttpHeader"` EnableSidInHTTPHeader bool `json:"EnableSidInHTTPHeader"`
SessionNameInHttpHeader string `json:"sessionNameInHttpHeader"` SessionNameInHTTPHeader string `json:"SessionNameInHTTPHeader"`
EnableSidInUrlQuery bool `json:"enableSidInUrlQuery"` EnableSidInURLQuery bool `json:"EnableSidInURLQuery"`
} }
// Manager contains Provider and its configuration. // Manager contains Provider and its configuration.
@ -125,14 +126,14 @@ func NewManager(provideName string, cf *ManagerConfig) (*Manager, error) {
cf.Maxlifetime = cf.Gclifetime cf.Maxlifetime = cf.Gclifetime
} }
if cf.EnableSidInHttpHeader { if cf.EnableSidInHTTPHeader {
if cf.SessionNameInHttpHeader == "" { if cf.SessionNameInHTTPHeader == "" {
panic(errors.New("SessionNameInHttpHeader is empty")) panic(errors.New("SessionNameInHTTPHeader is empty"))
} }
strMimeHeader := textproto.CanonicalMIMEHeaderKey(cf.SessionNameInHttpHeader) strMimeHeader := textproto.CanonicalMIMEHeaderKey(cf.SessionNameInHTTPHeader)
if cf.SessionNameInHttpHeader != strMimeHeader { if cf.SessionNameInHTTPHeader != strMimeHeader {
strErrMsg := "SessionNameInHttpHeader (" + cf.SessionNameInHttpHeader + ") has the wrong format, it should be like this : " + strMimeHeader strErrMsg := "SessionNameInHTTPHeader (" + cf.SessionNameInHTTPHeader + ") has the wrong format, it should be like this : " + strMimeHeader
panic(errors.New(strErrMsg)) panic(errors.New(strErrMsg))
} }
} }
@ -163,7 +164,7 @@ func (manager *Manager) getSid(r *http.Request) (string, error) {
cookie, errs := r.Cookie(manager.config.CookieName) cookie, errs := r.Cookie(manager.config.CookieName)
if errs != nil || cookie.Value == "" { if errs != nil || cookie.Value == "" {
var sid string var sid string
if manager.config.EnableSidInUrlQuery { if manager.config.EnableSidInURLQuery {
errs := r.ParseForm() errs := r.ParseForm()
if errs != nil { if errs != nil {
return "", errs return "", errs
@ -173,8 +174,8 @@ func (manager *Manager) getSid(r *http.Request) (string, error) {
} }
// if not found in Cookie / param, then read it from request headers // if not found in Cookie / param, then read it from request headers
if manager.config.EnableSidInHttpHeader && sid == "" { if manager.config.EnableSidInHTTPHeader && sid == "" {
sids, isFound := r.Header[manager.config.SessionNameInHttpHeader] sids, isFound := r.Header[manager.config.SessionNameInHTTPHeader]
if isFound && len(sids) != 0 { if isFound && len(sids) != 0 {
return sids[0], nil return sids[0], nil
} }
@ -226,9 +227,9 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
} }
r.AddCookie(cookie) r.AddCookie(cookie)
if manager.config.EnableSidInHttpHeader { if manager.config.EnableSidInHTTPHeader {
r.Header.Set(manager.config.SessionNameInHttpHeader, sid) r.Header.Set(manager.config.SessionNameInHTTPHeader, sid)
w.Header().Set(manager.config.SessionNameInHttpHeader, sid) w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
} }
return return
@ -236,9 +237,9 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
// SessionDestroy Destroy session by its id in http request cookie. // SessionDestroy Destroy session by its id in http request cookie.
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
if manager.config.EnableSidInHttpHeader { if manager.config.EnableSidInHTTPHeader {
r.Header.Del(manager.config.SessionNameInHttpHeader) r.Header.Del(manager.config.SessionNameInHTTPHeader)
w.Header().Del(manager.config.SessionNameInHttpHeader) w.Header().Del(manager.config.SessionNameInHTTPHeader)
} }
cookie, err := r.Cookie(manager.config.CookieName) cookie, err := r.Cookie(manager.config.CookieName)
@ -306,9 +307,9 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
} }
r.AddCookie(cookie) r.AddCookie(cookie)
if manager.config.EnableSidInHttpHeader { if manager.config.EnableSidInHTTPHeader {
r.Header.Set(manager.config.SessionNameInHttpHeader, sid) r.Header.Set(manager.config.SessionNameInHTTPHeader, sid)
w.Header().Set(manager.config.SessionNameInHttpHeader, sid) w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
} }
return return
@ -328,7 +329,7 @@ func (manager *Manager) sessionID() (string, error) {
b := make([]byte, manager.config.SessionIDLength) b := make([]byte, manager.config.SessionIDLength)
n, err := rand.Read(b) n, err := rand.Read(b)
if n != len(b) || err != nil { if n != len(b) || err != nil {
return "", fmt.Errorf("Could not successfully read from the system CSPRNG.") return "", fmt.Errorf("Could not successfully read from the system CSPRNG")
} }
return hex.EncodeToString(b), nil return hex.EncodeToString(b), nil
} }

View File

@ -11,44 +11,40 @@ import (
"github.com/ssdb/gossdb/ssdb" "github.com/ssdb/gossdb/ssdb"
) )
var ssdbProvider = &SsdbProvider{} var ssdbProvider = &Provider{}
type SsdbProvider struct { // Provider holds ssdb client and configs
type Provider struct {
client *ssdb.Client client *ssdb.Client
host string host string
port int port int
maxLifetime int64 maxLifetime int64
} }
func (p *SsdbProvider) connectInit() error { func (p *Provider) connectInit() error {
var err error var err error
if p.host == "" || p.port == 0 { if p.host == "" || p.port == 0 {
return errors.New("SessionInit First") return errors.New("SessionInit First")
} }
p.client, err = ssdb.Connect(p.host, p.port) p.client, err = ssdb.Connect(p.host, p.port)
if err != nil { return err
return err
}
return nil
} }
func (p *SsdbProvider) SessionInit(maxLifetime int64, savePath string) error { // SessionInit init the ssdb with the config
var e error = nil func (p *Provider) SessionInit(maxLifetime int64, savePath string) error {
p.maxLifetime = maxLifetime p.maxLifetime = maxLifetime
address := strings.Split(savePath, ":") address := strings.Split(savePath, ":")
p.host = address[0] p.host = address[0]
p.port, e = strconv.Atoi(address[1])
if e != nil { var err error
return e if p.port, err = strconv.Atoi(address[1]); err != nil {
}
err := p.connectInit()
if err != nil {
return err return err
} }
return nil return p.connectInit()
} }
func (p *SsdbProvider) SessionRead(sid string) (session.Store, error) { // SessionRead return a ssdb client session Store
func (p *Provider) SessionRead(sid string) (session.Store, error) {
if p.client == nil { if p.client == nil {
if err := p.connectInit(); err != nil { if err := p.connectInit(); err != nil {
return nil, err return nil, err
@ -71,7 +67,8 @@ func (p *SsdbProvider) SessionRead(sid string) (session.Store, error) {
return rs, nil return rs, nil
} }
func (p *SsdbProvider) SessionExist(sid string) bool { // SessionExist judged whether sid is exist in session
func (p *Provider) SessionExist(sid string) bool {
if p.client == nil { if p.client == nil {
if err := p.connectInit(); err != nil { if err := p.connectInit(); err != nil {
panic(err) panic(err)
@ -85,9 +82,10 @@ func (p *SsdbProvider) SessionExist(sid string) bool {
return false return false
} }
return true return true
} }
func (p *SsdbProvider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
// SessionRegenerate regenerate session with new sid and delete oldsid
func (p *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
//conn.Do("setx", key, v, ttl) //conn.Do("setx", key, v, ttl)
if p.client == nil { if p.client == nil {
if err := p.connectInit(); err != nil { if err := p.connectInit(); err != nil {
@ -119,27 +117,27 @@ func (p *SsdbProvider) SessionRegenerate(oldsid, sid string) (session.Store, err
return rs, nil return rs, nil
} }
func (p *SsdbProvider) SessionDestroy(sid string) error { // SessionDestroy destroy the sid
func (p *Provider) SessionDestroy(sid string) error {
if p.client == nil { if p.client == nil {
if err := p.connectInit(); err != nil { if err := p.connectInit(); err != nil {
return err return err
} }
} }
_, err := p.client.Del(sid) _, err := p.client.Del(sid)
if err != nil { return err
return err
}
return nil
} }
func (p *SsdbProvider) SessionGC() { // SessionGC not implemented
return func (p *Provider) SessionGC() {
} }
func (p *SsdbProvider) SessionAll() int { // SessionAll not implemented
func (p *Provider) SessionAll() int {
return 0 return 0
} }
// SessionStore holds the session information which stored in ssdb
type SessionStore struct { type SessionStore struct {
sid string sid string
lock sync.RWMutex lock sync.RWMutex
@ -148,12 +146,15 @@ type SessionStore struct {
client *ssdb.Client client *ssdb.Client
} }
// Set the key and value
func (s *SessionStore) Set(key, value interface{}) error { func (s *SessionStore) Set(key, value interface{}) error {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
s.values[key] = value s.values[key] = value
return nil return nil
} }
// Get return the value by the key
func (s *SessionStore) Get(key interface{}) interface{} { func (s *SessionStore) Get(key interface{}) interface{} {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -163,30 +164,36 @@ func (s *SessionStore) Get(key interface{}) interface{} {
return nil return nil
} }
// Delete the key in session store
func (s *SessionStore) Delete(key interface{}) error { func (s *SessionStore) Delete(key interface{}) error {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
delete(s.values, key) delete(s.values, key)
return nil return nil
} }
// Flush delete all keys and values
func (s *SessionStore) Flush() error { func (s *SessionStore) Flush() error {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
s.values = make(map[interface{}]interface{}) s.values = make(map[interface{}]interface{})
return nil return nil
} }
// SessionID return the sessionID
func (s *SessionStore) SessionID() string { func (s *SessionStore) SessionID() string {
return s.sid return s.sid
} }
// SessionRelease Store the keyvalues into ssdb
func (s *SessionStore) SessionRelease(w http.ResponseWriter) { func (s *SessionStore) SessionRelease(w http.ResponseWriter) {
b, err := session.EncodeGob(s.values) b, err := session.EncodeGob(s.values)
if err != nil { if err != nil {
return return
} }
s.client.Do("setx", s.sid, string(b), s.maxLifetime) s.client.Do("setx", s.sid, string(b), s.maxLifetime)
} }
func init() { func init() {
session.Register("ssdb", ssdbProvider) session.Register("ssdb", ssdbProvider)
} }

View File

@ -90,8 +90,6 @@ func serverStaticRouter(ctx *context.Context) {
} }
http.ServeContent(ctx.ResponseWriter, ctx.Request, filePath, sch.modTime, sch) http.ServeContent(ctx.ResponseWriter, ctx.Request, filePath, sch.modTime, sch)
return
} }
type serveContentHolder struct { type serveContentHolder struct {
@ -109,14 +107,14 @@ var (
func openFile(filePath string, fi os.FileInfo, acceptEncoding string) (bool, string, *serveContentHolder, error) { func openFile(filePath string, fi os.FileInfo, acceptEncoding string) (bool, string, *serveContentHolder, error) {
mapKey := acceptEncoding + ":" + filePath mapKey := acceptEncoding + ":" + filePath
mapLock.RLock() mapLock.RLock()
mapFile, _ := staticFileMap[mapKey] mapFile := staticFileMap[mapKey]
mapLock.RUnlock() mapLock.RUnlock()
if isOk(mapFile, fi) { if isOk(mapFile, fi) {
return mapFile.encoding != "", mapFile.encoding, mapFile, nil return mapFile.encoding != "", mapFile.encoding, mapFile, nil
} }
mapLock.Lock() mapLock.Lock()
defer mapLock.Unlock() defer mapLock.Unlock()
if mapFile, _ = staticFileMap[mapKey]; !isOk(mapFile, fi) { if mapFile = staticFileMap[mapKey]; !isOk(mapFile, fi) {
file, err := os.Open(filePath) file, err := os.Open(filePath)
if err != nil { if err != nil {
return false, "", nil, err return false, "", nil, err

View File

@ -100,7 +100,7 @@ type Parameter struct {
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"` Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
} }
// A limited subset of JSON-Schema's items object. It is used by parameter definitions that are not located in "body". // ParameterItems A limited subset of JSON-Schema's items object. It is used by parameter definitions that are not located in "body".
// http://swagger.io/specification/#itemsObject // http://swagger.io/specification/#itemsObject
type ParameterItems struct { type ParameterItems struct {
Type string `json:"type,omitempty" yaml:"type,omitempty"` Type string `json:"type,omitempty" yaml:"type,omitempty"`

View File

@ -31,11 +31,11 @@ import (
) )
var ( var (
beegoTplFuncMap = make(template.FuncMap) beegoTplFuncMap = make(template.FuncMap)
beeViewPathTemplateLocked = false beeViewPathTemplateLocked = false
// beeViewPathTemplates caching map and supported template file extensions per view // beeViewPathTemplates caching map and supported template file extensions per view
beeViewPathTemplates = make(map[string]map[string]*template.Template) beeViewPathTemplates = make(map[string]map[string]*template.Template)
templatesLock sync.RWMutex templatesLock sync.RWMutex
// beeTemplateExt stores the template extension which will build // beeTemplateExt stores the template extension which will build
beeTemplateExt = []string{"tpl", "html"} beeTemplateExt = []string{"tpl", "html"}
// beeTemplatePreprocessors stores associations of extension -> preprocessor handler // beeTemplatePreprocessors stores associations of extension -> preprocessor handler
@ -46,7 +46,7 @@ var (
// writing the output to wr. // writing the output to wr.
// A template will be executed safely in parallel. // A template will be executed safely in parallel.
func ExecuteTemplate(wr io.Writer, name string, data interface{}) error { func ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
return ExecuteViewPathTemplate(wr,name, BConfig.WebConfig.ViewsPath, data) return ExecuteViewPathTemplate(wr, name, BConfig.WebConfig.ViewsPath, data)
} }
// ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object, // ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object,
@ -57,7 +57,7 @@ func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data in
templatesLock.RLock() templatesLock.RLock()
defer templatesLock.RUnlock() defer templatesLock.RUnlock()
} }
if beeTemplates,ok := beeViewPathTemplates[viewPath]; ok { if beeTemplates, ok := beeViewPathTemplates[viewPath]; ok {
if t, ok := beeTemplates[name]; ok { if t, ok := beeTemplates[name]; ok {
var err error var err error
if t.Lookup(name) != nil { if t.Lookup(name) != nil {
@ -72,7 +72,7 @@ func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data in
} }
panic("can't find templatefile in the path:" + viewPath + "/" + name) panic("can't find templatefile in the path:" + viewPath + "/" + name)
} }
panic("Uknown view path:" + viewPath) panic("Unknown view path:" + viewPath)
} }
func init() { func init() {
@ -160,11 +160,14 @@ func AddTemplateExt(ext string) {
beeTemplateExt = append(beeTemplateExt, ext) beeTemplateExt = append(beeTemplateExt, ext)
} }
// AddViewPath adds a new path to the supported view paths. // AddViewPath adds a new path to the supported view paths.
//Can later be used by setting a controller ViewPath to this folder //Can later be used by setting a controller ViewPath to this folder
//will panic if called after beego.Run() //will panic if called after beego.Run()
func AddViewPath(viewPath string) error { func AddViewPath(viewPath string) error {
if beeViewPathTemplateLocked { if beeViewPathTemplateLocked {
if _, exist := beeViewPathTemplates[viewPath]; exist {
return nil //Ignore if viewpath already exists
}
panic("Can not add new view paths after beego.Run()") panic("Can not add new view paths after beego.Run()")
} }
beeViewPathTemplates[viewPath] = make(map[string]*template.Template) beeViewPathTemplates[viewPath] = make(map[string]*template.Template)
@ -184,7 +187,7 @@ func BuildTemplate(dir string, files ...string) error {
} }
return errors.New("dir open err") return errors.New("dir open err")
} }
beeTemplates,ok := beeViewPathTemplates[dir]; beeTemplates, ok := beeViewPathTemplates[dir]
if !ok { if !ok {
panic("Unknown view path: " + dir) panic("Unknown view path: " + dir)
} }
@ -214,7 +217,7 @@ func BuildTemplate(dir string, files ...string) error {
t, err = getTemplate(self.root, file, v...) t, err = getTemplate(self.root, file, v...)
} }
if err != nil { if err != nil {
logs.Trace("parse template err:", file, err) logs.Error("parse template err:", file, err)
} else { } else {
beeTemplates[file] = t beeTemplates[file] = t
} }
@ -227,9 +230,12 @@ func BuildTemplate(dir string, files ...string) error {
func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) { func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) {
var fileAbsPath string var fileAbsPath string
var rParent string
if filepath.HasPrefix(file, "../") { if filepath.HasPrefix(file, "../") {
rParent = filepath.Join(filepath.Dir(parent), file)
fileAbsPath = filepath.Join(root, filepath.Dir(parent), file) fileAbsPath = filepath.Join(root, filepath.Dir(parent), file)
} else { } else {
rParent = file
fileAbsPath = filepath.Join(root, file) fileAbsPath = filepath.Join(root, file)
} }
if e := utils.FileExists(fileAbsPath); !e { if e := utils.FileExists(fileAbsPath); !e {
@ -254,7 +260,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
if !HasTemplateExt(m[1]) { if !HasTemplateExt(m[1]) {
continue continue
} }
_, _, err = getTplDeep(root, m[1], file, t) _, _, err = getTplDeep(root, m[1], rParent, t)
if err != nil { if err != nil {
return nil, [][]string{}, err return nil, [][]string{}, err
} }
@ -293,7 +299,7 @@ func _getTemplate(t0 *template.Template, root string, subMods [][]string, others
t, subMods1, err = getTplDeep(root, otherFile, "", t) t, subMods1, err = getTplDeep(root, otherFile, "", t)
if err != nil { if err != nil {
logs.Trace("template parse file err:", err) logs.Trace("template parse file err:", err)
} else if subMods1 != nil && len(subMods1) > 0 { } else if len(subMods1) > 0 {
t, err = _getTemplate(t, root, subMods1, others...) t, err = _getTemplate(t, root, subMods1, others...)
} }
break break
@ -301,8 +307,9 @@ func _getTemplate(t0 *template.Template, root string, subMods [][]string, others
} }
//second check define //second check define
for _, otherFile := range others { for _, otherFile := range others {
var data []byte
fileAbsPath := filepath.Join(root, otherFile) fileAbsPath := filepath.Join(root, otherFile)
data, err := ioutil.ReadFile(fileAbsPath) data, err = ioutil.ReadFile(fileAbsPath)
if err != nil { if err != nil {
continue continue
} }
@ -314,7 +321,7 @@ func _getTemplate(t0 *template.Template, root string, subMods [][]string, others
t, subMods1, err = getTplDeep(root, otherFile, "", t) t, subMods1, err = getTplDeep(root, otherFile, "", t)
if err != nil { if err != nil {
logs.Trace("template parse file err:", err) logs.Trace("template parse file err:", err)
} else if subMods1 != nil && len(subMods1) > 0 { } else if len(subMods1) > 0 {
t, err = _getTemplate(t, root, subMods1, others...) t, err = _getTemplate(t, root, subMods1, others...)
} }
break break
@ -358,6 +365,7 @@ func DelStaticPath(url string) *App {
return BeeApp return BeeApp
} }
// AddTemplateEngine add a new templatePreProcessor which support extension
func AddTemplateEngine(extension string, fn templatePreProcessor) *App { func AddTemplateEngine(extension string, fn templatePreProcessor) *App {
AddTemplateExt(extension) AddTemplateExt(extension)
beeTemplateEngines[extension] = fn beeTemplateEngines[extension] = fn

View File

@ -15,6 +15,7 @@
package beego package beego
import ( import (
"bytes"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -142,3 +143,116 @@ func TestRelativeTemplate(t *testing.T) {
} }
os.RemoveAll(dir) os.RemoveAll(dir)
} }
var add = `{{ template "layout_blog.tpl" . }}
{{ define "css" }}
<link rel="stylesheet" href="/static/css/current.css">
{{ end}}
{{ define "content" }}
<h2>{{ .Title }}</h2>
<p> This is SomeVar: {{ .SomeVar }}</p>
{{ end }}
{{ define "js" }}
<script src="/static/js/current.js"></script>
{{ end}}`
var layoutBlog = `<!DOCTYPE html>
<html>
<head>
<title>Lin Li</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css">
{{ block "css" . }}{{ end }}
</head>
<body>
<div class="container">
{{ block "content" . }}{{ end }}
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
{{ block "js" . }}{{ end }}
</body>
</html>`
var output = `<!DOCTYPE html>
<html>
<head>
<title>Lin Li</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/css/current.css">
</head>
<body>
<div class="container">
<h2>Hello</h2>
<p> This is SomeVar: val</p>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="/static/js/current.js"></script>
</body>
</html>
`
func TestTemplateLayout(t *testing.T) {
dir := "_beeTmp"
files := []string{
"add.tpl",
"layout_blog.tpl",
}
if err := os.MkdirAll(dir, 0777); err != nil {
t.Fatal(err)
}
for k, name := range files {
os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
if f, err := os.Create(filepath.Join(dir, name)); err != nil {
t.Fatal(err)
} else {
if k == 0 {
f.WriteString(add)
} else if k == 1 {
f.WriteString(layoutBlog)
}
f.Close()
}
}
if err := AddViewPath(dir); err != nil {
t.Fatal(err)
}
beeTemplates := beeViewPathTemplates[dir]
if len(beeTemplates) != 2 {
t.Fatalf("should be 2 but got %v", len(beeTemplates))
}
out := bytes.NewBufferString("")
if err := beeTemplates["add.tpl"].ExecuteTemplate(out, "add.tpl", map[string]string{"Title": "Hello", "SomeVar": "val"}); err != nil {
t.Fatal(err)
}
if out.String() != output {
t.Log(out.String())
t.Fatal("Compare failed")
}
for _, name := range files {
os.RemoveAll(filepath.Join(dir, name))
}
os.RemoveAll(dir)
}

View File

@ -26,6 +26,12 @@ import (
"time" "time"
) )
const (
formatTime = "15:04:05"
formatDate = "2006-01-02"
formatDateTime = "2006-01-02 15:04:05"
)
// Substr returns the substr from start to length. // Substr returns the substr from start to length.
func Substr(s string, start, length int) string { func Substr(s string, start, length int) string {
bt := []rune(s) bt := []rune(s)
@ -46,26 +52,25 @@ func Substr(s string, start, length int) string {
// HTML2str returns escaping text convert from html. // HTML2str returns escaping text convert from html.
func HTML2str(html string) string { func HTML2str(html string) string {
src := string(html)
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>") re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower) html = re.ReplaceAllStringFunc(html, strings.ToLower)
//remove STYLE //remove STYLE
re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>") re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
src = re.ReplaceAllString(src, "") html = re.ReplaceAllString(html, "")
//remove SCRIPT //remove SCRIPT
re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>") re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
src = re.ReplaceAllString(src, "") html = re.ReplaceAllString(html, "")
re, _ = regexp.Compile("\\<[\\S\\s]+?\\>") re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllString(src, "\n") html = re.ReplaceAllString(html, "\n")
re, _ = regexp.Compile("\\s{2,}") re, _ = regexp.Compile("\\s{2,}")
src = re.ReplaceAllString(src, "\n") html = re.ReplaceAllString(html, "\n")
return strings.TrimSpace(src) return strings.TrimSpace(html)
} }
// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat" // DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
@ -193,7 +198,7 @@ func Str2html(raw string) template.HTML {
} }
// Htmlquote returns quoted html string. // Htmlquote returns quoted html string.
func Htmlquote(src string) string { func Htmlquote(text string) string {
//HTML编码为实体符号 //HTML编码为实体符号
/* /*
Encodes `text` for raw use in HTML. Encodes `text` for raw use in HTML.
@ -201,8 +206,6 @@ func Htmlquote(src string) string {
'&lt;&#39;&amp;&quot;&gt;' '&lt;&#39;&amp;&quot;&gt;'
*/ */
text := string(src)
text = strings.Replace(text, "&", "&amp;", -1) // Must be done first! text = strings.Replace(text, "&", "&amp;", -1) // Must be done first!
text = strings.Replace(text, "<", "&lt;", -1) text = strings.Replace(text, "<", "&lt;", -1)
text = strings.Replace(text, ">", "&gt;", -1) text = strings.Replace(text, ">", "&gt;", -1)
@ -216,7 +219,7 @@ func Htmlquote(src string) string {
} }
// Htmlunquote returns unquoted html string. // Htmlunquote returns unquoted html string.
func Htmlunquote(src string) string { func Htmlunquote(text string) string {
//实体符号解释为HTML //实体符号解释为HTML
/* /*
Decodes `text` that's HTML quoted. Decodes `text` that's HTML quoted.
@ -227,7 +230,6 @@ func Htmlunquote(src string) string {
// strings.Replace(s, old, new, n) // strings.Replace(s, old, new, n)
// 在s字符串中把old字符串替换为new字符串n表示替换的次数小于0表示全部替换 // 在s字符串中把old字符串替换为new字符串n表示替换的次数小于0表示全部替换
text := string(src)
text = strings.Replace(text, "&nbsp;", " ", -1) text = strings.Replace(text, "&nbsp;", " ", -1)
text = strings.Replace(text, "&rdquo;", "”", -1) text = strings.Replace(text, "&rdquo;", "”", -1)
text = strings.Replace(text, "&ldquo;", "“", -1) text = strings.Replace(text, "&ldquo;", "“", -1)
@ -262,19 +264,17 @@ func URLFor(endpoint string, values ...interface{}) string {
} }
// AssetsJs returns script tag with src string. // AssetsJs returns script tag with src string.
func AssetsJs(src string) template.HTML { func AssetsJs(text string) template.HTML {
text := string(src)
text = "<script src=\"" + src + "\"></script>" text = "<script src=\"" + text + "\"></script>"
return template.HTML(text) return template.HTML(text)
} }
// AssetsCSS returns stylesheet link tag with src string. // AssetsCSS returns stylesheet link tag with src string.
func AssetsCSS(src string) template.HTML { func AssetsCSS(text string) template.HTML {
text := string(src)
text = "<link href=\"" + src + "\" rel=\"stylesheet\" />" text = "<link href=\"" + text + "\" rel=\"stylesheet\" />"
return template.HTML(text) return template.HTML(text)
} }
@ -352,11 +352,28 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e
case reflect.Struct: case reflect.Struct:
switch fieldT.Type.String() { switch fieldT.Type.String() {
case "time.Time": case "time.Time":
format := time.RFC3339 var (
if len(tags) > 1 { t time.Time
format = tags[1] err error
)
if len(value) >= 25 {
value = value[:25]
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
} else if len(value) >= 19 {
value = value[:19]
t, err = time.ParseInLocation(formatDateTime, value, time.Local)
} else if len(value) >= 10 {
if len(value) > 10 {
value = value[:10]
}
t, err = time.ParseInLocation(formatDate, value, time.Local)
} else if len(value) >= 8 {
if len(value) > 8 {
value = value[:8]
}
t, err = time.ParseInLocation(formatTime, value, time.Local)
} }
t, err := time.ParseInLocation(format, value, time.Local)
if err != nil { if err != nil {
return err return err
} }
@ -490,9 +507,9 @@ func parseFormTag(fieldT reflect.StructField) (label, name, fType string, id str
class = fieldT.Tag.Get("class") class = fieldT.Tag.Get("class")
required = false required = false
required_field := fieldT.Tag.Get("required") requiredField := fieldT.Tag.Get("required")
if required_field != "-" && required_field != "" { if requiredField != "-" && requiredField != "" {
required, _ = strconv.ParseBool(required_field) required, _ = strconv.ParseBool(requiredField)
} }
switch len(tags) { switch len(tags) {

View File

@ -173,7 +173,7 @@ func TestParseForm(t *testing.T) {
if u.Intro != "I am an engineer!" { if u.Intro != "I am an engineer!" {
t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro) t.Errorf("Intro should equal `I am an engineer!` but got `%v`", u.Intro)
} }
if u.StrBool != true { if !u.StrBool {
t.Errorf("strboll should equal `true`, but got `%v`", u.StrBool) t.Errorf("strboll should equal `true`, but got `%v`", u.StrBool)
} }
y, m, d := u.Date.Date() y, m, d := u.Date.Date()
@ -254,44 +254,44 @@ func TestParseFormTag(t *testing.T) {
objT := reflect.TypeOf(&user{}).Elem() objT := reflect.TypeOf(&user{}).Elem()
label, name, fType, id, class, ignored, required := parseFormTag(objT.Field(0)) label, name, fType, _, _, ignored, _ := parseFormTag(objT.Field(0))
if !(name == "name" && label == "年龄:" && fType == "text" && ignored == false) { if !(name == "name" && label == "年龄:" && fType == "text" && !ignored) {
t.Errorf("Form Tag with name, label and type was not correctly parsed.") t.Errorf("Form Tag with name, label and type was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(1)) label, name, fType, _, _, ignored, _ = parseFormTag(objT.Field(1))
if !(name == "NoName" && label == "年龄:" && fType == "hidden" && ignored == false) { if !(name == "NoName" && label == "年龄:" && fType == "hidden" && !ignored) {
t.Errorf("Form Tag with label and type but without name was not correctly parsed.") t.Errorf("Form Tag with label and type but without name was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(2)) label, name, fType, _, _, ignored, _ = parseFormTag(objT.Field(2))
if !(name == "OnlyLabel" && label == "年龄:" && fType == "text" && ignored == false) { if !(name == "OnlyLabel" && label == "年龄:" && fType == "text" && !ignored) {
t.Errorf("Form Tag containing only label was not correctly parsed.") t.Errorf("Form Tag containing only label was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(3)) label, name, fType, id, class, ignored, _ := parseFormTag(objT.Field(3))
if !(name == "name" && label == "OnlyName: " && fType == "text" && ignored == false && if !(name == "name" && label == "OnlyName: " && fType == "text" && !ignored &&
id == "name" && class == "form-name") { id == "name" && class == "form-name") {
t.Errorf("Form Tag containing only name was not correctly parsed.") t.Errorf("Form Tag containing only name was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(4)) _, _, _, _, _, ignored, _ = parseFormTag(objT.Field(4))
if ignored == false { if !ignored {
t.Errorf("Form Tag that should be ignored was not correctly parsed.") t.Errorf("Form Tag that should be ignored was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(5)) _, name, _, _, _, _, required := parseFormTag(objT.Field(5))
if !(name == "name" && required == true) { if !(name == "name" && required) {
t.Errorf("Form Tag containing only name and required was not correctly parsed.") t.Errorf("Form Tag containing only name and required was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(6)) _, name, _, _, _, _, required = parseFormTag(objT.Field(6))
if !(name == "name" && required == false) { if !(name == "name" && !required) {
t.Errorf("Form Tag containing only name and ignore required was not correctly parsed.") t.Errorf("Form Tag containing only name and ignore required was not correctly parsed.")
} }
label, name, fType, id, class, ignored, required = parseFormTag(objT.Field(7)) _, name, _, _, _, _, required = parseFormTag(objT.Field(7))
if !(name == "name" && required == false) { if !(name == "name" && !required) {
t.Errorf("Form Tag containing only name and not required was not correctly parsed.") t.Errorf("Form Tag containing only name and not required was not correctly parsed.")
} }

View File

@ -119,7 +119,7 @@ func (m *URLMap) GetMap() map[string]interface{} {
func (m *URLMap) GetMapData() []map[string]interface{} { func (m *URLMap) GetMapData() []map[string]interface{} {
m.lock.Lock() m.lock.Lock()
defer m.lock.Unlock() defer m.lock.Unlock()
var resultLists []map[string]interface{} var resultLists []map[string]interface{}
for k, v := range m.urlmap { for k, v := range m.urlmap {

View File

@ -427,6 +427,7 @@ func run() {
} }
continue continue
case <-changed: case <-changed:
now = time.Now().Local()
continue continue
case <-stop: case <-stop:
return return

25
tree.go
View File

@ -288,10 +288,10 @@ func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{
return nil return nil
} }
w := make([]string, 0, 20) w := make([]string, 0, 20)
return t.match(pattern, w, ctx) return t.match(pattern[1:], pattern, w, ctx)
} }
func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Context) (runObject interface{}) { func (t *Tree) match(treePattern string, pattern string, wildcardValues []string, ctx *context.Context) (runObject interface{}) {
if len(pattern) > 0 { if len(pattern) > 0 {
i := 0 i := 0
for ; i < len(pattern) && pattern[i] == '/'; i++ { for ; i < len(pattern) && pattern[i] == '/'; i++ {
@ -301,13 +301,13 @@ func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Conte
// Handle leaf nodes: // Handle leaf nodes:
if len(pattern) == 0 { if len(pattern) == 0 {
for _, l := range t.leaves { for _, l := range t.leaves {
if ok := l.match(wildcardValues, ctx); ok { if ok := l.match(treePattern, wildcardValues, ctx); ok {
return l.runObject return l.runObject
} }
} }
if t.wildcard != nil { if t.wildcard != nil {
for _, l := range t.wildcard.leaves { for _, l := range t.wildcard.leaves {
if ok := l.match(wildcardValues, ctx); ok { if ok := l.match(treePattern, wildcardValues, ctx); ok {
return l.runObject return l.runObject
} }
} }
@ -327,7 +327,12 @@ func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Conte
} }
for _, subTree := range t.fixrouters { for _, subTree := range t.fixrouters {
if subTree.prefix == seg { if subTree.prefix == seg {
runObject = subTree.match(pattern, wildcardValues, ctx) if len(pattern) != 0 && pattern[0] == '/' {
treePattern = pattern[1:]
} else {
treePattern = pattern
}
runObject = subTree.match(treePattern, pattern, wildcardValues, ctx)
if runObject != nil { if runObject != nil {
break break
} }
@ -339,7 +344,7 @@ func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Conte
if strings.HasSuffix(seg, str) { if strings.HasSuffix(seg, str) {
for _, subTree := range t.fixrouters { for _, subTree := range t.fixrouters {
if subTree.prefix == seg[:len(seg)-len(str)] { if subTree.prefix == seg[:len(seg)-len(str)] {
runObject = subTree.match(pattern, wildcardValues, ctx) runObject = subTree.match(treePattern, pattern, wildcardValues, ctx)
if runObject != nil { if runObject != nil {
ctx.Input.SetParam(":ext", str[1:]) ctx.Input.SetParam(":ext", str[1:])
} }
@ -349,7 +354,7 @@ func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Conte
} }
} }
if runObject == nil && t.wildcard != nil { if runObject == nil && t.wildcard != nil {
runObject = t.wildcard.match(pattern, append(wildcardValues, seg), ctx) runObject = t.wildcard.match(treePattern, pattern, append(wildcardValues, seg), ctx)
} }
if runObject == nil && len(t.leaves) > 0 { if runObject == nil && len(t.leaves) > 0 {
@ -368,7 +373,7 @@ func (t *Tree) match(pattern string, wildcardValues []string, ctx *context.Conte
wildcardValues = append(wildcardValues, pattern[start:i]) wildcardValues = append(wildcardValues, pattern[start:i])
} }
for _, l := range t.leaves { for _, l := range t.leaves {
if ok := l.match(wildcardValues, ctx); ok { if ok := l.match(treePattern, wildcardValues, ctx); ok {
return l.runObject return l.runObject
} }
} }
@ -386,7 +391,7 @@ type leafInfo struct {
runObject interface{} runObject interface{}
} }
func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok bool) { func (leaf *leafInfo) match(treePattern string, wildcardValues []string, ctx *context.Context) (ok bool) {
//fmt.Println("Leaf:", wildcardValues, leaf.wildcards, leaf.regexps) //fmt.Println("Leaf:", wildcardValues, leaf.wildcards, leaf.regexps)
if leaf.regexps == nil { if leaf.regexps == nil {
if len(wildcardValues) == 0 && len(leaf.wildcards) == 0 { // static path if len(wildcardValues) == 0 && len(leaf.wildcards) == 0 { // static path
@ -394,7 +399,7 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
} }
// match * // match *
if len(leaf.wildcards) == 1 && leaf.wildcards[0] == ":splat" { if len(leaf.wildcards) == 1 && leaf.wildcards[0] == ":splat" {
ctx.Input.SetParam(":splat", path.Join(wildcardValues...)) ctx.Input.SetParam(":splat", treePattern)
return true return true
} }
// match *.* or :id // match *.* or :id

View File

@ -42,7 +42,7 @@ func init() {
routers = append(routers, testinfo{"/", "/", nil}) routers = append(routers, testinfo{"/", "/", nil})
routers = append(routers, testinfo{"/customer/login", "/customer/login", 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{"/customer/login", "/customer/login.json", map[string]string{":ext": "json"}})
routers = append(routers, testinfo{"/*", "/customer/123", map[string]string{":splat": "customer/123"}}) 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{"/*", "/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{"/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/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}})

View File

@ -474,7 +474,7 @@ func randomBrightness(c color.RGBA, max uint8) color.RGBA {
uint8(int(c.R) + n), uint8(int(c.R) + n),
uint8(int(c.G) + n), uint8(int(c.G) + n),
uint8(int(c.B) + n), uint8(int(c.B) + n),
uint8(c.A), c.A,
} }
} }

View File

@ -72,7 +72,7 @@ func GrepFile(patten string, filename string) (lines []string, err error) {
lines = make([]string, 0) lines = make([]string, 0)
reader := bufio.NewReader(fd) reader := bufio.NewReader(fd)
prefix := "" prefix := ""
isLongLine := false var isLongLine bool
for { for {
byteLine, isPrefix, er := reader.ReadLine() byteLine, isPrefix, er := reader.ReadLine()
if er != nil && er != io.EOF { if er != nil && er != io.EOF {

View File

@ -54,7 +54,7 @@ func TestSearchFile(t *testing.T) {
_, err = SearchFile(noExistedFile, ".") _, err = SearchFile(noExistedFile, ".")
if err == nil { if err == nil {
t.Errorf("err shouldnot be nil, got path: %s", SelfDir()) t.Errorf("err shouldnt be nil, got path: %s", SelfDir())
} }
} }

30
utils/utils.go Normal file
View File

@ -0,0 +1,30 @@
package utils
import (
"os"
"path/filepath"
"runtime"
"strings"
)
// GetGOPATHs returns all paths in GOPATH variable.
func GetGOPATHs() []string {
gopath := os.Getenv("GOPATH")
if gopath == "" && strings.Compare(runtime.Version(), "go1.8") >= 0 {
gopath = defaultGOPATH()
}
return filepath.SplitList(gopath)
}
func defaultGOPATH() string {
env := "HOME"
if runtime.GOOS == "windows" {
env = "USERPROFILE"
} else if runtime.GOOS == "plan9" {
env = "home"
}
if home := os.Getenv(env); home != "" {
return filepath.Join(home, "go")
}
return ""
}

View File

@ -42,7 +42,7 @@ func TestGetValidFuncs(t *testing.T) {
} }
f, _ = tf.FieldByName("Tag") f, _ = tf.FieldByName("Tag")
if vfs, err = getValidFuncs(f); err.Error() != "doesn't exsits Maxx valid function" { if _, err = getValidFuncs(f); err.Error() != "doesn't exsits Maxx valid function" {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -349,7 +349,7 @@ func (v *Validation) RecursiveValid(objc interface{}) (bool, error) {
//Step 1: validate obj itself firstly //Step 1: validate obj itself firstly
// fails if objc is not struct // fails if objc is not struct
pass, err := v.Valid(objc) pass, err := v.Valid(objc)
if err != nil || false == pass { if err != nil || !pass {
return pass, err // Stop recursive validation return pass, err // Stop recursive validation
} }
// Step 2: Validate struct's struct fields // Step 2: Validate struct's struct fields

View File

@ -214,6 +214,12 @@ func TestEmail(t *testing.T) {
if !valid.Email("suchuangji@gmail.com", "email").Ok { if !valid.Email("suchuangji@gmail.com", "email").Ok {
t.Error("\"suchuangji@gmail.com\" is a valid email address should be true") t.Error("\"suchuangji@gmail.com\" is a valid email address should be true")
} }
if valid.Email("@suchuangji@gmail.com", "email").Ok {
t.Error("\"@suchuangji@gmail.com\" is a valid email address should be false")
}
if valid.Email("suchuangji@gmail.com ok", "email").Ok {
t.Error("\"suchuangji@gmail.com ok\" is a valid email address should be false")
}
} }
func TestIP(t *testing.T) { func TestIP(t *testing.T) {

View File

@ -518,7 +518,7 @@ func (a AlphaDash) GetLimitValue() interface{} {
return nil return nil
} }
var emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?") var emailPattern = regexp.MustCompile("^[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?$")
// Email check struct // Email check struct
type Email struct { type Email struct {