Merge pull request #2596 from astaxie/develop

beego 1.8.1
This commit is contained in:
astaxie 2017-04-25 22:51:23 +08:00 committed by GitHub
commit 522b3a4a70
72 changed files with 556 additions and 442 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,8 @@ 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
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 +49,7 @@ 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/)
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

@ -157,8 +157,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)
} }
@ -208,12 +208,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 +276,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 +287,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 +329,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 +337,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.1"
// 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:

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)
} }
@ -397,11 +405,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 +421,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

@ -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

@ -105,7 +105,7 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface
switch { switch {
case maxAge > 0: case maxAge > 0:
fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(maxAge)*time.Second).UTC().Format(time.RFC1123), maxAge) fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(maxAge)*time.Second).UTC().Format(time.RFC1123), maxAge)
case maxAge < 0: case maxAge <= 0:
fmt.Fprintf(&b, "; Max-Age=0") fmt.Fprintf(&b, "; Max-Age=0")
} }
} }

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

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()

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

@ -395,7 +395,7 @@ 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))
} }
func (m *Log) Unmarshal(data []byte) error { func (m *Log) Unmarshal(data []byte) error {
var hasFields [1]uint64 var hasFields [1]uint64

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

@ -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

@ -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) {
@ -270,7 +268,7 @@ 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)) err = os.Chmod(fName, os.FileMode(0440))
// re-start logger // re-start logger
RESTART_LOGGER: RESTART_LOGGER:

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
@ -561,11 +561,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

@ -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}
@ -592,7 +592,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 +601,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 +654,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 +699,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 +929,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 +987,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 +1067,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 {
@ -1357,7 +1357,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 +1533,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 +1594,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))

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,7 +246,7 @@ 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 {

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)
} }
@ -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

@ -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

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

@ -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,10 +155,13 @@ 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 doc == nil { if doc == nil {
kv = make(map[interface{}]interface{}) kv = make(map[interface{}]interface{})
} else { } else {
@ -230,7 +233,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,36 @@ 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{}
kvs []byte
err error
)
if kvs, err = c.Get([]byte(sid)); err != nil {
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(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 +136,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 +153,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 +164,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,20 @@ 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 (
var kv map[interface{}]interface{} kv map[interface{}]interface{}
kvs string
err error
)
if kvs, err = redis.String(c.Do("GET", sid)); err != nil {
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 +223,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 +237,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

@ -163,10 +163,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

@ -115,7 +115,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

@ -26,26 +26,19 @@ func (p *SsdbProvider) connectInit() error {
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 { func (p *SsdbProvider) SessionInit(maxLifetime int64, savePath string) error {
var e error = nil
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) { func (p *SsdbProvider) SessionRead(sid string) (session.Store, error) {
@ -85,8 +78,8 @@ 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) { func (p *SsdbProvider) 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 {
@ -126,14 +119,10 @@ func (p *SsdbProvider) SessionDestroy(sid string) error {
} }
} }
_, err := p.client.Del(sid) _, err := p.client.Del(sid)
if err != nil { return err
return err
}
return nil
} }
func (p *SsdbProvider) SessionGC() { func (p *SsdbProvider) SessionGC() {
return
} }
func (p *SsdbProvider) SessionAll() int { func (p *SsdbProvider) SessionAll() int {

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

@ -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
@ -314,7 +320,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

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 layout_blog = `<!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(layout_blog)
}
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
} }

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()
@ -255,43 +255,43 @@ 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, id, class, ignored, required := 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, id, class, ignored, required = 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, id, class, ignored, required = 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, required = 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)) label, name, fType, id, class, ignored, required = 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)) label, name, fType, id, class, ignored, 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)) label, name, fType, id, class, ignored, 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)) label, name, fType, id, class, ignored, 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,
} }
} }

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

@ -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 {