diff --git a/.gitignore b/.gitignore
index 482e34b1..39ae5706 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.idea
.DS_Store
*.swp
*.swo
diff --git a/.go_style b/.go_style
new file mode 100644
index 00000000..26682eed
--- /dev/null
+++ b/.go_style
@@ -0,0 +1,16 @@
+{
+ "file_line": 500,
+ "func_line": 80,
+ "params_num":4,
+ "results_num":3,
+ "formated": true,
+ "pkg_name": true,
+ "camel_name":true,
+ "ignore":[
+ "a/*",
+ "b/*/c/*.go"
+ ],
+ "fatal":[
+ "formated"
+ ]
+}
diff --git a/README.md b/README.md
index 776e5c2d..3357beef 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,7 @@
[![Build Status](https://drone.io/github.com/astaxie/beego/status.png)](https://drone.io/github.com/astaxie/beego/latest)
-beego is a Go Framework inspired by tornado and sinatra.
-
-It is a simple & powerful web framework.
+beego is an open-source, high-performance, modularity, full-stack web framework.
More info [beego.me](http://beego.me)
@@ -12,20 +10,18 @@ More info [beego.me](http://beego.me)
* RESTful support
* MVC architecture
-* Session support (store in memory, file, Redis or MySQL)
-* Cache support (store in memory, Redis or Memcache)
-* Global Config
-* Intelligent routing
-* Thread-safe map
-* Friendly displaying of errors
-* Useful template functions
-
+* modularity
+* auto API documents
+* annotation router
+* namespace
+* powerful develop tools
+* full stack for web & API
## Documentation
[English](http://beego.me/docs/intro/)
-[API](http://gowalker.org/github.com/astaxie/beego)
+[API](http://godoc.org/github.com/astaxie/beego)
[中文文档](http://beego.me/docs/intro/)
@@ -33,7 +29,4 @@ More info [beego.me](http://beego.me)
## LICENSE
beego is licensed under the Apache Licence, Version 2.0
-(http://www.apache.org/licenses/LICENSE-2.0.html).
-
-[![Clone in Koding](http://learn.koding.com/btn/clone_d.png)][koding]
-[koding]: https://koding.com/Teamwork?import=https://github.com/astaxie/beego/archive/master.zip&c=git1
\ No newline at end of file
+(http://www.apache.org/licenses/LICENSE-2.0.html).
\ No newline at end of file
diff --git a/admin.go b/admin.go
index cfaaef72..e464a0e3 100644
--- a/admin.go
+++ b/admin.go
@@ -1,15 +1,25 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
import (
+ "bytes"
+ "encoding/json"
"fmt"
"net/http"
- "strconv"
+ "text/template"
"time"
"github.com/astaxie/beego/toolbox"
@@ -46,7 +56,6 @@ func init() {
beeAdminApp.Route("/prof", profIndex)
beeAdminApp.Route("/healthcheck", healthcheck)
beeAdminApp.Route("/task", taskStatus)
- beeAdminApp.Route("/runtask", runTask)
beeAdminApp.Route("/listconf", listConf)
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
}
@@ -54,22 +63,24 @@ func init() {
// AdminIndex is the default http.Handler for admin module.
// it matches url pattern "/".
func adminIndex(rw http.ResponseWriter, r *http.Request) {
- rw.Write([]byte("
beego admin dashboard"))
- rw.Write([]byte("Welcome to Admin Dashboard \n"))
- rw.Write([]byte("There are servral functions: \n"))
- rw.Write([]byte("1. Record all request and request time, http://localhost:" + strconv.Itoa(AdminHttpPort) + "/qps \n"))
- rw.Write([]byte("2. Get runtime profiling data by the pprof, http://localhost:" + strconv.Itoa(AdminHttpPort) + "/prof \n"))
- rw.Write([]byte("3. Get healthcheck result from http://localhost:" + strconv.Itoa(AdminHttpPort) + "/healthcheck \n"))
- rw.Write([]byte("4. Get current task infomation from task http://localhost:" + strconv.Itoa(AdminHttpPort) + "/task \n"))
- rw.Write([]byte("5. To run a task passed a param http://localhost:" + strconv.Itoa(AdminHttpPort) + "/runtask \n"))
- rw.Write([]byte("6. Get all confige & router infomation http://localhost:" + strconv.Itoa(AdminHttpPort) + "/listconf \n"))
- rw.Write([]byte(""))
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(indexTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ data := make(map[interface{}]interface{})
+ tmpl.Execute(rw, data)
}
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
// it's registered with url pattern "/qbs" in admin module.
func qpsIndex(rw http.ResponseWriter, r *http.Request) {
- toolbox.StatisticsMap.GetMap(rw)
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(qpsTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ data := make(map[interface{}]interface{})
+ data["Content"] = toolbox.StatisticsMap.GetMap()
+
+ tmpl.Execute(rw, data)
+
}
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
@@ -78,112 +89,220 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
r.ParseForm()
command := r.Form.Get("command")
if command != "" {
+ data := make(map[interface{}]interface{})
switch command {
case "conf":
- fmt.Fprintln(rw, "list all beego's conf:")
- fmt.Fprintln(rw, "AppName:", AppName)
- fmt.Fprintln(rw, "AppPath:", AppPath)
- fmt.Fprintln(rw, "AppConfigPath:", AppConfigPath)
- fmt.Fprintln(rw, "StaticDir:", StaticDir)
- fmt.Fprintln(rw, "StaticExtensionsToGzip:", StaticExtensionsToGzip)
- fmt.Fprintln(rw, "HttpAddr:", HttpAddr)
- fmt.Fprintln(rw, "HttpPort:", HttpPort)
- fmt.Fprintln(rw, "HttpTLS:", EnableHttpTLS)
- fmt.Fprintln(rw, "HttpCertFile:", HttpCertFile)
- fmt.Fprintln(rw, "HttpKeyFile:", HttpKeyFile)
- fmt.Fprintln(rw, "RecoverPanic:", RecoverPanic)
- fmt.Fprintln(rw, "AutoRender:", AutoRender)
- fmt.Fprintln(rw, "ViewsPath:", ViewsPath)
- fmt.Fprintln(rw, "RunMode:", RunMode)
- fmt.Fprintln(rw, "SessionOn:", SessionOn)
- fmt.Fprintln(rw, "SessionProvider:", SessionProvider)
- fmt.Fprintln(rw, "SessionName:", SessionName)
- fmt.Fprintln(rw, "SessionGCMaxLifetime:", SessionGCMaxLifetime)
- fmt.Fprintln(rw, "SessionSavePath:", SessionSavePath)
- fmt.Fprintln(rw, "SessionHashFunc:", SessionHashFunc)
- fmt.Fprintln(rw, "SessionHashKey:", SessionHashKey)
- fmt.Fprintln(rw, "SessionCookieLifeTime:", SessionCookieLifeTime)
- fmt.Fprintln(rw, "UseFcgi:", UseFcgi)
- fmt.Fprintln(rw, "MaxMemory:", MaxMemory)
- fmt.Fprintln(rw, "EnableGzip:", EnableGzip)
- fmt.Fprintln(rw, "DirectoryIndex:", DirectoryIndex)
- fmt.Fprintln(rw, "HttpServerTimeOut:", HttpServerTimeOut)
- fmt.Fprintln(rw, "ErrorsShow:", ErrorsShow)
- fmt.Fprintln(rw, "XSRFKEY:", XSRFKEY)
- fmt.Fprintln(rw, "EnableXSRF:", EnableXSRF)
- fmt.Fprintln(rw, "XSRFExpire:", XSRFExpire)
- fmt.Fprintln(rw, "CopyRequestBody:", CopyRequestBody)
- fmt.Fprintln(rw, "TemplateLeft:", TemplateLeft)
- fmt.Fprintln(rw, "TemplateRight:", TemplateRight)
- fmt.Fprintln(rw, "BeegoServerName:", BeegoServerName)
- fmt.Fprintln(rw, "EnableAdmin:", EnableAdmin)
- fmt.Fprintln(rw, "AdminHttpAddr:", AdminHttpAddr)
- fmt.Fprintln(rw, "AdminHttpPort:", AdminHttpPort)
+ m := make(map[string]interface{})
+
+ m["AppName"] = AppName
+ m["AppPath"] = AppPath
+ m["AppConfigPath"] = AppConfigPath
+ m["StaticDir"] = StaticDir
+ m["StaticExtensionsToGzip"] = StaticExtensionsToGzip
+ m["HttpAddr"] = HttpAddr
+ m["HttpPort"] = HttpPort
+ m["HttpTLS"] = EnableHttpTLS
+ m["HttpCertFile"] = HttpCertFile
+ m["HttpKeyFile"] = HttpKeyFile
+ m["RecoverPanic"] = RecoverPanic
+ m["AutoRender"] = AutoRender
+ m["ViewsPath"] = ViewsPath
+ m["RunMode"] = RunMode
+ m["SessionOn"] = SessionOn
+ m["SessionProvider"] = SessionProvider
+ m["SessionName"] = SessionName
+ m["SessionGCMaxLifetime"] = SessionGCMaxLifetime
+ m["SessionSavePath"] = SessionSavePath
+ m["SessionHashFunc"] = SessionHashFunc
+ m["SessionHashKey"] = SessionHashKey
+ m["SessionCookieLifeTime"] = SessionCookieLifeTime
+ m["UseFcgi"] = UseFcgi
+ m["MaxMemory"] = MaxMemory
+ m["EnableGzip"] = EnableGzip
+ m["DirectoryIndex"] = DirectoryIndex
+ m["HttpServerTimeOut"] = HttpServerTimeOut
+ m["ErrorsShow"] = ErrorsShow
+ m["XSRFKEY"] = XSRFKEY
+ m["EnableXSRF"] = EnableXSRF
+ m["XSRFExpire"] = XSRFExpire
+ m["CopyRequestBody"] = CopyRequestBody
+ m["TemplateLeft"] = TemplateLeft
+ m["TemplateRight"] = TemplateRight
+ m["BeegoServerName"] = BeegoServerName
+ m["EnableAdmin"] = EnableAdmin
+ m["AdminHttpAddr"] = AdminHttpAddr
+ m["AdminHttpPort"] = AdminHttpPort
+
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(configTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+
+ data["Content"] = m
+
+ tmpl.Execute(rw, data)
+
case "router":
- fmt.Fprintln(rw, "Print all router infomation:")
- for method, t := range BeeApp.Handlers.routers {
- fmt.Fprintln(rw)
- fmt.Fprintln(rw)
- fmt.Fprintln(rw, " Method:", method)
- printTree(rw, t)
+ resultList := new([][]string)
+
+ var result = []string{
+ fmt.Sprintf("header"),
+ fmt.Sprintf("Router Pattern"),
+ fmt.Sprintf("Methods"),
+ fmt.Sprintf("Controller"),
}
- // @todo print routers
+ *resultList = append(*resultList, result)
+
+ for method, t := range BeeApp.Handlers.routers {
+ var result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("Method: %s", method),
+ fmt.Sprintf(""),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
+
+ printTree(resultList, t)
+ }
+ data["Content"] = resultList
+ data["Title"] = "Routers"
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(routerAndFilterTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ tmpl.Execute(rw, data)
case "filter":
- fmt.Fprintln(rw, "Print all filter infomation:")
+ resultList := new([][]string)
+
+ var result = []string{
+ fmt.Sprintf("header"),
+ fmt.Sprintf("Router Pattern"),
+ fmt.Sprintf("Filter Function"),
+ }
+ *resultList = append(*resultList, result)
+
if BeeApp.Handlers.enableFilter {
- fmt.Fprintln(rw, "BeforeRouter:")
+ var result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("Before Router"),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
+
if bf, ok := BeeApp.Handlers.filters[BeforeRouter]; ok {
for _, f := range bf {
- fmt.Fprintln(rw, f.pattern, utils.GetFuncName(f.filterFunc))
+
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", f.pattern),
+ fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)),
+ }
+ *resultList = append(*resultList, result)
+
}
}
- fmt.Fprintln(rw, "BeforeExec:")
+ result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("Before Exec"),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
if bf, ok := BeeApp.Handlers.filters[BeforeExec]; ok {
for _, f := range bf {
- fmt.Fprintln(rw, f.pattern, utils.GetFuncName(f.filterFunc))
+
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", f.pattern),
+ fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)),
+ }
+ *resultList = append(*resultList, result)
+
}
}
- fmt.Fprintln(rw, "AfterExec:")
+ result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("AfterExec Exec"),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
+
if bf, ok := BeeApp.Handlers.filters[AfterExec]; ok {
for _, f := range bf {
- fmt.Fprintln(rw, f.pattern, utils.GetFuncName(f.filterFunc))
+
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", f.pattern),
+ fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)),
+ }
+ *resultList = append(*resultList, result)
+
}
}
- fmt.Fprintln(rw, "FinishRouter:")
+ result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("Finish Router"),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
+
if bf, ok := BeeApp.Handlers.filters[FinishRouter]; ok {
for _, f := range bf {
- fmt.Fprintln(rw, f.pattern, utils.GetFuncName(f.filterFunc))
+
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", f.pattern),
+ fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)),
+ }
+ *resultList = append(*resultList, result)
+
}
}
}
+ data["Content"] = resultList
+ data["Title"] = "Filters"
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(routerAndFilterTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ tmpl.Execute(rw, data)
+
default:
rw.Write([]byte("command not support"))
}
} else {
- rw.Write([]byte("beego admin dashboard"))
- rw.Write([]byte("ListConf support this command: \n"))
- rw.Write([]byte("1. command=conf \n"))
- rw.Write([]byte("2. command=router \n"))
- rw.Write([]byte("3. command=filter \n"))
- rw.Write([]byte(""))
}
}
-func printTree(rw http.ResponseWriter, t *Tree) {
+func printTree(resultList *[][]string, t *Tree) {
for _, tr := range t.fixrouters {
- printTree(rw, tr)
+ printTree(resultList, tr)
}
if t.wildcard != nil {
- printTree(rw, t.wildcard)
+ printTree(resultList, t.wildcard)
}
for _, l := range t.leaves {
if v, ok := l.runObject.(*controllerInfo); ok {
if v.routerType == routerTypeBeego {
- fmt.Fprintln(rw, v.pattern, v.methods, v.controllerType.Name())
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", v.pattern),
+ fmt.Sprintf("%s", v.methods),
+ fmt.Sprintf("%s", v.controllerType),
+ }
+ *resultList = append(*resultList, result)
} else if v.routerType == routerTypeRESTFul {
- fmt.Fprintln(rw, v.pattern, v.methods)
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", v.pattern),
+ fmt.Sprintf("%s", v.methods),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
} else if v.routerType == routerTypeHandler {
- fmt.Fprintln(rw, v.pattern, "handler")
+ var result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", v.pattern),
+ fmt.Sprintf(""),
+ fmt.Sprintf(""),
+ }
+ *resultList = append(*resultList, result)
}
}
}
@@ -194,58 +313,127 @@ func printTree(rw http.ResponseWriter, t *Tree) {
func profIndex(rw http.ResponseWriter, r *http.Request) {
r.ParseForm()
command := r.Form.Get("command")
+ format := r.Form.Get("format")
+ data := make(map[string]interface{})
+
+ var result bytes.Buffer
if command != "" {
- toolbox.ProcessInput(command, rw)
+ toolbox.ProcessInput(command, &result)
+ data["Content"] = result.String()
+
+ if format == "json" && command == "gc summary" {
+ dataJson, err := json.Marshal(data)
+ if err != nil {
+ http.Error(rw, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ rw.Header().Set("Content-Type", "application/json")
+ rw.Write(dataJson)
+ return
+ }
+
+ data["Title"] = command
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(profillingTpl))
+ if command == "gc summary" {
+ tmpl = template.Must(tmpl.Parse(gcAjaxTpl))
+ } else {
+
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ }
+ tmpl.Execute(rw, data)
} else {
- rw.Write([]byte("beego admin dashboard"))
- rw.Write([]byte("request url like '/prof?command=lookup goroutine' \n"))
- rw.Write([]byte("the command have below types: \n"))
- rw.Write([]byte("1. lookup goroutine \n"))
- rw.Write([]byte("2. lookup heap \n"))
- rw.Write([]byte("3. lookup threadcreate \n"))
- rw.Write([]byte("4. lookup block \n"))
- rw.Write([]byte("5. start cpuprof \n"))
- rw.Write([]byte("6. stop cpuprof \n"))
- rw.Write([]byte("7. get memprof \n"))
- rw.Write([]byte("8. gc summary \n"))
- rw.Write([]byte(""))
}
}
// Healthcheck is a http.Handler calling health checking and showing the result.
// it's in "/healthcheck" pattern in admin module.
func healthcheck(rw http.ResponseWriter, req *http.Request) {
+ data := make(map[interface{}]interface{})
+
+ resultList := new([][]string)
+ var result = []string{
+ fmt.Sprintf("header"),
+ fmt.Sprintf("Name"),
+ fmt.Sprintf("Status"),
+ }
+ *resultList = append(*resultList, result)
+
for name, h := range toolbox.AdminCheckList {
if err := h.Check(); err != nil {
- fmt.Fprintf(rw, "%s : %s\n", name, err.Error())
+ result = []string{
+ fmt.Sprintf("error"),
+ fmt.Sprintf("%s", name),
+ fmt.Sprintf("%s", err.Error()),
+ }
+
} else {
- fmt.Fprintf(rw, "%s : ok\n", name)
+ result = []string{
+ fmt.Sprintf("success"),
+ fmt.Sprintf("%s", name),
+ fmt.Sprintf("OK"),
+ }
+
}
+ *resultList = append(*resultList, result)
}
+
+ data["Content"] = resultList
+ data["Title"] = "Health Check"
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(healthCheckTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ tmpl.Execute(rw, data)
+
}
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
// it's in "/task" pattern in admin module.
func taskStatus(rw http.ResponseWriter, req *http.Request) {
- for tname, tk := range toolbox.AdminTaskList {
- fmt.Fprintf(rw, "%s:%s:%s", tname, tk.GetStatus(), tk.GetPrev().String())
- }
-}
+ data := make(map[interface{}]interface{})
-// RunTask is a http.Handler to run a Task from the "query string.
-// the request url likes /runtask?taskname=sendmail.
-func runTask(rw http.ResponseWriter, req *http.Request) {
+ // Run Task
req.ParseForm()
taskname := req.Form.Get("taskname")
- if t, ok := toolbox.AdminTaskList[taskname]; ok {
- err := t.Run()
- if err != nil {
- fmt.Fprintf(rw, "%v", err)
+ if taskname != "" {
+
+ if t, ok := toolbox.AdminTaskList[taskname]; ok {
+ err := t.Run()
+ if err != nil {
+ data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
+ }
+ data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is %s", taskname, t.GetStatus())}
+ } else {
+ data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)}
}
- fmt.Fprintf(rw, "%s run success,Now the Status is %s", taskname, t.GetStatus())
- } else {
- fmt.Fprintf(rw, "there's no task which named:%s", taskname)
}
+
+ // List Tasks
+ resultList := new([][]string)
+ var result = []string{
+ fmt.Sprintf("header"),
+ fmt.Sprintf("Task Name"),
+ fmt.Sprintf("Task Spec"),
+ fmt.Sprintf("Task Function"),
+ }
+ *resultList = append(*resultList, result)
+ for tname, tk := range toolbox.AdminTaskList {
+ result = []string{
+ fmt.Sprintf(""),
+ fmt.Sprintf("%s", tname),
+ fmt.Sprintf("%s", tk.GetStatus()),
+ fmt.Sprintf("%s", tk.GetPrev().String()),
+ }
+ *resultList = append(*resultList, result)
+ }
+
+ data["Content"] = resultList
+ data["Title"] = "Tasks"
+ tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
+ tmpl = template.Must(tmpl.Parse(tasksTpl))
+ tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
+ tmpl.Execute(rw, data)
}
// adminApp is an http.HandlerFunc map used as beeAdminApp.
diff --git a/adminui.go b/adminui.go
new file mode 100644
index 00000000..0c82775e
--- /dev/null
+++ b/adminui.go
@@ -0,0 +1,345 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package beego
+
+var indexTpl = `
+{{define "content"}}
+
+
+
+
+
+{{template "scripts" .}}
+
+
+`
diff --git a/app.go b/app.go
index 26e565c5..f1706616 100644
--- a/app.go
+++ b/app.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -66,6 +74,7 @@ func (app *App) Run() {
if EnableHttpTLS {
go func() {
+ time.Sleep(20 * time.Microsecond)
if HttpsPort != 0 {
app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort)
}
@@ -80,6 +89,7 @@ func (app *App) Run() {
if EnableHttpListen {
go func() {
+ app.Server.Addr = addr
err := app.Server.ListenAndServe()
if err != nil {
BeeLogger.Critical("ListenAndServe: ", err)
diff --git a/beego.go b/beego.go
index d230d998..46499743 100644
--- a/beego.go
+++ b/beego.go
@@ -1,9 +1,28 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// beego is an open-source, high-performance, modularity, full-stack web framework
+//
+// package main
+//
+// import "github.com/astaxie/beego"
+//
+// func main() {
+// beego.Run()
+// }
+//
+// more infomation: http://beego.me
package beego
import (
@@ -19,7 +38,7 @@ import (
)
// beego web framework version.
-const VERSION = "1.3.1"
+const VERSION = "1.4.0"
type hookfunc func() error //hook function to run
var hooks []hookfunc //hook function slice to store the hookfunc
@@ -359,6 +378,7 @@ func initBeforeHttpRun() {
`"sessionIDHashFunc":"` + SessionHashFunc + `",` +
`"sessionIDHashKey":"` + SessionHashKey + `",` +
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
+ `"domain":"` + SessionDomain + `",` +
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
}
GlobalSessions, err = session.NewManager(SessionProvider,
@@ -380,14 +400,13 @@ func initBeforeHttpRun() {
middleware.AppName = AppName
middleware.RegisterErrorHandler()
- for u, _ := range StaticDir {
- Get(u, serverStaticRouter)
- Get(u+"/*", serverStaticRouter)
- }
if EnableDocs {
Get("/docs", serverDocs)
Get("/docs/*", serverDocs)
}
+
+ //init mime
+ AddAPPStartHook(initMime)
}
// this function is for test package init
@@ -406,6 +425,4 @@ func TestBeegoInit(apppath string) {
func init() {
hooks = make([]hookfunc, 0)
- //init mime
- AddAPPStartHook(initMime)
}
diff --git a/cache/README.md b/cache/README.md
index c0bfcc59..72d0d1c5 100644
--- a/cache/README.md
+++ b/cache/README.md
@@ -22,7 +22,7 @@ First you must import it
Then init a Cache (example with memory adapter)
- bm, err := NewCache("memory", `{"interval":60}`)
+ bm, err := cache.NewCache("memory", `{"interval":60}`)
Use it like this:
diff --git a/cache/cache.go b/cache/cache.go
index 3273e2f9..d4ad5d59 100644
--- a/cache/cache.go
+++ b/cache/cache.go
@@ -1,9 +1,33 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+//
+// import(
+// "github.com/astaxie/beego/cache"
+// )
+//
+// bm, err := cache.NewCache("memory", `{"interval":60}`)
+//
+// Use it like this:
+//
+// bm.Put("astaxie", 1, 10)
+// bm.Get("astaxie")
+// bm.IsExist("astaxie")
+// bm.Delete("astaxie")
+//
+// more docs http://beego.me/docs/module/cache.md
package cache
import (
@@ -13,7 +37,7 @@ import (
// Cache interface contains all behaviors for cache adapter.
// usage:
// cache.Register("file",cache.NewFileCache()) // this operation is run in init method of file.go.
-// c := cache.NewCache("file","{....}")
+// c,err := cache.NewCache("file","{....}")
// c.Put("key",value,3600)
// v := c.Get("key")
//
@@ -31,11 +55,11 @@ type Cache interface {
Incr(key string) error
// decrease cached int value by key, as a counter.
Decr(key string) error
- // check cached value is existed or not.
+ // check if cached value exists or not.
IsExist(key string) bool
// clear all cache.
ClearAll() error
- // start gc routine via config string setting.
+ // start gc routine based on config string settings.
StartAndGC(config string) error
}
@@ -48,23 +72,24 @@ func Register(name string, adapter Cache) {
if adapter == nil {
panic("cache: Register adapter is nil")
}
- if _, dup := adapters[name]; dup {
+ if _, ok := adapters[name]; ok {
panic("cache: Register called twice for adapter " + name)
}
adapters[name] = adapter
}
-// Create a new cache driver by adapter and config string.
+// Create a new cache driver by adapter name and config string.
// config need to be correct JSON as string: {"interval":360}.
// it will start gc automatically.
-func NewCache(adapterName, config string) (Cache, error) {
+func NewCache(adapterName, config string) (adapter Cache, e error) {
adapter, ok := adapters[adapterName]
if !ok {
- return nil, fmt.Errorf("cache: unknown adaptername %q (forgotten import?)", adapterName)
+ e = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName)
+ return
}
err := adapter.StartAndGC(config)
if err != nil {
- return nil, err
+ adapter = nil
}
- return adapter, nil
+ return
}
diff --git a/cache/cache_test.go b/cache/cache_test.go
index 263ad257..bf9e79c2 100644
--- a/cache/cache_test.go
+++ b/cache/cache_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package cache
diff --git a/cache/conv.go b/cache/conv.go
index 00cbdd24..724abfd2 100644
--- a/cache/conv.go
+++ b/cache/conv.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package cache
@@ -19,12 +27,11 @@ func GetString(v interface{}) string {
case []byte:
return string(result)
default:
- if v == nil {
- return ""
- } else {
+ if v != nil {
return fmt.Sprintf("%v", result)
}
}
+ return ""
}
// convert interface to int.
@@ -37,12 +44,9 @@ func GetInt(v interface{}) int {
case int64:
return int(result)
default:
- d := GetString(v)
- if d != "" {
- value, err := strconv.Atoi(d)
- if err == nil {
- return value
- }
+ if d := GetString(v); d != "" {
+ value, _ := strconv.Atoi(d)
+ return value
}
}
return 0
@@ -58,12 +62,10 @@ func GetInt64(v interface{}) int64 {
case int64:
return result
default:
- d := GetString(v)
- if d != "" {
- result, err := strconv.ParseInt(d, 10, 64)
- if err == nil {
- return result
- }
+
+ if d := GetString(v); d != "" {
+ value, _ := strconv.ParseInt(d, 10, 64)
+ return value
}
}
return 0
@@ -75,12 +77,9 @@ func GetFloat64(v interface{}) float64 {
case float64:
return result
default:
- d := GetString(v)
- if d != "" {
- value, err := strconv.ParseFloat(d, 64)
- if err == nil {
- return value
- }
+ if d := GetString(v); d != "" {
+ value, _ := strconv.ParseFloat(d, 64)
+ return value
}
}
return 0
@@ -92,12 +91,9 @@ func GetBool(v interface{}) bool {
case bool:
return result
default:
- d := GetString(v)
- if d != "" {
- result, err := strconv.ParseBool(d)
- if err == nil {
- return result
- }
+ if d := GetString(v); d != "" {
+ value, _ := strconv.ParseBool(d)
+ return value
}
}
return false
diff --git a/cache/conv_test.go b/cache/conv_test.go
index 82d73af7..267bb0c9 100644
--- a/cache/conv_test.go
+++ b/cache/conv_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package cache
diff --git a/cache/file.go b/cache/file.go
index 7178aa20..6ecf6568 100644
--- a/cache/file.go
+++ b/cache/file.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package cache
@@ -57,12 +65,10 @@ func NewFileCache() *FileCache {
// Start and begin gc for file cache.
// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}
-func (this *FileCache) StartAndGC(config string) error {
+func (fc *FileCache) StartAndGC(config string) error {
var cfg map[string]string
json.Unmarshal([]byte(config), &cfg)
- //fmt.Println(cfg)
- //fmt.Println(config)
if _, ok := cfg["CachePath"]; !ok {
cfg["CachePath"] = FileCachePath
}
@@ -75,69 +81,53 @@ func (this *FileCache) StartAndGC(config string) error {
if _, ok := cfg["EmbedExpiry"]; !ok {
cfg["EmbedExpiry"] = strconv.FormatInt(FileCacheEmbedExpiry, 10)
}
- this.CachePath = cfg["CachePath"]
- this.FileSuffix = cfg["FileSuffix"]
- this.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
- this.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
+ fc.CachePath = cfg["CachePath"]
+ fc.FileSuffix = cfg["FileSuffix"]
+ fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
+ fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
- this.Init()
+ fc.Init()
return nil
}
// Init will make new dir for file cache if not exist.
-func (this *FileCache) Init() {
+func (fc *FileCache) Init() {
app := filepath.Dir(os.Args[0])
- this.CachePath = filepath.Join(app, this.CachePath)
- ok, err := exists(this.CachePath)
- if err != nil { // print error
- //fmt.Println(err)
+ fc.CachePath = filepath.Join(app, fc.CachePath)
+ if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
+ _ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
}
- if !ok {
- if err = os.Mkdir(this.CachePath, os.ModePerm); err != nil {
- //fmt.Println(err);
- }
- }
- //fmt.Println(this.getCacheFileName("123456"));
}
// get cached file name. it's md5 encoded.
-func (this *FileCache) getCacheFileName(key string) string {
+func (fc *FileCache) getCacheFileName(key string) string {
m := md5.New()
io.WriteString(m, key)
keyMd5 := hex.EncodeToString(m.Sum(nil))
- cachePath := this.CachePath
- //fmt.Println("cachepath : " , cachePath)
- //fmt.Println("md5" , keyMd5);
- switch this.DirectoryLevel {
+ cachePath := fc.CachePath
+ switch fc.DirectoryLevel {
case 2:
cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4])
case 1:
cachePath = filepath.Join(cachePath, keyMd5[0:2])
}
- ok, err := exists(cachePath)
- if err != nil {
- //fmt.Println(err)
+ if ok, _ := exists(cachePath); !ok { // todo : error handle
+ _ = os.MkdirAll(cachePath, os.ModePerm) // todo : error handle
}
- if !ok {
- if err = os.MkdirAll(cachePath, os.ModePerm); err != nil {
- //fmt.Println(err);
- }
- }
- return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, this.FileSuffix))
+
+ return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix))
}
// Get value from file cache.
// if non-exist or expired, return empty string.
-func (this *FileCache) Get(key string) interface{} {
- filename := this.getCacheFileName(key)
- filedata, err := File_get_contents(filename)
- //fmt.Println("get length:" , len(filedata));
+func (fc *FileCache) Get(key string) interface{} {
+ fileData, err := File_get_contents(fc.getCacheFileName(key))
if err != nil {
return ""
}
var to FileCacheItem
- Gob_decode(filedata, &to)
+ Gob_decode(fileData, &to)
if to.Expired < time.Now().Unix() {
return ""
}
@@ -147,12 +137,10 @@ func (this *FileCache) Get(key string) interface{} {
// Put value into file cache.
// timeout means how long to keep this file, unit of ms.
// if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever.
-func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
+func (fc *FileCache) Put(key string, val interface{}, timeout int64) error {
gob.Register(val)
- filename := this.getCacheFileName(key)
- var item FileCacheItem
- item.Data = val
+ item := FileCacheItem{Data: val}
if timeout == FileCacheEmbedExpiry {
item.Expired = time.Now().Unix() + (86400 * 365 * 10) // ten years
} else {
@@ -163,13 +151,12 @@ func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
if err != nil {
return err
}
- err = File_put_contents(filename, data)
- return err
+ return File_put_contents(fc.getCacheFileName(key), data)
}
// Delete file cache value.
-func (this *FileCache) Delete(key string) error {
- filename := this.getCacheFileName(key)
+func (fc *FileCache) Delete(key string) error {
+ filename := fc.getCacheFileName(key)
if ok, _ := exists(filename); ok {
return os.Remove(filename)
}
@@ -177,44 +164,41 @@ func (this *FileCache) Delete(key string) error {
}
// Increase cached int value.
-// this value is saving forever unless Delete.
-func (this *FileCache) Incr(key string) error {
- data := this.Get(key)
+// fc value is saving forever unless Delete.
+func (fc *FileCache) Incr(key string) error {
+ data := fc.Get(key)
var incr int
- //fmt.Println(reflect.TypeOf(data).Name())
if reflect.TypeOf(data).Name() != "int" {
incr = 0
} else {
incr = data.(int) + 1
}
- this.Put(key, incr, FileCacheEmbedExpiry)
+ fc.Put(key, incr, FileCacheEmbedExpiry)
return nil
}
// Decrease cached int value.
-func (this *FileCache) Decr(key string) error {
- data := this.Get(key)
+func (fc *FileCache) Decr(key string) error {
+ data := fc.Get(key)
var decr int
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
decr = 0
} else {
decr = data.(int) - 1
}
- this.Put(key, decr, FileCacheEmbedExpiry)
+ fc.Put(key, decr, FileCacheEmbedExpiry)
return nil
}
// Check value is exist.
-func (this *FileCache) IsExist(key string) bool {
- filename := this.getCacheFileName(key)
- ret, _ := exists(filename)
+func (fc *FileCache) IsExist(key string) bool {
+ ret, _ := exists(fc.getCacheFileName(key))
return ret
}
// Clean cached files.
// not implemented.
-func (this *FileCache) ClearAll() error {
- //this.CachePath
+func (fc *FileCache) ClearAll() error {
return nil
}
@@ -232,22 +216,22 @@ func exists(path string) (bool, error) {
// Get bytes to file.
// if non-exist, create this file.
-func File_get_contents(filename string) ([]byte, error) {
- f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
- if err != nil {
- return []byte(""), err
+func File_get_contents(filename string) (data []byte, e error) {
+ f, e := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
+ if e != nil {
+ return
}
defer f.Close()
- stat, err := f.Stat()
- if err != nil {
- return []byte(""), err
+ stat, e := f.Stat()
+ if e != nil {
+ return
}
- data := make([]byte, stat.Size())
- result, err := f.Read(data)
- if int64(result) == stat.Size() {
- return data, err
+ data = make([]byte, stat.Size())
+ result, e := f.Read(data)
+ if e != nil || int64(result) != stat.Size() {
+ return nil, e
}
- return []byte(""), err
+ return
}
// Put bytes to file.
diff --git a/cache/memcache/memcache.go b/cache/memcache/memcache.go
index 37658ffe..f5a5c6ef 100644
--- a/cache/memcache/memcache.go
+++ b/cache/memcache/memcache.go
@@ -1,24 +1,48 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package cache
+// package memcahe for cache provider
+//
+// depend on github.com/bradfitz/gomemcache/memcache
+//
+// go install github.com/bradfitz/gomemcache/memcache
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/cache/memcache"
+// "github.com/astaxie/beego/cache"
+// )
+//
+// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
+//
+// more docs http://beego.me/docs/module/cache.md
+package memcache
import (
"encoding/json"
"errors"
+ "strings"
- "github.com/beego/memcache"
+ "github.com/bradfitz/gomemcache/memcache"
"github.com/astaxie/beego/cache"
)
// Memcache adapter.
type MemcacheCache struct {
- c *memcache.Connection
- conninfo string
+ conn *memcache.Client
+ conninfo []string
}
// create new memcache adapter.
@@ -28,32 +52,21 @@ func NewMemCache() *MemcacheCache {
// get value from memcache.
func (rc *MemcacheCache) Get(key string) interface{} {
- if rc.c == nil {
- var err error
- rc.c, err = rc.connectInit()
- if err != nil {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
return err
}
}
- v, err := rc.c.Get(key)
- if err != nil {
- return nil
+ if item, err := rc.conn.Get(key); err == nil {
+ return string(item.Value)
}
- var contain interface{}
- if len(v) > 0 {
- contain = string(v[0].Value)
- } else {
- contain = nil
- }
- return contain
+ return nil
}
// put value to memcache. only support string.
func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
- if rc.c == nil {
- var err error
- rc.c, err = rc.connectInit()
- if err != nil {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
return err
}
}
@@ -61,69 +74,64 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
if !ok {
return errors.New("val must string")
}
- stored, err := rc.c.Set(key, 0, uint64(timeout), []byte(v))
- if err == nil && stored == false {
- return errors.New("stored fail")
- }
- return err
+ item := memcache.Item{Key: key, Value: []byte(v), Expiration: int32(timeout)}
+ return rc.conn.Set(&item)
}
// delete value in memcache.
func (rc *MemcacheCache) Delete(key string) error {
- if rc.c == nil {
- var err error
- rc.c, err = rc.connectInit()
- if err != nil {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
return err
}
}
- _, err := rc.c.Delete(key)
+ return rc.conn.Delete(key)
+}
+
+// increase counter.
+func (rc *MemcacheCache) Incr(key string) error {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
+ return err
+ }
+ }
+ _, err := rc.conn.Increment(key, 1)
return err
}
-// [Not Support]
-// increase counter.
-func (rc *MemcacheCache) Incr(key string) error {
- return errors.New("not support in memcache")
-}
-
-// [Not Support]
// decrease counter.
func (rc *MemcacheCache) Decr(key string) error {
- return errors.New("not support in memcache")
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
+ return err
+ }
+ }
+ _, err := rc.conn.Decrement(key, 1)
+ return err
}
// check value exists in memcache.
func (rc *MemcacheCache) IsExist(key string) bool {
- if rc.c == nil {
- var err error
- rc.c, err = rc.connectInit()
- if err != nil {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
return false
}
}
- v, err := rc.c.Get(key)
+ _, err := rc.conn.Get(key)
if err != nil {
return false
}
- if len(v) == 0 {
- return false
- } else {
- return true
- }
+ return true
}
// clear all cached in memcache.
func (rc *MemcacheCache) ClearAll() error {
- if rc.c == nil {
- var err error
- rc.c, err = rc.connectInit()
- if err != nil {
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
return err
}
}
- err := rc.c.FlushAll()
- return err
+ return rc.conn.FlushAll()
}
// start memcache adapter.
@@ -135,24 +143,19 @@ func (rc *MemcacheCache) StartAndGC(config string) error {
if _, ok := cf["conn"]; !ok {
return errors.New("config has no conn key")
}
- rc.conninfo = cf["conn"]
- var err error
- if rc.c != nil {
- rc.c, err = rc.connectInit()
- if err != nil {
- return errors.New("dial tcp conn error")
+ rc.conninfo = strings.Split(cf["conn"], ";")
+ if rc.conn == nil {
+ if err := rc.connectInit(); err != nil {
+ return err
}
}
return nil
}
// connect to memcache and keep the connection.
-func (rc *MemcacheCache) connectInit() (*memcache.Connection, error) {
- c, err := memcache.Connect(rc.conninfo)
- if err != nil {
- return nil, err
- }
- return c, nil
+func (rc *MemcacheCache) connectInit() error {
+ rc.conn = memcache.New(rc.conninfo...)
+ return nil
}
func init() {
diff --git a/cache/memory.go b/cache/memory.go
index 2d2f3803..b90d227c 100644
--- a/cache/memory.go
+++ b/cache/memory.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package cache
@@ -46,15 +54,14 @@ func NewMemoryCache() *MemoryCache {
func (bc *MemoryCache) Get(name string) interface{} {
bc.lock.RLock()
defer bc.lock.RUnlock()
- itm, ok := bc.items[name]
- if !ok {
- return nil
+ if itm, ok := bc.items[name]; ok {
+ if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired {
+ go bc.Delete(name)
+ return nil
+ }
+ return itm.val
}
- if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired {
- go bc.Delete(name)
- return nil
- }
- return itm.val
+ return nil
}
// Put cache to memory.
@@ -62,12 +69,11 @@ func (bc *MemoryCache) Get(name string) interface{} {
func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error {
bc.lock.Lock()
defer bc.lock.Unlock()
- t := MemoryItem{
+ bc.items[name] = &MemoryItem{
val: value,
Lastaccess: time.Now(),
expired: expired,
}
- bc.items[name] = &t
return nil
}
@@ -79,8 +85,7 @@ func (bc *MemoryCache) Delete(name string) error {
return errors.New("key not exist")
}
delete(bc.items, name)
- _, valid := bc.items[name]
- if valid {
+ if _, ok := bc.items[name]; ok {
return errors.New("delete key error")
}
return nil
@@ -211,8 +216,7 @@ func (bc *MemoryCache) item_expired(name string) bool {
if !ok {
return true
}
- sec := time.Now().Unix() - itm.Lastaccess.Unix()
- if sec >= itm.expired {
+ if time.Now().Unix()-itm.Lastaccess.Unix() >= itm.expired {
delete(bc.items, name)
return true
}
diff --git a/cache/redis/redis.go b/cache/redis/redis.go
index 451166a3..35cf88cd 100644
--- a/cache/redis/redis.go
+++ b/cache/redis/redis.go
@@ -1,17 +1,40 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package cache
+// package redis for cache provider
+//
+// depend on github.com/garyburd/redigo/redis
+//
+// go install github.com/garyburd/redigo/redis
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/cache/redis"
+// "github.com/astaxie/beego/cache"
+// )
+//
+// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
+//
+// more docs http://beego.me/docs/module/cache.md
+package redis
import (
"encoding/json"
"errors"
"time"
- "github.com/beego/redigo/redis"
+ "github.com/garyburd/redigo/redis"
"github.com/astaxie/beego/cache"
)
@@ -43,52 +66,74 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa
// Get cache from redis.
func (rc *RedisCache) Get(key string) interface{} {
- v, err := rc.do("HGET", rc.key, key)
- if err != nil {
- return nil
+ if v, err := rc.do("GET", key); err == nil {
+ return v
}
-
- return v
+ return nil
}
// put cache to redis.
-// timeout is ignored.
func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
- _, err := rc.do("HSET", rc.key, key, val)
+ var err error
+ if _, err = rc.do("SET", key, val); err != nil {
+ return err
+ }
+
+ if _, err = rc.do("HSET", rc.key, key, true); err != nil {
+ return err
+ }
+ _, err = rc.do("EXPIRE", key, timeout)
return err
}
// delete cache in redis.
func (rc *RedisCache) Delete(key string) error {
- _, err := rc.do("HDEL", rc.key, key)
+ var err error
+ if _, err = rc.do("DEL", key); err != nil {
+ return err
+ }
+ _, err = rc.do("HDEL", rc.key, key)
return err
}
-// check cache exist in redis.
+// check cache's existence in redis.
func (rc *RedisCache) IsExist(key string) bool {
- v, err := redis.Bool(rc.do("HEXISTS", rc.key, key))
+ v, err := redis.Bool(rc.do("EXISTS", key))
if err != nil {
return false
}
-
+ if v == false {
+ if _, err = rc.do("HDEL", rc.key, key); err != nil {
+ return false
+ }
+ }
return v
}
// increase counter in redis.
func (rc *RedisCache) Incr(key string) error {
- _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, 1))
+ _, err := redis.Bool(rc.do("INCRBY", key, 1))
return err
}
// decrease counter in redis.
func (rc *RedisCache) Decr(key string) error {
- _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, -1))
+ _, err := redis.Bool(rc.do("INCRBY", key, -1))
return err
}
// clean all cache in redis. delete this redis collection.
func (rc *RedisCache) ClearAll() error {
- _, err := rc.do("DEL", rc.key)
+ cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key))
+ if err != nil {
+ return err
+ }
+ for _, str := range cachedKeys {
+ if _, err = rc.do("DEL", str); err != nil {
+ return err
+ }
+ }
+ _, err = rc.do("DEL", rc.key)
return err
}
@@ -114,26 +159,21 @@ func (rc *RedisCache) StartAndGC(config string) error {
c := rc.p.Get()
defer c.Close()
- if err := c.Err(); err != nil {
- return err
- }
- return nil
+ return c.Err()
}
// connect to redis.
func (rc *RedisCache) connectInit() {
+ dialFunc := func() (c redis.Conn, err error) {
+ c, err = redis.Dial("tcp", rc.conninfo)
+ return
+ }
// initialize a new pool
rc.p = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 180 * time.Second,
- Dial: func() (redis.Conn, error) {
- c, err := redis.Dial("tcp", rc.conninfo)
- if err != nil {
- return nil, err
- }
- return c, nil
- },
+ Dial: dialFunc,
}
}
diff --git a/cache/redis/redis_test.go b/cache/redis/redis_test.go
new file mode 100644
index 00000000..fbe82ac5
--- /dev/null
+++ b/cache/redis/redis_test.go
@@ -0,0 +1,85 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package redis
+
+import (
+ "testing"
+ "time"
+
+ "github.com/garyburd/redigo/redis"
+
+ "github.com/astaxie/beego/cache"
+)
+
+func TestRedisCache(t *testing.T) {
+ bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`)
+ if err != nil {
+ t.Error("init err")
+ }
+ if err = bm.Put("astaxie", 1, 10); err != nil {
+ t.Error("set Error", err)
+ }
+ if !bm.IsExist("astaxie") {
+ t.Error("check err")
+ }
+
+ time.Sleep(10 * time.Second)
+
+ if bm.IsExist("astaxie") {
+ t.Error("check err")
+ }
+ if err = bm.Put("astaxie", 1, 10); err != nil {
+ t.Error("set Error", err)
+ }
+
+ if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
+ t.Error("get err")
+ }
+
+ if err = bm.Incr("astaxie"); err != nil {
+ t.Error("Incr Error", err)
+ }
+
+ if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 {
+ t.Error("get err")
+ }
+
+ if err = bm.Decr("astaxie"); err != nil {
+ t.Error("Decr Error", err)
+ }
+
+ if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
+ t.Error("get err")
+ }
+ bm.Delete("astaxie")
+ if bm.IsExist("astaxie") {
+ t.Error("delete err")
+ }
+ //test string
+ if err = bm.Put("astaxie", "author", 10); err != nil {
+ t.Error("set Error", err)
+ }
+ if !bm.IsExist("astaxie") {
+ t.Error("check err")
+ }
+
+ if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" {
+ t.Error("get err")
+ }
+ // test clear all
+ if err = bm.ClearAll(); err != nil {
+ t.Error("clear all err")
+ }
+}
diff --git a/config.go b/config.go
index 280edc6b..db234e16 100644
--- a/config.go
+++ b/config.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -52,6 +60,7 @@ var (
SessionHashKey string // session hash salt string.
SessionCookieLifeTime int // the life time of session id in cookie.
SessionAutoSetCookie bool // auto setcookie
+ SessionDomain string // the cookie domain default is empty
UseFcgi bool
MaxMemory int64
EnableGzip bool // flag of enable gzip
@@ -180,147 +189,147 @@ func ParseConfig() (err error) {
return err
} else {
- if v, err := getConfig("string", "HttpAddr"); err == nil {
+ if v, err := GetConfig("string", "HttpAddr"); err == nil {
HttpAddr = v.(string)
}
- if v, err := getConfig("int", "HttpPort"); err == nil {
+ if v, err := GetConfig("int", "HttpPort"); err == nil {
HttpPort = v.(int)
}
- if v, err := getConfig("bool", "EnableHttpListen"); err == nil {
+ if v, err := GetConfig("bool", "EnableHttpListen"); err == nil {
EnableHttpListen = v.(bool)
}
- if maxmemory, err := getConfig("int64", "MaxMemory"); err == nil {
+ if maxmemory, err := GetConfig("int64", "MaxMemory"); err == nil {
MaxMemory = maxmemory.(int64)
}
- if appname, _ := getConfig("string", "AppName"); appname != "" {
+ if appname, _ := GetConfig("string", "AppName"); appname != "" {
AppName = appname.(string)
}
- if runmode, _ := getConfig("string", "RunMode"); runmode != "" {
+ if runmode, _ := GetConfig("string", "RunMode"); runmode != "" {
RunMode = runmode.(string)
}
- if autorender, err := getConfig("bool", "AutoRender"); err == nil {
+ if autorender, err := GetConfig("bool", "AutoRender"); err == nil {
AutoRender = autorender.(bool)
}
- if autorecover, err := getConfig("bool", "RecoverPanic"); err == nil {
+ if autorecover, err := GetConfig("bool", "RecoverPanic"); err == nil {
RecoverPanic = autorecover.(bool)
}
- if views, _ := getConfig("string", "ViewsPath"); views != "" {
+ if views, _ := GetConfig("string", "ViewsPath"); views != "" {
ViewsPath = views.(string)
}
- if sessionon, err := getConfig("bool", "SessionOn"); err == nil {
+ if sessionon, err := GetConfig("bool", "SessionOn"); err == nil {
SessionOn = sessionon.(bool)
}
- if sessProvider, _ := getConfig("string", "SessionProvider"); sessProvider != "" {
+ if sessProvider, _ := GetConfig("string", "SessionProvider"); sessProvider != "" {
SessionProvider = sessProvider.(string)
}
- if sessName, _ := getConfig("string", "SessionName"); sessName != "" {
+ if sessName, _ := GetConfig("string", "SessionName"); sessName != "" {
SessionName = sessName.(string)
}
- if sesssavepath, _ := getConfig("string", "SessionSavePath"); sesssavepath != "" {
+ if sesssavepath, _ := GetConfig("string", "SessionSavePath"); sesssavepath != "" {
SessionSavePath = sesssavepath.(string)
}
- if sesshashfunc, _ := getConfig("string", "SessionHashFunc"); sesshashfunc != "" {
+ if sesshashfunc, _ := GetConfig("string", "SessionHashFunc"); sesshashfunc != "" {
SessionHashFunc = sesshashfunc.(string)
}
- if sesshashkey, _ := getConfig("string", "SessionHashKey"); sesshashkey != "" {
+ if sesshashkey, _ := GetConfig("string", "SessionHashKey"); sesshashkey != "" {
SessionHashKey = sesshashkey.(string)
}
- if sessMaxLifeTime, err := getConfig("int64", "SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 {
+ if sessMaxLifeTime, err := GetConfig("int64", "SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 {
SessionGCMaxLifetime = sessMaxLifeTime.(int64)
}
- if sesscookielifetime, err := getConfig("int", "SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 {
+ if sesscookielifetime, err := GetConfig("int", "SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 {
SessionCookieLifeTime = sesscookielifetime.(int)
}
- if usefcgi, err := getConfig("bool", "UseFcgi"); err == nil {
+ if usefcgi, err := GetConfig("bool", "UseFcgi"); err == nil {
UseFcgi = usefcgi.(bool)
}
- if enablegzip, err := getConfig("bool", "EnableGzip"); err == nil {
+ if enablegzip, err := GetConfig("bool", "EnableGzip"); err == nil {
EnableGzip = enablegzip.(bool)
}
- if directoryindex, err := getConfig("bool", "DirectoryIndex"); err == nil {
+ if directoryindex, err := GetConfig("bool", "DirectoryIndex"); err == nil {
DirectoryIndex = directoryindex.(bool)
}
- if timeout, err := getConfig("int64", "HttpServerTimeOut"); err == nil {
+ if timeout, err := GetConfig("int64", "HttpServerTimeOut"); err == nil {
HttpServerTimeOut = timeout.(int64)
}
- if errorsshow, err := getConfig("bool", "ErrorsShow"); err == nil {
+ if errorsshow, err := GetConfig("bool", "ErrorsShow"); err == nil {
ErrorsShow = errorsshow.(bool)
}
- if copyrequestbody, err := getConfig("bool", "CopyRequestBody"); err == nil {
+ if copyrequestbody, err := GetConfig("bool", "CopyRequestBody"); err == nil {
CopyRequestBody = copyrequestbody.(bool)
}
- if xsrfkey, _ := getConfig("string", "XSRFKEY"); xsrfkey != "" {
+ if xsrfkey, _ := GetConfig("string", "XSRFKEY"); xsrfkey != "" {
XSRFKEY = xsrfkey.(string)
}
- if enablexsrf, err := getConfig("bool", "EnableXSRF"); err == nil {
+ if enablexsrf, err := GetConfig("bool", "EnableXSRF"); err == nil {
EnableXSRF = enablexsrf.(bool)
}
- if expire, err := getConfig("int", "XSRFExpire"); err == nil {
+ if expire, err := GetConfig("int", "XSRFExpire"); err == nil {
XSRFExpire = expire.(int)
}
- if tplleft, _ := getConfig("string", "TemplateLeft"); tplleft != "" {
+ if tplleft, _ := GetConfig("string", "TemplateLeft"); tplleft != "" {
TemplateLeft = tplleft.(string)
}
- if tplright, _ := getConfig("string", "TemplateRight"); tplright != "" {
+ if tplright, _ := GetConfig("string", "TemplateRight"); tplright != "" {
TemplateRight = tplright.(string)
}
- if httptls, err := getConfig("bool", "EnableHttpTLS"); err == nil {
+ if httptls, err := GetConfig("bool", "EnableHttpTLS"); err == nil {
EnableHttpTLS = httptls.(bool)
}
- if httpsport, err := getConfig("int", "HttpsPort"); err == nil {
+ if httpsport, err := GetConfig("int", "HttpsPort"); err == nil {
HttpsPort = httpsport.(int)
}
- if certfile, _ := getConfig("string", "HttpCertFile"); certfile != "" {
+ if certfile, _ := GetConfig("string", "HttpCertFile"); certfile != "" {
HttpCertFile = certfile.(string)
}
- if keyfile, _ := getConfig("string", "HttpKeyFile"); keyfile != "" {
+ if keyfile, _ := GetConfig("string", "HttpKeyFile"); keyfile != "" {
HttpKeyFile = keyfile.(string)
}
- if serverName, _ := getConfig("string", "BeegoServerName"); serverName != "" {
+ if serverName, _ := GetConfig("string", "BeegoServerName"); serverName != "" {
BeegoServerName = serverName.(string)
}
- if flashname, _ := getConfig("string", "FlashName"); flashname != "" {
+ if flashname, _ := GetConfig("string", "FlashName"); flashname != "" {
FlashName = flashname.(string)
}
- if flashseperator, _ := getConfig("string", "FlashSeperator"); flashseperator != "" {
+ if flashseperator, _ := GetConfig("string", "FlashSeperator"); flashseperator != "" {
FlashSeperator = flashseperator.(string)
}
- if sd, _ := getConfig("string", "StaticDir"); sd != "" {
+ if sd, _ := GetConfig("string", "StaticDir"); sd != "" {
for k := range StaticDir {
delete(StaticDir, k)
}
@@ -334,7 +343,7 @@ func ParseConfig() (err error) {
}
}
- if sgz, _ := getConfig("string", "StaticExtensionsToGzip"); sgz != "" {
+ if sgz, _ := GetConfig("string", "StaticExtensionsToGzip"); sgz != "" {
extensions := strings.Split(sgz.(string), ",")
if len(extensions) > 0 {
StaticExtensionsToGzip = []string{}
@@ -351,26 +360,37 @@ func ParseConfig() (err error) {
}
}
- if enableadmin, err := getConfig("bool", "EnableAdmin"); err == nil {
+ if enableadmin, err := GetConfig("bool", "EnableAdmin"); err == nil {
EnableAdmin = enableadmin.(bool)
}
- if adminhttpaddr, _ := getConfig("string", "AdminHttpAddr"); adminhttpaddr != "" {
+ if adminhttpaddr, _ := GetConfig("string", "AdminHttpAddr"); adminhttpaddr != "" {
AdminHttpAddr = adminhttpaddr.(string)
}
- if adminhttpport, err := getConfig("int", "AdminHttpPort"); err == nil {
+ if adminhttpport, err := GetConfig("int", "AdminHttpPort"); err == nil {
AdminHttpPort = adminhttpport.(int)
}
- if enabledocs, err := getConfig("bool", "EnableDocs"); err == nil {
+ if enabledocs, err := GetConfig("bool", "EnableDocs"); err == nil {
EnableDocs = enabledocs.(bool)
}
}
return nil
}
-func getConfig(typ, key string) (interface{}, error) {
+// Getconfig throw the Runmode
+// [dev]
+// name = astaixe
+// IsEnable = false
+// [prod]
+// name = slene
+// IsEnable = true
+//
+// usage:
+// GetConfig("string", "name")
+// GetConfig("bool", "IsEnable")
+func GetConfig(typ, key string) (interface{}, error) {
switch typ {
case "string":
v := AppConfig.String(RunMode + "::" + key)
diff --git a/config/config.go b/config/config.go
index 7446abb4..8d9261b8 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,9 +1,44 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+// import(
+// "github.com/astaxie/beego/config"
+// )
+//
+// cnf, err := config.NewConfig("ini", "config.conf")
+//
+// cnf APIS:
+//
+// cnf.Set(key, val string) error
+// cnf.String(key string) string
+// cnf.Strings(key string) []string
+// cnf.Int(key string) (int, error)
+// cnf.Int64(key string) (int64, error)
+// cnf.Bool(key string) (bool, error)
+// cnf.Float(key string) (float64, error)
+// cnf.DefaultString(key string, defaultval string) string
+// cnf.DefaultStrings(key string, defaultval []string) []string
+// cnf.DefaultInt(key string, defaultval int) int
+// cnf.DefaultInt64(key string, defaultval int64) int64
+// cnf.DefaultBool(key string, defaultval bool) bool
+// cnf.DefaultFloat(key string, defaultval float64) float64
+// cnf.DIY(key string) (interface{}, error)
+// cnf.GetSection(section string) (map[string]string, error)
+// cnf.SaveConfigFile(filename string) error
+//
+// more docs http://beego.me/docs/module/config.md
package config
import (
@@ -19,12 +54,21 @@ type ConfigContainer interface {
Int64(key string) (int64, error)
Bool(key string) (bool, error)
Float(key string) (float64, error)
+ DefaultString(key string, defaultval string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
+ DefaultStrings(key string, defaultval []string) []string //get string slice
+ DefaultInt(key string, defaultval int) int
+ DefaultInt64(key string, defaultval int64) int64
+ DefaultBool(key string, defaultval bool) bool
+ DefaultFloat(key string, defaultval float64) float64
DIY(key string) (interface{}, error)
+ GetSection(section string) (map[string]string, error)
+ SaveConfigFile(filename string) error
}
// Config is the adapter interface for parsing config file to get raw data to ConfigContainer.
type Config interface {
Parse(key string) (ConfigContainer, error)
+ ParseData(data []byte) (ConfigContainer, error)
}
var adapters = make(map[string]Config)
@@ -36,7 +80,7 @@ func Register(name string, adapter Config) {
if adapter == nil {
panic("config: Register adapter is nil")
}
- if _, dup := adapters[name]; dup {
+ if _, ok := adapters[name]; ok {
panic("config: Register called twice for adapter " + name)
}
adapters[name] = adapter
@@ -51,3 +95,13 @@ func NewConfig(adapterName, fileaname string) (ConfigContainer, error) {
}
return adapter.Parse(fileaname)
}
+
+// adapterName is ini/json/xml/yaml.
+// data is the config data.
+func NewConfigData(adapterName string, data []byte) (ConfigContainer, error) {
+ adapter, ok := adapters[adapterName]
+ if !ok {
+ return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
+ }
+ return adapter.ParseData(data)
+}
diff --git a/config/fake.go b/config/fake.go
index ece4f696..54588e5e 100644
--- a/config/fake.go
+++ b/config/fake.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package config
@@ -17,13 +25,11 @@ type fakeConfigContainer struct {
}
func (c *fakeConfigContainer) getData(key string) string {
- key = strings.ToLower(key)
- return c.data[key]
+ return c.data[strings.ToLower(key)]
}
func (c *fakeConfigContainer) Set(key, val string) error {
- key = strings.ToLower(key)
- c.data[key] = val
+ c.data[strings.ToLower(key)] = val
return nil
}
@@ -31,34 +37,89 @@ func (c *fakeConfigContainer) String(key string) string {
return c.getData(key)
}
+func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string {
+ if v := c.getData(key); v == "" {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) Strings(key string) []string {
return strings.Split(c.getData(key), ";")
}
+func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string {
+ if v := c.Strings(key); len(v) == 0 {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) Int(key string) (int, error) {
return strconv.Atoi(c.getData(key))
}
+func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
+ if v, err := c.Int(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) Int64(key string) (int64, error) {
return strconv.ParseInt(c.getData(key), 10, 64)
}
+func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
+ if v, err := c.Int64(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) Bool(key string) (bool, error) {
return strconv.ParseBool(c.getData(key))
}
+func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
+ if v, err := c.Bool(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) Float(key string) (float64, error) {
return strconv.ParseFloat(c.getData(key), 64)
}
+func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
+ if v, err := c.Float(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
- key = strings.ToLower(key)
- if v, ok := c.data[key]; ok {
+ if v, ok := c.data[strings.ToLower(key)]; ok {
return v, nil
}
return nil, errors.New("key not find")
}
+func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) {
+ return nil, errors.New("not implement in the fakeConfigContainer")
+}
+
+func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
+ return errors.New("not implement in the fakeConfigContainer")
+}
+
var _ ConfigContainer = new(fakeConfigContainer)
func NewFakeConfig() ConfigContainer {
diff --git a/config/ini.go b/config/ini.go
index 0593864a..ec72a718 100644
--- a/config/ini.go
+++ b/config/ini.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package config
@@ -10,11 +18,15 @@ import (
"bufio"
"bytes"
"errors"
+ "fmt"
"io"
+ "io/ioutil"
"os"
+ "path"
"strconv"
"strings"
"sync"
+ "time"
"unicode"
)
@@ -27,6 +39,7 @@ var (
bDQuote = []byte{'"'} // quote signal
sectionStart = []byte{'['} // section start signal
sectionEnd = []byte{']'} // section end signal
+ lineBreak = "\n"
)
// IniConfig implements Config to parse ini file.
@@ -80,8 +93,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
}
if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) {
- section = string(line[1 : len(line)-1])
- section = strings.ToLower(section) // section name case insensitive
+ section = strings.ToLower(string(line[1 : len(line)-1])) // section name case insensitive
if comment.Len() > 0 {
cfg.sectionComment[section] = comment.String()
comment.Reset()
@@ -89,67 +101,124 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
if _, ok := cfg.data[section]; !ok {
cfg.data[section] = make(map[string]string)
}
- } else {
- if _, ok := cfg.data[section]; !ok {
- cfg.data[section] = make(map[string]string)
- }
- keyval := bytes.SplitN(line, bEqual, 2)
- val := bytes.TrimSpace(keyval[1])
- if bytes.HasPrefix(val, bDQuote) {
- val = bytes.Trim(val, `"`)
- }
+ continue
+ }
- key := string(bytes.TrimSpace(keyval[0])) // key name case insensitive
- key = strings.ToLower(key)
- cfg.data[section][key] = string(val)
- if comment.Len() > 0 {
- cfg.keycomment[section+"."+key] = comment.String()
- comment.Reset()
- }
+ if _, ok := cfg.data[section]; !ok {
+ cfg.data[section] = make(map[string]string)
+ }
+ keyValue := bytes.SplitN(line, bEqual, 2)
+ val := bytes.TrimSpace(keyValue[1])
+ if bytes.HasPrefix(val, bDQuote) {
+ val = bytes.Trim(val, `"`)
+ }
+
+ key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive
+ key = strings.ToLower(key)
+ cfg.data[section][key] = string(val)
+ if comment.Len() > 0 {
+ cfg.keyComment[section+"."+key] = comment.String()
+ comment.Reset()
}
}
return cfg, nil
}
+func (ini *IniConfig) ParseData(data []byte) (ConfigContainer, error) {
+ // Save memory data to temporary file
+ tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond()))
+ os.MkdirAll(path.Dir(tmpName), os.ModePerm)
+ if err := ioutil.WriteFile(tmpName, data, 0655); err != nil {
+ return nil, err
+ }
+ return ini.Parse(tmpName)
+}
+
// A Config represents the ini configuration.
// When set and get value, support key as section:name type.
type IniConfigContainer struct {
filename string
data map[string]map[string]string // section=> key:val
sectionComment map[string]string // section : comment
- keycomment map[string]string // id: []{comment, key...}; id 1 is for main comment.
+ keyComment map[string]string // id: []{comment, key...}; id 1 is for main comment.
sync.RWMutex
}
// Bool returns the boolean value for a given key.
func (c *IniConfigContainer) Bool(key string) (bool, error) {
- key = strings.ToLower(key)
- return strconv.ParseBool(c.getdata(key))
+ return strconv.ParseBool(c.getdata(strings.ToLower(key)))
+}
+
+// DefaultBool returns the boolean value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultBool(key string, defaultval bool) bool {
+ if v, err := c.Bool(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
}
// Int returns the integer value for a given key.
func (c *IniConfigContainer) Int(key string) (int, error) {
- key = strings.ToLower(key)
- return strconv.Atoi(c.getdata(key))
+ return strconv.Atoi(c.getdata(strings.ToLower(key)))
+}
+
+// DefaultInt returns the integer value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultInt(key string, defaultval int) int {
+ if v, err := c.Int(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
}
// Int64 returns the int64 value for a given key.
func (c *IniConfigContainer) Int64(key string) (int64, error) {
- key = strings.ToLower(key)
- return strconv.ParseInt(c.getdata(key), 10, 64)
+ return strconv.ParseInt(c.getdata(strings.ToLower(key)), 10, 64)
+}
+
+// DefaultInt64 returns the int64 value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
+ if v, err := c.Int64(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
}
// Float returns the float value for a given key.
func (c *IniConfigContainer) Float(key string) (float64, error) {
- key = strings.ToLower(key)
- return strconv.ParseFloat(c.getdata(key), 64)
+ return strconv.ParseFloat(c.getdata(strings.ToLower(key)), 64)
+}
+
+// DefaultFloat returns the float64 value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
+ if v, err := c.Float(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
}
// String returns the string value for a given key.
func (c *IniConfigContainer) String(key string) string {
key = strings.ToLower(key)
- return c.getdata(key)
+ return c.getdata(strings.ToLower(key))
+}
+
+// DefaultString returns the string value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultString(key string, defaultval string) string {
+ if v := c.String(key); v == "" {
+ return defaultval
+ } else {
+ return v
+ }
}
// Strings returns the []string value for a given key.
@@ -157,6 +226,78 @@ func (c *IniConfigContainer) Strings(key string) []string {
return strings.Split(c.String(key), ";")
}
+// DefaultStrings returns the []string value for a given key.
+// if err != nil return defaltval
+func (c *IniConfigContainer) DefaultStrings(key string, defaultval []string) []string {
+ if v := c.Strings(key); len(v) == 0 {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
+// GetSection returns map for the given section
+func (c *IniConfigContainer) GetSection(section string) (map[string]string, error) {
+ if v, ok := c.data[section]; ok {
+ return v, nil
+ } else {
+ return nil, errors.New("not exist setction")
+ }
+}
+
+// SaveConfigFile save the config into file
+func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
+ // Write configuration file by filename.
+ f, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ buf := bytes.NewBuffer(nil)
+ for section, dt := range c.data {
+ // Write section comments.
+ if v, ok := c.sectionComment[section]; ok {
+ if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil {
+ return err
+ }
+ }
+
+ if section != DEFAULT_SECTION {
+ // Write section name.
+ if _, err = buf.WriteString(string(sectionStart) + section + string(sectionEnd) + lineBreak); err != nil {
+ return err
+ }
+ }
+
+ for key, val := range dt {
+ if key != " " {
+ // Write key comments.
+ if v, ok := c.keyComment[key]; ok {
+ if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil {
+ return err
+ }
+ }
+
+ // Write key and value.
+ if _, err = buf.WriteString(key + string(bEqual) + val + lineBreak); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Put a line between sections.
+ if _, err = buf.WriteString(lineBreak); err != nil {
+ return err
+ }
+ }
+
+ if _, err = buf.WriteTo(f); err != nil {
+ return err
+ }
+ return nil
+}
+
// WriteValue writes a new value for key.
// if write to one section, the key need be "section::key".
// if the section is not existed, it panics.
@@ -167,16 +308,19 @@ func (c *IniConfigContainer) Set(key, value string) error {
return errors.New("key is empty")
}
- var section, k string
- key = strings.ToLower(key)
- sectionkey := strings.Split(key, "::")
- if len(sectionkey) >= 2 {
- section = sectionkey[0]
- k = sectionkey[1]
+ var (
+ section, k string
+ sectionKey []string = strings.Split(key, "::")
+ )
+
+ if len(sectionKey) >= 2 {
+ section = sectionKey[0]
+ k = sectionKey[1]
} else {
section = DEFAULT_SECTION
- k = sectionkey[0]
+ k = sectionKey[0]
}
+
if _, ok := c.data[section]; !ok {
c.data[section] = make(map[string]string)
}
@@ -186,8 +330,7 @@ func (c *IniConfigContainer) Set(key, value string) error {
// DIY returns the raw value by a given key.
func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
- key = strings.ToLower(key)
- if v, ok := c.data[key]; ok {
+ if v, ok := c.data[strings.ToLower(key)]; ok {
return v, nil
}
return v, errors.New("key not find")
@@ -201,18 +344,19 @@ func (c *IniConfigContainer) getdata(key string) string {
return ""
}
- var section, k string
- key = strings.ToLower(key)
- sectionkey := strings.Split(key, "::")
- if len(sectionkey) >= 2 {
- section = sectionkey[0]
- k = sectionkey[1]
+ var (
+ section, k string
+ sectionKey []string = strings.Split(key, "::")
+ )
+ if len(sectionKey) >= 2 {
+ section = sectionKey[0]
+ k = sectionKey[1]
} else {
section = DEFAULT_SECTION
- k = sectionkey[0]
+ k = sectionKey[0]
}
if v, ok := c.data[section]; ok {
- if vv, o := v[k]; o {
+ if vv, ok := v[k]; ok {
return vv
}
}
diff --git a/config/ini_test.go b/config/ini_test.go
index 3e792ded..7599ab8b 100644
--- a/config/ini_test.go
+++ b/config/ini_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package config
diff --git a/config/json.go b/config/json.go
index 440d98bf..ae86ea53 100644
--- a/config/json.go
+++ b/config/json.go
@@ -1,18 +1,29 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package config
import (
"encoding/json"
"errors"
+ "fmt"
"io/ioutil"
"os"
+ "path"
"strings"
"sync"
+ "time"
)
// JsonConfig is a json config parser and implements Config interface.
@@ -26,13 +37,13 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
return nil, err
}
defer file.Close()
- x := &JsonConfigContainer{
- data: make(map[string]interface{}),
- }
content, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
+ x := &JsonConfigContainer{
+ data: make(map[string]interface{}),
+ }
err = json.Unmarshal(content, &x.data)
if err != nil {
var wrappingArray []interface{}
@@ -45,6 +56,16 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
return x, nil
}
+func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) {
+ // Save memory data to temporary file
+ tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond()))
+ os.MkdirAll(path.Dir(tmpName), os.ModePerm)
+ if err := ioutil.WriteFile(tmpName, data, 0655); err != nil {
+ return nil, err
+ }
+ return js.Parse(tmpName)
+}
+
// A Config represents the json configuration.
// Only when get value, support key as section:name type.
type JsonConfigContainer struct {
@@ -54,71 +75,110 @@ type JsonConfigContainer struct {
// Bool returns the boolean value for a given key.
func (c *JsonConfigContainer) Bool(key string) (bool, error) {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
if v, ok := val.(bool); ok {
return v, nil
- } else {
- return false, errors.New("not bool value")
}
+ return false, errors.New("not bool value")
+ }
+ return false, errors.New("not exist key:" + key)
+}
+
+// DefaultBool return the bool value if has no error
+// otherwise return the defaultval
+func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool {
+ if v, err := c.Bool(key); err != nil {
+ return defaultval
} else {
- return false, errors.New("not exist key:" + key)
+ return v
}
}
// Int returns the integer value for a given key.
func (c *JsonConfigContainer) Int(key string) (int, error) {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
if v, ok := val.(float64); ok {
return int(v), nil
- } else {
- return 0, errors.New("not int value")
}
+ return 0, errors.New("not int value")
+ }
+ return 0, errors.New("not exist key:" + key)
+}
+
+// DefaultInt returns the integer value for a given key.
+// if err != nil return defaltval
+func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int {
+ if v, err := c.Int(key); err != nil {
+ return defaultval
} else {
- return 0, errors.New("not exist key:" + key)
+ return v
}
}
// Int64 returns the int64 value for a given key.
func (c *JsonConfigContainer) Int64(key string) (int64, error) {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
if v, ok := val.(float64); ok {
return int64(v), nil
- } else {
- return 0, errors.New("not int64 value")
}
+ return 0, errors.New("not int64 value")
+ }
+ return 0, errors.New("not exist key:" + key)
+}
+
+// DefaultInt64 returns the int64 value for a given key.
+// if err != nil return defaltval
+func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
+ if v, err := c.Int64(key); err != nil {
+ return defaultval
} else {
- return 0, errors.New("not exist key:" + key)
+ return v
}
}
// Float returns the float value for a given key.
func (c *JsonConfigContainer) Float(key string) (float64, error) {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
if v, ok := val.(float64); ok {
return v, nil
- } else {
- return 0.0, errors.New("not float64 value")
}
+ return 0.0, errors.New("not float64 value")
+ }
+ return 0.0, errors.New("not exist key:" + key)
+}
+
+// DefaultFloat returns the float64 value for a given key.
+// if err != nil return defaltval
+func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
+ if v, err := c.Float(key); err != nil {
+ return defaultval
} else {
- return 0.0, errors.New("not exist key:" + key)
+ return v
}
}
// String returns the string value for a given key.
func (c *JsonConfigContainer) String(key string) string {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
if v, ok := val.(string); ok {
return v
- } else {
- return ""
}
+ }
+ return ""
+}
+
+// DefaultString returns the string value for a given key.
+// if err != nil return defaltval
+func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string {
+ if v := c.String(key); v == "" {
+ return defaultval
} else {
- return ""
+ return v
}
}
@@ -127,6 +187,41 @@ func (c *JsonConfigContainer) Strings(key string) []string {
return strings.Split(c.String(key), ";")
}
+// DefaultStrings returns the []string value for a given key.
+// if err != nil return defaltval
+func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string {
+ if v := c.Strings(key); len(v) == 0 {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
+// GetSection returns map for the given section
+func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) {
+ if v, ok := c.data[section]; ok {
+ return v.(map[string]string), nil
+ } else {
+ return nil, errors.New("not exist setction")
+ }
+}
+
+// SaveConfigFile save the config into file
+func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) {
+ // Write configuration file by filename.
+ f, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ b, err := json.MarshalIndent(c.data, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = f.Write(b)
+ return err
+}
+
// WriteValue writes a new value for key.
func (c *JsonConfigContainer) Set(key, val string) error {
c.Lock()
@@ -137,39 +232,37 @@ func (c *JsonConfigContainer) Set(key, val string) error {
// DIY returns the raw value by a given key.
func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
- val := c.getdata(key)
+ val := c.getData(key)
if val != nil {
return val, nil
- } else {
- return nil, errors.New("not exist key")
}
+ return nil, errors.New("not exist key")
}
// section.key or key
-func (c *JsonConfigContainer) getdata(key string) interface{} {
+func (c *JsonConfigContainer) getData(key string) interface{} {
c.RLock()
defer c.RUnlock()
if len(key) == 0 {
return nil
}
- sectionkey := strings.Split(key, "::")
- if len(sectionkey) >= 2 {
- cruval, ok := c.data[sectionkey[0]]
+ sectionKey := strings.Split(key, "::")
+ if len(sectionKey) >= 2 {
+ curValue, ok := c.data[sectionKey[0]]
if !ok {
return nil
}
- for _, key := range sectionkey[1:] {
- if v, ok := cruval.(map[string]interface{}); !ok {
- return nil
- } else if cruval, ok = v[key]; !ok {
- return nil
+ for _, key := range sectionKey[1:] {
+ if v, ok := curValue.(map[string]interface{}); ok {
+ if curValue, ok = v[key]; !ok {
+ return nil
+ }
}
}
- return cruval
- } else {
- if v, ok := c.data[key]; ok {
- return v
- }
+ return curValue
+ }
+ if v, ok := c.data[key]; ok {
+ return v
}
return nil
}
diff --git a/config/json_test.go b/config/json_test.go
index a2741941..409e2c12 100644
--- a/config/json_test.go
+++ b/config/json_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package config
@@ -61,13 +69,13 @@ func TestJsonStartsWithArray(t *testing.T) {
t.Fatal(err)
}
rootArray, err := jsonconf.DIY("rootArray")
- if (err != nil) {
+ if err != nil {
t.Error("array does not exist as element")
}
rootArrayCasted := rootArray.([]interface{})
- if (rootArrayCasted == nil) {
+ if rootArrayCasted == nil {
t.Error("array from root is nil")
- }else {
+ } else {
elem := rootArrayCasted[0].(map[string]interface{})
if elem["url"] != "user" || elem["serviceAPI"] != "http://www.test.com/user" {
t.Error("array[0] values are not valid")
diff --git a/config/xml/xml.go b/config/xml/xml.go
index f763d4f0..a1d9fcdb 100644
--- a/config/xml/xml.go
+++ b/config/xml/xml.go
@@ -1,18 +1,45 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package config
+// package xml for config provider
+//
+// depend on github.com/beego/x2j
+//
+// go install github.com/beego/x2j
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/config/xml"
+// "github.com/astaxie/beego/config"
+// )
+//
+// cnf, err := config.NewConfig("xml", "config.xml")
+//
+// more docs http://beego.me/docs/module/config.md
+package xml
import (
+ "encoding/xml"
"errors"
+ "fmt"
"io/ioutil"
"os"
+ "path"
"strconv"
"strings"
"sync"
+ "time"
"github.com/astaxie/beego/config"
"github.com/beego/x2j"
@@ -21,31 +48,41 @@ import (
// XmlConfig is a xml config parser and implements Config interface.
// xml configurations should be included in tag.
// only support key/value pair as value as each item.
-type XMLConfig struct {
-}
+type XMLConfig struct{}
// Parse returns a ConfigContainer with parsed xml config map.
-func (xmls *XMLConfig) Parse(filename string) (config.ConfigContainer, error) {
+func (xc *XMLConfig) Parse(filename string) (config.ConfigContainer, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
- x := &XMLConfigContainer{
- data: make(map[string]interface{}),
- }
+
+ x := &XMLConfigContainer{data: make(map[string]interface{})}
content, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
+
d, err := x2j.DocToMap(string(content))
if err != nil {
return nil, err
}
+
x.data = d["config"].(map[string]interface{})
return x, nil
}
+func (x *XMLConfig) ParseData(data []byte) (config.ConfigContainer, error) {
+ // Save memory data to temporary file
+ tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond()))
+ os.MkdirAll(path.Dir(tmpName), os.ModePerm)
+ if err := ioutil.WriteFile(tmpName, data, 0655); err != nil {
+ return nil, err
+ }
+ return x.Parse(tmpName)
+}
+
// A Config represents the xml configuration.
type XMLConfigContainer struct {
data map[string]interface{}
@@ -57,21 +94,61 @@ func (c *XMLConfigContainer) Bool(key string) (bool, error) {
return strconv.ParseBool(c.data[key].(string))
}
+// DefaultBool return the bool value if has no error
+// otherwise return the defaultval
+func (c *XMLConfigContainer) DefaultBool(key string, defaultval bool) bool {
+ if v, err := c.Bool(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Int returns the integer value for a given key.
func (c *XMLConfigContainer) Int(key string) (int, error) {
return strconv.Atoi(c.data[key].(string))
}
+// DefaultInt returns the integer value for a given key.
+// if err != nil return defaltval
+func (c *XMLConfigContainer) DefaultInt(key string, defaultval int) int {
+ if v, err := c.Int(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Int64 returns the int64 value for a given key.
func (c *XMLConfigContainer) Int64(key string) (int64, error) {
return strconv.ParseInt(c.data[key].(string), 10, 64)
}
+// DefaultInt64 returns the int64 value for a given key.
+// if err != nil return defaltval
+func (c *XMLConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
+ if v, err := c.Int64(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Float returns the float value for a given key.
func (c *XMLConfigContainer) Float(key string) (float64, error) {
return strconv.ParseFloat(c.data[key].(string), 64)
}
+// DefaultFloat returns the float64 value for a given key.
+// if err != nil return defaltval
+func (c *XMLConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
+ if v, err := c.Float(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// String returns the string value for a given key.
func (c *XMLConfigContainer) String(key string) string {
if v, ok := c.data[key].(string); ok {
@@ -80,11 +157,56 @@ func (c *XMLConfigContainer) String(key string) string {
return ""
}
+// DefaultString returns the string value for a given key.
+// if err != nil return defaltval
+func (c *XMLConfigContainer) DefaultString(key string, defaultval string) string {
+ if v := c.String(key); v == "" {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Strings returns the []string value for a given key.
func (c *XMLConfigContainer) Strings(key string) []string {
return strings.Split(c.String(key), ";")
}
+// DefaultStrings returns the []string value for a given key.
+// if err != nil return defaltval
+func (c *XMLConfigContainer) DefaultStrings(key string, defaultval []string) []string {
+ if v := c.Strings(key); len(v) == 0 {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
+// GetSection returns map for the given section
+func (c *XMLConfigContainer) GetSection(section string) (map[string]string, error) {
+ if v, ok := c.data[section]; ok {
+ return v.(map[string]string), nil
+ } else {
+ return nil, errors.New("not exist setction")
+ }
+}
+
+// SaveConfigFile save the config into file
+func (c *XMLConfigContainer) SaveConfigFile(filename string) (err error) {
+ // Write configuration file by filename.
+ f, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ b, err := xml.MarshalIndent(c.data, " ", " ")
+ if err != nil {
+ return err
+ }
+ _, err = f.Write(b)
+ return err
+}
+
// WriteValue writes a new value for key.
func (c *XMLConfigContainer) Set(key, val string) error {
c.Lock()
diff --git a/config/xml/xml_test.go b/config/xml/xml_test.go
index 767b02ed..fa3c17f1 100644
--- a/config/xml/xml_test.go
+++ b/config/xml/xml_test.go
@@ -1,10 +1,18 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package config
+package xml
import (
"os"
diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go
index 04a6def3..c5be44a9 100644
--- a/config/yaml/yaml.go
+++ b/config/yaml/yaml.go
@@ -1,59 +1,92 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package config
+// package yaml for config provider
+//
+// depend on github.com/beego/goyaml2
+//
+// go install github.com/beego/goyaml2
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/config/yaml"
+// "github.com/astaxie/beego/config"
+// )
+//
+// cnf, err := config.NewConfig("yaml", "config.yaml")
+//
+// more docs http://beego.me/docs/module/config.md
+package yaml
import (
"bytes"
"encoding/json"
"errors"
+ "fmt"
"io/ioutil"
"log"
"os"
+ "path"
"strings"
"sync"
+ "time"
"github.com/astaxie/beego/config"
"github.com/beego/goyaml2"
)
// YAMLConfig is a yaml config parser and implements Config interface.
-type YAMLConfig struct {
-}
+type YAMLConfig struct{}
// Parse returns a ConfigContainer with parsed yaml config map.
-func (yaml *YAMLConfig) Parse(filename string) (config.ConfigContainer, error) {
- y := &YAMLConfigContainer{
- data: make(map[string]interface{}),
- }
+func (yaml *YAMLConfig) Parse(filename string) (y config.ConfigContainer, err error) {
cnf, err := ReadYmlReader(filename)
if err != nil {
+ return
+ }
+ y = &YAMLConfigContainer{
+ data: cnf,
+ }
+ return
+}
+
+func (yaml *YAMLConfig) ParseData(data []byte) (config.ConfigContainer, error) {
+ // Save memory data to temporary file
+ tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond()))
+ os.MkdirAll(path.Dir(tmpName), os.ModePerm)
+ if err := ioutil.WriteFile(tmpName, data, 0655); err != nil {
return nil, err
}
- y.data = cnf
- return y, nil
+ return yaml.Parse(tmpName)
}
// Read yaml file to map.
// if json like, use json package, unless goyaml2 package.
func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
- err = nil
f, err := os.Open(path)
if err != nil {
return
}
defer f.Close()
- err = nil
+
buf, err := ioutil.ReadAll(f)
if err != nil || len(buf) < 3 {
return
}
if string(buf[0:1]) == "{" {
- log.Println("Look lile a Json, try it")
+ log.Println("Look like a Json, try json umarshal")
err = json.Unmarshal(buf, &cnf)
if err == nil {
log.Println("It is Json Map")
@@ -61,19 +94,19 @@ func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
}
}
- _map, _err := goyaml2.Read(bytes.NewBuffer(buf))
- if _err != nil {
- log.Println("Goyaml2 ERR>", string(buf), _err)
- //err = goyaml.Unmarshal(buf, &cnf)
- err = _err
+ data, err := goyaml2.Read(bytes.NewBuffer(buf))
+ if err != nil {
+ log.Println("Goyaml2 ERR>", string(buf), err)
return
}
- if _map == nil {
+
+ if data == nil {
log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf))
+ return
}
- cnf, ok := _map.(map[string]interface{})
+ cnf, ok := data.(map[string]interface{})
if !ok {
- log.Println("Not a Map? >> ", string(buf), _map)
+ log.Println("Not a Map? >> ", string(buf), data)
cnf = nil
}
return
@@ -93,6 +126,16 @@ func (c *YAMLConfigContainer) Bool(key string) (bool, error) {
return false, errors.New("not bool value")
}
+// DefaultBool return the bool value if has no error
+// otherwise return the defaultval
+func (c *YAMLConfigContainer) DefaultBool(key string, defaultval bool) bool {
+ if v, err := c.Bool(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Int returns the integer value for a given key.
func (c *YAMLConfigContainer) Int(key string) (int, error) {
if v, ok := c.data[key].(int64); ok {
@@ -101,6 +144,16 @@ func (c *YAMLConfigContainer) Int(key string) (int, error) {
return 0, errors.New("not int value")
}
+// DefaultInt returns the integer value for a given key.
+// if err != nil return defaltval
+func (c *YAMLConfigContainer) DefaultInt(key string, defaultval int) int {
+ if v, err := c.Int(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Int64 returns the int64 value for a given key.
func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
if v, ok := c.data[key].(int64); ok {
@@ -109,6 +162,16 @@ func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
return 0, errors.New("not bool value")
}
+// DefaultInt64 returns the int64 value for a given key.
+// if err != nil return defaltval
+func (c *YAMLConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
+ if v, err := c.Int64(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Float returns the float value for a given key.
func (c *YAMLConfigContainer) Float(key string) (float64, error) {
if v, ok := c.data[key].(float64); ok {
@@ -117,6 +180,16 @@ func (c *YAMLConfigContainer) Float(key string) (float64, error) {
return 0.0, errors.New("not float64 value")
}
+// DefaultFloat returns the float64 value for a given key.
+// if err != nil return defaltval
+func (c *YAMLConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
+ if v, err := c.Float(key); err != nil {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// String returns the string value for a given key.
func (c *YAMLConfigContainer) String(key string) string {
if v, ok := c.data[key].(string); ok {
@@ -125,11 +198,52 @@ func (c *YAMLConfigContainer) String(key string) string {
return ""
}
+// DefaultString returns the string value for a given key.
+// if err != nil return defaltval
+func (c *YAMLConfigContainer) DefaultString(key string, defaultval string) string {
+ if v := c.String(key); v == "" {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
// Strings returns the []string value for a given key.
func (c *YAMLConfigContainer) Strings(key string) []string {
return strings.Split(c.String(key), ";")
}
+// DefaultStrings returns the []string value for a given key.
+// if err != nil return defaltval
+func (c *YAMLConfigContainer) DefaultStrings(key string, defaultval []string) []string {
+ if v := c.Strings(key); len(v) == 0 {
+ return defaultval
+ } else {
+ return v
+ }
+}
+
+// GetSection returns map for the given section
+func (c *YAMLConfigContainer) GetSection(section string) (map[string]string, error) {
+ if v, ok := c.data[section]; ok {
+ return v.(map[string]string), nil
+ } else {
+ return nil, errors.New("not exist setction")
+ }
+}
+
+// SaveConfigFile save the config into file
+func (c *YAMLConfigContainer) SaveConfigFile(filename string) (err error) {
+ // Write configuration file by filename.
+ f, err := os.Create(filename)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ err = goyaml2.Write(f, c.data)
+ return err
+}
+
// WriteValue writes a new value for key.
func (c *YAMLConfigContainer) Set(key, val string) error {
c.Lock()
diff --git a/config/yaml/yaml_test.go b/config/yaml/yaml_test.go
index fbeaf654..19ecdca1 100644
--- a/config/yaml/yaml_test.go
+++ b/config/yaml/yaml_test.go
@@ -1,10 +1,18 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
-package config
+package yaml
import (
"os"
diff --git a/config_test.go b/config_test.go
index 19eaeacf..17645f80 100644
--- a/config_test.go
+++ b/config_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/context/context.go b/context/context.go
index 87986bec..d31076d4 100644
--- a/context/context.go
+++ b/context/context.go
@@ -1,9 +1,24 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+//
+// import "github.com/astaxie/beego/context"
+//
+// ctx := context.Context{Request:req,ResponseWriter:rw}
+//
+// more docs http://beego.me/docs/module/context.md
package context
import (
@@ -17,6 +32,7 @@ import (
"time"
"github.com/astaxie/beego/middleware"
+ "github.com/astaxie/beego/utils"
)
// Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
@@ -26,20 +42,21 @@ type Context struct {
Output *BeegoOutput
Request *http.Request
ResponseWriter http.ResponseWriter
+ _xsrf_token string
}
// Redirect does redirection to localurl with http header status code.
// It sends http response header directly.
func (ctx *Context) Redirect(status int, localurl string) {
ctx.Output.Header("Location", localurl)
- ctx.Output.SetStatus(status)
+ ctx.ResponseWriter.WriteHeader(status)
}
// Abort stops this request.
// if middleware.ErrorMaps exists, panic body.
// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string.
func (ctx *Context) Abort(status int, body string) {
- ctx.Output.SetStatus(status)
+ ctx.ResponseWriter.WriteHeader(status)
// first panic from ErrorMaps, is is user defined error functions.
if _, ok := middleware.ErrorMaps[body]; ok {
panic(body)
@@ -58,7 +75,7 @@ func (ctx *Context) Abort(status int, body string) {
// Write string to response body.
// it sends response body.
func (ctx *Context) WriteString(content string) {
- ctx.Output.Body([]byte(content))
+ ctx.ResponseWriter.Write([]byte(content))
}
// Get cookie from request by a given key.
@@ -110,3 +127,35 @@ func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interf
cookie := strings.Join([]string{vs, timestamp, sig}, "|")
ctx.Output.Cookie(name, cookie, others...)
}
+
+// XsrfToken creates a xsrf token string and returns.
+func (ctx *Context) XsrfToken(key string, expire int64) string {
+ if ctx._xsrf_token == "" {
+ token, ok := ctx.GetSecureCookie(key, "_xsrf")
+ if !ok {
+ token = string(utils.RandomCreateBytes(32))
+ ctx.SetSecureCookie(key, "_xsrf", token, expire)
+ }
+ ctx._xsrf_token = token
+ }
+ return ctx._xsrf_token
+}
+
+// CheckXsrfCookie checks xsrf token in this request is valid or not.
+// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
+// or in form field value named as "_xsrf".
+func (ctx *Context) CheckXsrfCookie() bool {
+ token := ctx.Input.Query("_xsrf")
+ if token == "" {
+ token = ctx.Request.Header.Get("X-Xsrftoken")
+ }
+ if token == "" {
+ token = ctx.Request.Header.Get("X-Csrftoken")
+ }
+ if token == "" {
+ ctx.Abort(403, "'_xsrf' argument missing from POST")
+ } else if ctx._xsrf_token != token {
+ ctx.Abort(403, "XSRF cookie does not match POST argument")
+ }
+ return true
+}
diff --git a/context/input.go b/context/input.go
index 400f8a57..c6038693 100644
--- a/context/input.go
+++ b/context/input.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package context
diff --git a/context/input_test.go b/context/input_test.go
index f53d013d..ddd1a056 100644
--- a/context/input_test.go
+++ b/context/input_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package context
diff --git a/context/output.go b/context/output.go
index 8011392f..6298ee77 100644
--- a/context/output.go
+++ b/context/output.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package context
@@ -68,6 +76,14 @@ func (output *BeegoOutput) Body(content []byte) {
} else {
output.Header("Content-Length", strconv.Itoa(len(content)))
}
+
+ // Write status code if it has been set manually
+ // Set it to 0 afterwards to prevent "multiple response.WriteHeader calls"
+ if output.Status != 0 {
+ output.Context.ResponseWriter.WriteHeader(output.Status)
+ output.Status = 0
+ }
+
output_writer.Write(content)
switch output_writer.(type) {
case *gzip.Writer:
@@ -267,7 +283,6 @@ func (output *BeegoOutput) ContentType(ext string) {
// SetStatus sets response status code.
// It writes response header directly.
func (output *BeegoOutput) SetStatus(status int) {
- output.Context.ResponseWriter.WriteHeader(status)
output.Status = status
}
diff --git a/controller.go b/controller.go
index d1f19e43..eee79513 100644
--- a/controller.go
+++ b/controller.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -22,7 +30,6 @@ import (
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/session"
- "github.com/astaxie/beego/utils"
)
//commonly used mime-types
@@ -270,6 +277,11 @@ func (c *Controller) Abort(code string) {
}
}
+// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
+func (c *Controller) CustomAbort(status int, body string) {
+ c.Ctx.Abort(status, body)
+}
+
// StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
func (c *Controller) StopRun() {
panic(USERSTOPRUN)
@@ -474,18 +486,13 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter
// XsrfToken creates a xsrf token string and returns.
func (c *Controller) XsrfToken() string {
if c._xsrf_token == "" {
- token, ok := c.GetSecureCookie(XSRFKEY, "_xsrf")
- if !ok {
- var expire int64
- if c.XSRFExpire > 0 {
- expire = int64(c.XSRFExpire)
- } else {
- expire = int64(XSRFExpire)
- }
- token = string(utils.RandomCreateBytes(32))
- c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire)
+ var expire int64
+ if c.XSRFExpire > 0 {
+ expire = int64(c.XSRFExpire)
+ } else {
+ expire = int64(XSRFExpire)
}
- c._xsrf_token = token
+ c._xsrf_token = c.Ctx.XsrfToken(XSRFKEY, expire)
}
return c._xsrf_token
}
@@ -497,19 +504,7 @@ func (c *Controller) CheckXsrfCookie() bool {
if !c.EnableXSRF {
return true
}
- token := c.GetString("_xsrf")
- if token == "" {
- token = c.Ctx.Request.Header.Get("X-Xsrftoken")
- }
- if token == "" {
- token = c.Ctx.Request.Header.Get("X-Csrftoken")
- }
- if token == "" {
- c.Ctx.Abort(403, "'_xsrf' argument missing from POST")
- } else if c._xsrf_token != token {
- c.Ctx.Abort(403, "XSRF cookie does not match POST argument")
- }
- return true
+ return c.Ctx.CheckXsrfCookie()
}
// XsrfFormHtml writes an input field contains xsrf token value.
diff --git a/docs.go b/docs.go
index b8e7d193..aaad205e 100644
--- a/docs.go
+++ b/docs.go
@@ -1,3 +1,17 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package beego
import (
diff --git a/example/beeapi/main.go b/example/beeapi/main.go
index bed06196..c1250e03 100644
--- a/example/beeapi/main.go
+++ b/example/beeapi/main.go
@@ -1,7 +1,11 @@
// Beego (http://beego.me/)
+
// @description beego is an open-source, high-performance web framework for the Go programming language.
+
// @link http://github.com/astaxie/beego for the canonical source repository
+
// @license http://github.com/astaxie/beego/blob/master/LICENSE
+
// @authors astaxie
package main
diff --git a/filter.go b/filter.go
index a7db36a4..294966d4 100644
--- a/filter.go
+++ b/filter.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/filter_test.go b/filter_test.go
index e5428b96..ff6f750b 100644
--- a/filter_test.go
+++ b/filter_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/flash.go b/flash.go
index a67ee5c8..6e85141f 100644
--- a/flash.go
+++ b/flash.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/flash_test.go b/flash_test.go
index f0a17480..7c581e6a 100644
--- a/flash_test.go
+++ b/flash_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/httplib/httplib.go b/httplib/httplib.go
index f7d083f2..1c0d5544 100644
--- a/httplib/httplib.go
+++ b/httplib/httplib.go
@@ -1,9 +1,33 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+//
+// import "github.com/astaxie/beego/context"
+//
+// b := httplib.Post("http://beego.me/")
+// b.Param("username","astaxie")
+// b.Param("password","123456")
+// b.PostFile("uploadfile1", "httplib.pdf")
+// b.PostFile("uploadfile2", "httplib.txt")
+// str, err := b.String()
+// if err != nil {
+// t.Fatal(err)
+// }
+// fmt.Println(str)
+//
+// more docs http://beego.me/docs/module/httplib.md
package httplib
import (
@@ -52,41 +76,46 @@ func SetDefaultSetting(setting BeegoHttpSettings) {
// Get returns *BeegoHttpRequest with GET method.
func Get(url string) *BeegoHttpRequest {
var req http.Request
+ var resp http.Response
req.Method = "GET"
req.Header = http.Header{}
- return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting}
+ return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil}
}
// Post returns *BeegoHttpRequest with POST method.
func Post(url string) *BeegoHttpRequest {
var req http.Request
+ var resp http.Response
req.Method = "POST"
req.Header = http.Header{}
- return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting}
+ return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil}
}
// Put returns *BeegoHttpRequest with PUT method.
func Put(url string) *BeegoHttpRequest {
var req http.Request
+ var resp http.Response
req.Method = "PUT"
req.Header = http.Header{}
- return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting}
+ return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil}
}
// Delete returns *BeegoHttpRequest DELETE GET method.
func Delete(url string) *BeegoHttpRequest {
var req http.Request
+ var resp http.Response
req.Method = "DELETE"
req.Header = http.Header{}
- return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting}
+ return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil}
}
// Head returns *BeegoHttpRequest with HEAD method.
func Head(url string) *BeegoHttpRequest {
var req http.Request
+ var resp http.Response
req.Method = "HEAD"
req.Header = http.Header{}
- return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting}
+ return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil}
}
// BeegoHttpSettings
@@ -108,6 +137,8 @@ type BeegoHttpRequest struct {
params map[string]string
files map[string]string
setting BeegoHttpSettings
+ resp *http.Response
+ body []byte
}
// Change request settings
@@ -123,7 +154,7 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest {
}
// SetUserAgent sets User-Agent header field
-func (b *BeegoHttpRequest) SetAgent(useragent string) *BeegoHttpRequest {
+func (b *BeegoHttpRequest) SetUserAgent(useragent string) *BeegoHttpRequest {
b.setting.UserAgent = useragent
return b
}
@@ -223,6 +254,9 @@ func (b *BeegoHttpRequest) Body(data interface{}) *BeegoHttpRequest {
}
func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
+ if b.resp.StatusCode != 0 {
+ return b.resp, nil
+ }
var paramBody string
if len(b.params) > 0 {
var buf bytes.Buffer
@@ -341,6 +375,7 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
if err != nil {
return nil, err
}
+ b.resp = resp
return resp, nil
}
@@ -358,6 +393,9 @@ func (b *BeegoHttpRequest) String() (string, error) {
// Bytes returns the body []byte in response.
// it calls Response inner.
func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
+ if b.body != nil {
+ return b.body, nil
+ }
resp, err := b.getResponse()
if err != nil {
return nil, err
@@ -370,6 +408,7 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
if err != nil {
return nil, err
}
+ b.body = data
return data, nil
}
@@ -391,10 +430,7 @@ func (b *BeegoHttpRequest) ToFile(filename string) error {
}
defer resp.Body.Close()
_, err = io.Copy(f, resp.Body)
- if err != nil {
- return err
- }
- return nil
+ return err
}
// ToJson returns the map that marshals from the body bytes as json in response .
@@ -405,24 +441,18 @@ func (b *BeegoHttpRequest) ToJson(v interface{}) error {
return err
}
err = json.Unmarshal(data, v)
- if err != nil {
- return err
- }
- return nil
+ return err
}
// ToXml returns the map that marshals from the body bytes as xml in response .
// it calls Response inner.
-func (b *BeegoHttpRequest) ToXML(v interface{}) error {
+func (b *BeegoHttpRequest) ToXml(v interface{}) error {
data, err := b.Bytes()
if err != nil {
return err
}
err = xml.Unmarshal(data, v)
- if err != nil {
- return err
- }
- return nil
+ return err
}
// Response executes request client gets response mannually.
diff --git a/httplib/httplib_test.go b/httplib/httplib_test.go
index 7325862c..2d49d875 100644
--- a/httplib/httplib_test.go
+++ b/httplib/httplib_test.go
@@ -1,100 +1,193 @@
-// Beego (http://beego.me)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package httplib
import (
- "fmt"
"io/ioutil"
+ "os"
+ "strings"
"testing"
)
-func TestGetUrl(t *testing.T) {
- resp, err := Get("http://beego.me").Debug(true).Response()
+func TestResponse(t *testing.T) {
+ req := Get("http://httpbin.org/get")
+ resp, err := req.Response()
if err != nil {
t.Fatal(err)
}
- if resp.Body == nil {
- t.Fatal("body is nil")
- }
- data, err := ioutil.ReadAll(resp.Body)
- defer resp.Body.Close()
- if err != nil {
- t.Fatal(err)
- }
- if len(data) == 0 {
- t.Fatal("data is no")
- }
+ t.Log(resp)
+}
- str, err := Get("http://beego.me").String()
+func TestGet(t *testing.T) {
+ req := Get("http://httpbin.org/get")
+ b, err := req.Bytes()
if err != nil {
t.Fatal(err)
}
- if len(str) == 0 {
- t.Fatal("has no info")
+ t.Log(b)
+
+ s, err := req.String()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(s)
+
+ if string(b) != s {
+ t.Fatal("request data not match")
}
}
-func ExamplePost(t *testing.T) {
- b := Post("http://beego.me/").Debug(true)
- b.Param("username", "astaxie")
- b.Param("password", "hello")
- b.PostFile("uploadfile", "httplib_test.go")
- str, err := b.String()
+func TestSimplePost(t *testing.T) {
+ v := "smallfish"
+ req := Post("http://httpbin.org/post")
+ req.Param("username", v)
+
+ str, err := req.String()
if err != nil {
t.Fatal(err)
}
- fmt.Println(str)
+ t.Log(str)
+
+ n := strings.Index(str, v)
+ if n == -1 {
+ t.Fatal(v + " not found in post")
+ }
}
-func TestSimpleGetString(t *testing.T) {
- fmt.Println("TestSimpleGetString==========================================")
- html, err := Get("http://httpbin.org/headers").SetAgent("beegoooooo").String()
+func TestPostFile(t *testing.T) {
+ v := "smallfish"
+ req := Post("http://httpbin.org/post")
+ req.Param("username", v)
+ req.PostFile("uploadfile", "httplib_test.go")
+
+ str, err := req.String()
if err != nil {
t.Fatal(err)
}
- fmt.Println(html)
- fmt.Println("TestSimpleGetString==========================================")
+ t.Log(str)
+
+ n := strings.Index(str, v)
+ if n == -1 {
+ t.Fatal(v + " not found in post")
+ }
}
-func TestSimpleGetStringWithDefaultCookie(t *testing.T) {
- fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================")
- html, err := Get("http://httpbin.org/cookies/set?k1=v1").SetEnableCookie(true).String()
+func TestSimplePut(t *testing.T) {
+ str, err := Put("http://httpbin.org/put").String()
if err != nil {
t.Fatal(err)
}
- fmt.Println(html)
- html, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String()
- if err != nil {
- t.Fatal(err)
- }
- fmt.Println(html)
- fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================")
+ t.Log(str)
}
-func TestDefaultSetting(t *testing.T) {
- fmt.Println("TestDefaultSetting==========================================")
- var def BeegoHttpSettings
- def.EnableCookie = true
- //def.ShowDebug = true
- def.UserAgent = "UserAgent"
- //def.ConnectTimeout = 60*time.Second
- //def.ReadWriteTimeout = 60*time.Second
- def.Transport = nil //http.DefaultTransport
- SetDefaultSetting(def)
-
- html, err := Get("http://httpbin.org/headers").String()
+func TestSimpleDelete(t *testing.T) {
+ str, err := Delete("http://httpbin.org/delete").String()
if err != nil {
t.Fatal(err)
}
- fmt.Println(html)
- html, err = Get("http://httpbin.org/headers").String()
- if err != nil {
- t.Fatal(err)
- }
- fmt.Println(html)
- fmt.Println("TestDefaultSetting==========================================")
+ t.Log(str)
+}
+
+func TestWithCookie(t *testing.T) {
+ v := "smallfish"
+ str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(str)
+
+ str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(str)
+
+ n := strings.Index(str, v)
+ if n == -1 {
+ t.Fatal(v + " not found in cookie")
+ }
+}
+
+func TestWithUserAgent(t *testing.T) {
+ v := "beego"
+ str, err := Get("http://httpbin.org/headers").SetUserAgent(v).String()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(str)
+
+ n := strings.Index(str, v)
+ if n == -1 {
+ t.Fatal(v + " not found in user-agent")
+ }
+}
+
+func TestWithSetting(t *testing.T) {
+ v := "beego"
+ var setting BeegoHttpSettings
+ setting.EnableCookie = true
+ setting.UserAgent = v
+ setting.Transport = nil
+ SetDefaultSetting(setting)
+
+ str, err := Get("http://httpbin.org/get").String()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(str)
+
+ n := strings.Index(str, v)
+ if n == -1 {
+ t.Fatal(v + " not found in user-agent")
+ }
+}
+
+func TestToJson(t *testing.T) {
+ req := Get("http://httpbin.org/ip")
+ resp, err := req.Response()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(resp)
+
+ // httpbin will return http remote addr
+ type Ip struct {
+ Origin string `json:"origin"`
+ }
+ var ip Ip
+ err = req.ToJson(&ip)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Log(ip.Origin)
+
+ if n := strings.Count(ip.Origin, "."); n != 3 {
+ t.Fatal("response is not valid ip")
+ }
+}
+
+func TestToFile(t *testing.T) {
+ f := "beego_testfile"
+ req := Get("http://httpbin.org/ip")
+ err := req.ToFile(f)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(f)
+ b, err := ioutil.ReadFile(f)
+ if n := strings.Index(string(b), "origin"); n == -1 {
+ t.Fatal(err)
+ }
}
diff --git a/log.go b/log.go
index ac72ec34..5afba8ed 100644
--- a/log.go
+++ b/log.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -14,12 +22,14 @@ import (
// Log levels to control the logging output.
const (
- LevelTrace = iota
- LevelDebug
- LevelInfo
- LevelWarning
- LevelError
+ LevelEmergency = iota
+ LevelAlert
LevelCritical
+ LevelError
+ LevelWarning
+ LevelNotice
+ LevelInformational
+ LevelDebug
)
// SetLogLevel sets the global log level used by the simple
@@ -45,29 +55,12 @@ func SetLogger(adaptername string, config string) error {
return nil
}
-// Trace logs a message at trace level.
-func Trace(v ...interface{}) {
- BeeLogger.Trace(generateFmtStr(len(v)), v...)
+func Emergency(v ...interface{}) {
+ BeeLogger.Emergency(generateFmtStr(len(v)), v...)
}
-// Debug logs a message at debug level.
-func Debug(v ...interface{}) {
- BeeLogger.Debug(generateFmtStr(len(v)), v...)
-}
-
-// Info logs a message at info level.
-func Info(v ...interface{}) {
- BeeLogger.Info(generateFmtStr(len(v)), v...)
-}
-
-// Warning logs a message at warning level.
-func Warn(v ...interface{}) {
- BeeLogger.Warn(generateFmtStr(len(v)), v...)
-}
-
-// Error logs a message at error level.
-func Error(v ...interface{}) {
- BeeLogger.Error(generateFmtStr(len(v)), v...)
+func Alert(v ...interface{}) {
+ BeeLogger.Alert(generateFmtStr(len(v)), v...)
}
// Critical logs a message at critical level.
@@ -75,6 +68,46 @@ func Critical(v ...interface{}) {
BeeLogger.Critical(generateFmtStr(len(v)), v...)
}
+// Error logs a message at error level.
+func Error(v ...interface{}) {
+ BeeLogger.Error(generateFmtStr(len(v)), v...)
+}
+
+// Warning logs a message at warning level.
+func Warning(v ...interface{}) {
+ BeeLogger.Warning(generateFmtStr(len(v)), v...)
+}
+
+// Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0.
+func Warn(v ...interface{}) {
+ Warning(v...)
+}
+
+func Notice(v ...interface{}) {
+ BeeLogger.Notice(generateFmtStr(len(v)), v...)
+}
+
+// Info logs a message at info level.
+func Informational(v ...interface{}) {
+ BeeLogger.Informational(generateFmtStr(len(v)), v...)
+}
+
+// Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0.
+func Info(v ...interface{}) {
+ Informational(v...)
+}
+
+// Debug logs a message at debug level.
+func Debug(v ...interface{}) {
+ BeeLogger.Debug(generateFmtStr(len(v)), v...)
+}
+
+// Trace logs a message at trace level.
+// Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0.
+func Trace(v ...interface{}) {
+ BeeLogger.Trace(generateFmtStr(len(v)), v...)
+}
+
func generateFmtStr(n int) string {
return strings.Repeat("%v ", n)
}
diff --git a/logs/conn.go b/logs/conn.go
index 588e73f4..612634fa 100644
--- a/logs/conn.go
+++ b/logs/conn.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -45,7 +53,7 @@ func (c *ConnWriter) Init(jsonconfig string) error {
// write message in connection.
// if connection is down, try to re-connect.
func (c *ConnWriter) WriteMsg(msg string, level int) error {
- if level < c.Level {
+ if level > c.Level {
return nil
}
if c.neddedConnectOnMsg() {
diff --git a/logs/conn_test.go b/logs/conn_test.go
index e05cbe05..747fb890 100644
--- a/logs/conn_test.go
+++ b/logs/conn_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -13,5 +21,5 @@ import (
func TestConn(t *testing.T) {
log := NewLogger(1000)
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
- log.Info("info")
+ log.Informational("informational")
}
diff --git a/logs/console.go b/logs/console.go
index 9316a55e..461291c2 100644
--- a/logs/console.go
+++ b/logs/console.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -24,12 +32,14 @@ func NewBrush(color string) Brush {
}
var colors = []Brush{
- NewBrush("1;36"), // Trace cyan
- NewBrush("1;34"), // Debug blue
- NewBrush("1;32"), // Info green
- NewBrush("1;33"), // Warn yellow
+ NewBrush("1;37"), // Emergency white
+ NewBrush("1;36"), // Alert cyan
+ NewBrush("1;35"), // Critical magenta
NewBrush("1;31"), // Error red
- NewBrush("1;35"), // Critical purple
+ NewBrush("1;33"), // Warning yellow
+ NewBrush("1;32"), // Notice green
+ NewBrush("1;34"), // Informational blue
+ NewBrush("1;34"), // Debug blue
}
// ConsoleWriter implements LoggerInterface and writes messages to terminal.
@@ -42,7 +52,7 @@ type ConsoleWriter struct {
func NewConsole() LoggerInterface {
cw := new(ConsoleWriter)
cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime)
- cw.Level = LevelTrace
+ cw.Level = LevelDebug
return cw
}
@@ -61,7 +71,7 @@ func (c *ConsoleWriter) Init(jsonconfig string) error {
// write message in console.
func (c *ConsoleWriter) WriteMsg(msg string, level int) error {
- if level < c.Level {
+ if level > c.Level {
return nil
}
if goos := runtime.GOOS; goos == "windows" {
diff --git a/logs/console_test.go b/logs/console_test.go
index a8c942c1..2fad7241 100644
--- a/logs/console_test.go
+++ b/logs/console_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -10,22 +18,29 @@ import (
"testing"
)
+// Try each log level in decreasing order of priority.
+func testConsoleCalls(bl *BeeLogger) {
+ bl.Emergency("emergency")
+ bl.Alert("alert")
+ bl.Critical("critical")
+ bl.Error("error")
+ bl.Warning("warning")
+ bl.Notice("notice")
+ bl.Informational("informational")
+ bl.Debug("debug")
+}
+
+// Test console logging by visually comparing the lines being output with and
+// without a log level specification.
func TestConsole(t *testing.T) {
- log := NewLogger(10000)
- log.EnableFuncCallDepth(true)
- log.SetLogger("console", "")
- log.Trace("trace")
- log.Info("info")
- log.Warn("warning")
- log.Debug("debug")
- log.Critical("critical")
+ log1 := NewLogger(10000)
+ log1.EnableFuncCallDepth(true)
+ log1.SetLogger("console", "")
+ testConsoleCalls(log1)
+
log2 := NewLogger(100)
- log2.SetLogger("console", `{"level":1}`)
- log.Trace("trace")
- log.Info("info")
- log.Warn("warning")
- log.Debug("debug")
- log.Critical("critical")
+ log2.SetLogger("console", `{"level":3}`)
+ testConsoleCalls(log2)
}
func BenchmarkConsole(b *testing.B) {
@@ -33,6 +48,6 @@ func BenchmarkConsole(b *testing.B) {
log.EnableFuncCallDepth(true)
log.SetLogger("console", "")
for i := 0; i < b.N; i++ {
- log.Trace("trace")
+ log.Debug("debug")
}
}
diff --git a/logs/file.go b/logs/file.go
index f5cbb9ff..e80b955c 100644
--- a/logs/file.go
+++ b/logs/file.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -138,7 +146,7 @@ func (w *FileLogWriter) docheck(size int) {
// write logger message into file.
func (w *FileLogWriter) WriteMsg(msg string, level int) error {
- if level < w.Level {
+ if level > w.Level {
return nil
}
n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] "
diff --git a/logs/file_test.go b/logs/file_test.go
index 90349ec6..c71e9bb4 100644
--- a/logs/file_test.go
+++ b/logs/file_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -10,6 +18,7 @@ import (
"bufio"
"fmt"
"os"
+ "strconv"
"testing"
"time"
)
@@ -17,12 +26,14 @@ import (
func TestFile(t *testing.T) {
log := NewLogger(10000)
log.SetLogger("file", `{"filename":"test.log"}`)
- log.Trace("test")
- log.Info("info")
log.Debug("debug")
- log.Warn("warning")
+ log.Informational("info")
+ log.Notice("notice")
+ log.Warning("warning")
log.Error("error")
+ log.Alert("alert")
log.Critical("critical")
+ log.Emergency("emergency")
time.Sleep(time.Second * 4)
f, err := os.Open("test.log")
if err != nil {
@@ -39,21 +50,24 @@ func TestFile(t *testing.T) {
linenum++
}
}
- if linenum != 6 {
- t.Fatal(linenum, "not line 6")
+ var expected = LevelDebug + 1
+ if linenum != expected {
+ t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines")
}
os.Remove("test.log")
}
func TestFile2(t *testing.T) {
log := NewLogger(10000)
- log.SetLogger("file", `{"filename":"test2.log","level":2}`)
- log.Trace("test")
- log.Info("info")
+ log.SetLogger("file", fmt.Sprintf(`{"filename":"test2.log","level":%d}`, LevelError))
log.Debug("debug")
- log.Warn("warning")
+ log.Info("info")
+ log.Notice("notice")
+ log.Warning("warning")
log.Error("error")
+ log.Alert("alert")
log.Critical("critical")
+ log.Emergency("emergency")
time.Sleep(time.Second * 4)
f, err := os.Open("test2.log")
if err != nil {
@@ -70,8 +84,9 @@ func TestFile2(t *testing.T) {
linenum++
}
}
- if linenum != 4 {
- t.Fatal(linenum, "not line 4")
+ var expected = LevelError + 1
+ if linenum != expected {
+ t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines")
}
os.Remove("test2.log")
}
@@ -79,17 +94,19 @@ func TestFile2(t *testing.T) {
func TestFileRotate(t *testing.T) {
log := NewLogger(10000)
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
- log.Trace("test")
- log.Info("info")
log.Debug("debug")
- log.Warn("warning")
+ log.Info("info")
+ log.Notice("notice")
+ log.Warning("warning")
log.Error("error")
+ log.Alert("alert")
log.Critical("critical")
+ log.Emergency("emergency")
time.Sleep(time.Second * 4)
rotatename := "test3.log" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1)
b, err := exists(rotatename)
if !b || err != nil {
- t.Fatal("rotate not gen")
+ t.Fatal("rotate not generated")
}
os.Remove(rotatename)
os.Remove("test3.log")
@@ -110,7 +127,7 @@ func BenchmarkFile(b *testing.B) {
log := NewLogger(100000)
log.SetLogger("file", `{"filename":"test4.log"}`)
for i := 0; i < b.N; i++ {
- log.Trace("trace")
+ log.Debug("debug")
}
os.Remove("test4.log")
}
diff --git a/logs/log.go b/logs/log.go
index 423f9ec3..4349e8a5 100644
--- a/logs/log.go
+++ b/logs/log.go
@@ -1,9 +1,35 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+//
+// import "github.com/astaxie/beego/logs"
+//
+// log := NewLogger(10000)
+// log.SetLogger("console", "")
+//
+// > the first params stand for how many channel
+//
+// Use it like this:
+//
+// log.Trace("trace")
+// log.Info("info")
+// log.Warn("warning")
+// log.Debug("debug")
+// log.Critical("critical")
+//
+// more docs http://beego.me/docs/module/logs.md
package logs
import (
@@ -13,14 +39,25 @@ import (
"sync"
)
+// RFC5424 log message levels.
const (
- // log message levels
- LevelTrace = iota
- LevelDebug
- LevelInfo
- LevelWarn
- LevelError
+ LevelEmergency = iota
+ LevelAlert
LevelCritical
+ LevelError
+ LevelWarning
+ LevelNotice
+ LevelInformational
+ LevelDebug
+)
+
+// Legacy loglevel constants to ensure backwards compatibility.
+//
+// Deprecated: will be removed in 1.5.0.
+const (
+ LevelInfo = LevelInformational
+ LevelTrace = LevelDebug
+ LevelWarn = LevelWarning
)
type loggerType func() LoggerInterface
@@ -69,6 +106,7 @@ type logMsg struct {
// if the buffering chan is full, logger adapters write to file or other way.
func NewLogger(channellen int64) *BeeLogger {
bl := new(BeeLogger)
+ bl.level = LevelDebug
bl.loggerFuncCallDepth = 2
bl.msg = make(chan *logMsg, channellen)
bl.outputs = make(map[string]LoggerInterface)
@@ -110,7 +148,7 @@ func (bl *BeeLogger) DelLogger(adaptername string) error {
}
func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
- if bl.level > loglevel {
+ if loglevel > bl.level {
return nil
}
lm := new(logMsg)
@@ -130,8 +168,10 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
return nil
}
-// set log message level.
-// if message level (such as LevelTrace) is less than logger level (such as LevelWarn), ignore message.
+// Set log message level.
+//
+// If message level (such as LevelDebug) is higher than logger level (such as LevelWarning),
+// log providers will not even be sent the message.
func (bl *BeeLogger) SetLevel(l int) {
bl.level = l
}
@@ -147,7 +187,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
}
// start logger chan reading.
-// when chan is full, write logs.
+// when chan is not empty, write logs.
func (bl *BeeLogger) startLogger() {
for {
select {
@@ -159,40 +199,73 @@ func (bl *BeeLogger) startLogger() {
}
}
-// log trace level message.
-func (bl *BeeLogger) Trace(format string, v ...interface{}) {
- msg := fmt.Sprintf("[T] "+format, v...)
- bl.writerMsg(LevelTrace, msg)
-}
-
-// log debug level message.
-func (bl *BeeLogger) Debug(format string, v ...interface{}) {
+// Log EMERGENCY level message.
+func (bl *BeeLogger) Emergency(format string, v ...interface{}) {
msg := fmt.Sprintf("[D] "+format, v...)
- bl.writerMsg(LevelDebug, msg)
+ bl.writerMsg(LevelEmergency, msg)
}
-// log info level message.
-func (bl *BeeLogger) Info(format string, v ...interface{}) {
- msg := fmt.Sprintf("[I] "+format, v...)
- bl.writerMsg(LevelInfo, msg)
+// Log ALERT level message.
+func (bl *BeeLogger) Alert(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[D] "+format, v...)
+ bl.writerMsg(LevelAlert, msg)
}
-// log warn level message.
-func (bl *BeeLogger) Warn(format string, v ...interface{}) {
- msg := fmt.Sprintf("[W] "+format, v...)
- bl.writerMsg(LevelWarn, msg)
+// Log CRITICAL level message.
+func (bl *BeeLogger) Critical(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[C] "+format, v...)
+ bl.writerMsg(LevelCritical, msg)
}
-// log error level message.
+// Log ERROR level message.
func (bl *BeeLogger) Error(format string, v ...interface{}) {
msg := fmt.Sprintf("[E] "+format, v...)
bl.writerMsg(LevelError, msg)
}
-// log critical level message.
-func (bl *BeeLogger) Critical(format string, v ...interface{}) {
- msg := fmt.Sprintf("[C] "+format, v...)
- bl.writerMsg(LevelCritical, msg)
+// Log WARNING level message.
+func (bl *BeeLogger) Warning(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[W] "+format, v...)
+ bl.writerMsg(LevelWarning, msg)
+}
+
+// Log NOTICE level message.
+func (bl *BeeLogger) Notice(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[W] "+format, v...)
+ bl.writerMsg(LevelNotice, msg)
+}
+
+// Log INFORMATIONAL level message.
+func (bl *BeeLogger) Informational(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[I] "+format, v...)
+ bl.writerMsg(LevelInformational, msg)
+}
+
+// Log DEBUG level message.
+func (bl *BeeLogger) Debug(format string, v ...interface{}) {
+ msg := fmt.Sprintf("[D] "+format, v...)
+ bl.writerMsg(LevelDebug, msg)
+}
+
+// Log WARN level message.
+//
+// Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0.
+func (bl *BeeLogger) Warn(format string, v ...interface{}) {
+ bl.Warning(format, v...)
+}
+
+// Log INFO level message.
+//
+// Deprecated: compatibility alias for Informational(), Will be removed in 1.5.0.
+func (bl *BeeLogger) Info(format string, v ...interface{}) {
+ bl.Informational(format, v...)
+}
+
+// Log TRACE level message.
+//
+// Deprecated: compatibility alias for Debug(), Will be removed in 1.5.0.
+func (bl *BeeLogger) Trace(format string, v ...interface{}) {
+ bl.Debug(format, v...)
}
// flush all chan data.
diff --git a/logs/smtp.go b/logs/smtp.go
index 2b9e50a0..3373d7f4 100644
--- a/logs/smtp.go
+++ b/logs/smtp.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
@@ -51,22 +59,30 @@ func (s *SmtpWriter) Init(jsonconfig string) error {
return nil
}
+func (s *SmtpWriter) GetSmtpAuth(host string) smtp.Auth {
+ if len(strings.Trim(s.Username, " ")) == 0 && len(strings.Trim(s.Password, " ")) == 0 {
+ return nil
+ }
+ return smtp.PlainAuth(
+ "",
+ s.Username,
+ s.Password,
+ host,
+ )
+}
+
// write message in smtp writer.
// it will send an email with subject and only this message.
func (s *SmtpWriter) WriteMsg(msg string, level int) error {
- if level < s.Level {
+ if level > s.Level {
return nil
}
hp := strings.Split(s.Host, ":")
// Set up authentication information.
- auth := smtp.PlainAuth(
- "",
- s.Username,
- s.Password,
- hp[0],
- )
+ auth := s.GetSmtpAuth(hp[0])
+
// Connect to the server, authenticate, set the sender and recipient,
// and send the email all in one step.
content_type := "Content-Type: text/plain" + "; charset=UTF-8"
diff --git a/logs/smtp_test.go b/logs/smtp_test.go
index cb8d3009..28e762d2 100644
--- a/logs/smtp_test.go
+++ b/logs/smtp_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package logs
diff --git a/memzipfile.go b/memzipfile.go
index 92d6003a..cc5e3851 100644
--- a/memzipfile.go
+++ b/memzipfile.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/middleware/error.go b/middleware/error.go
index 3aff9a80..3b7191e9 100644
--- a/middleware/error.go
+++ b/middleware/error.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package middleware
@@ -311,6 +319,7 @@ func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg strin
if err != nil {
isint = 500
}
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(isint)
h(w, r)
return
diff --git a/middleware/exceptions.go b/middleware/exceptions.go
index 09cb46cb..a08a7358 100644
--- a/middleware/exceptions.go
+++ b/middleware/exceptions.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package middleware
diff --git a/middleware/i18n.go b/middleware/i18n.go
index 10ec12bb..e4dab693 100644
--- a/middleware/i18n.go
+++ b/middleware/i18n.go
@@ -1,90 +1,71 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Usage:
+//
+// import "github.com/astaxie/beego/middleware"
+//
+// I18N = middleware.NewLocale("conf/i18n.conf", beego.AppConfig.String("language"))
+//
+// more docs: http://beego.me/docs/module/i18n.md
package middleware
-//import (
-// "github.com/astaxie/beego/config"
-// "os"
-// "path"
-//)
+import (
+ "encoding/json"
+ "io/ioutil"
+ "os"
+)
-//type Translation struct {
-// filetype string
-// CurrentLocal string
-// Locales map[string]map[string]string
-//}
+type Translation struct {
+ filepath string
+ CurrentLocal string
+ Locales map[string]map[string]string
+}
-//func NewLocale(filetype string) *Translation {
-// return &Translation{
-// filetype: filetype,
-// CurrentLocal: "zh",
-// Locales: make(map[string]map[string]string),
-// }
-//}
+func NewLocale(filepath string, defaultlocal string) *Translation {
+ i18n := make(map[string]map[string]string)
+ file, err := os.Open(filepath)
+ if err != nil {
+ panic("open " + filepath + " err :" + err.Error())
+ }
+ data, err := ioutil.ReadAll(file)
+ if err != nil {
+ panic("read " + filepath + " err :" + err.Error())
+ }
+ err = json.Unmarshal(data, &i18n)
+ if err != nil {
+ panic("json.Unmarshal " + filepath + " err :" + err.Error())
+ }
+ return &Translation{
+ filepath: filepath,
+ CurrentLocal: defaultlocal,
+ Locales: i18n,
+ }
+}
-//func (t *Translation) loadTranslations(dirPath string) error {
-// dir, err := os.Open(dirPath)
-// if err != nil {
-// return err
-// }
-// defer dir.Close()
+func (t *Translation) SetLocale(local string) {
+ t.CurrentLocal = local
+}
-// names, err := dir.Readdirnames(-1)
-// if err != nil {
-// return err
-// }
-
-// for _, name := range names {
-// fullPath := path.Join(dirPath, name)
-
-// fi, err := os.Stat(fullPath)
-// if err != nil {
-// return err
-// }
-
-// if fi.IsDir() {
-// continue
-// } else {
-// if err := t.loadTranslation(fullPath, name); err != nil {
-// return err
-// }
-// }
-// }
-
-// return nil
-//}
-
-//func (t *Translation) loadTranslation(fullPath, locale string) error {
-
-// sourceKey2Trans, ok := t.Locales[locale]
-// if !ok {
-// sourceKey2Trans = make(map[string]string)
-
-// t.Locales[locale] = sourceKey2Trans
-// }
-
-// for _, m := range trf.Messages {
-// if m.Translation != "" {
-// sourceKey2Trans[sourceKey(m.Source, m.Context)] = m.Translation
-// }
-// }
-
-// return nil
-//}
-
-//func (t *Translation) SetLocale(local string) {
-// t.CurrentLocal = local
-//}
-
-//func (t *Translation) Translate(key string) string {
-// if ct, ok := t.Locales[t.CurrentLocal]; ok {
-// if v, o := ct[key]; o {
-// return v
-// }
-// }
-// return key
-//}
+func (t *Translation) Translate(key string, local string) string {
+ if local == "" {
+ local = t.CurrentLocal
+ }
+ if ct, ok := t.Locales[key]; ok {
+ if v, o := ct[local]; o {
+ return v
+ }
+ }
+ return key
+}
diff --git a/migration/migration.go b/migration/migration.go
new file mode 100644
index 00000000..d64d60d3
--- /dev/null
+++ b/migration/migration.go
@@ -0,0 +1,280 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// migration package for migration
+//
+// The table structure is as follow:
+//
+// CREATE TABLE `migrations` (
+// `id_migration` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key',
+// `name` varchar(255) DEFAULT NULL COMMENT 'migration name, unique',
+// `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'date migrated or rolled back',
+// `statements` longtext COMMENT 'SQL statements for this migration',
+// `rollback_statements` longtext,
+// `status` enum('update','rollback') DEFAULT NULL COMMENT 'update indicates it is a normal migration while rollback means this migration is rolled back',
+// PRIMARY KEY (`id_migration`)
+// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+package migration
+
+import (
+ "errors"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/orm"
+)
+
+// const the data format for the bee generate migration datatype
+const (
+ M_DATE_FORMAT = "20060102_150405"
+ M_DB_DATE_FORMAT = "2006-01-02 15:04:05"
+)
+
+// Migrationer is an interface for all Migration struct
+type Migrationer interface {
+ Up()
+ Down()
+ Reset()
+ Exec(name, status string) error
+ GetCreated() int64
+}
+
+var (
+ migrationMap map[string]Migrationer
+)
+
+func init() {
+ migrationMap = make(map[string]Migrationer)
+}
+
+// the basic type which will implement the basic type
+type Migration struct {
+ sqls []string
+ Created string
+}
+
+// implement in the Inheritance struct for upgrade
+func (m *Migration) Up() {
+
+}
+
+// implement in the Inheritance struct for down
+func (m *Migration) Down() {
+
+}
+
+// add sql want to execute
+func (m *Migration) Sql(sql string) {
+ m.sqls = append(m.sqls, sql)
+}
+
+// Reset the sqls
+func (m *Migration) Reset() {
+ m.sqls = make([]string, 0)
+}
+
+// execute the sql already add in the sql
+func (m *Migration) Exec(name, status string) error {
+ o := orm.NewOrm()
+ for _, s := range m.sqls {
+ beego.Info("exec sql:", s)
+ r := o.Raw(s)
+ _, err := r.Exec()
+ if err != nil {
+ return err
+ }
+ }
+ return m.addOrUpdateRecord(name, status)
+}
+
+func (m *Migration) addOrUpdateRecord(name, status string) error {
+ o := orm.NewOrm()
+ if status == "down" {
+ status = "rollback"
+ p, err := o.Raw("update migrations set `status` = ?, `rollback_statements` = ?, `created_at` = ? where name = ?").Prepare()
+ if err != nil {
+ return nil
+ }
+ _, err = p.Exec(status, strings.Join(m.sqls, "; "), time.Now().Format(M_DB_DATE_FORMAT), name)
+ return err
+ } else {
+ status = "update"
+ p, err := o.Raw("insert into migrations(`name`, `created_at`, `statements`, `status`) values(?,?,?,?)").Prepare()
+ if err != nil {
+ return err
+ }
+ _, err = p.Exec(name, time.Now().Format(M_DB_DATE_FORMAT), strings.Join(m.sqls, "; "), status)
+ return err
+ }
+}
+
+// get the unixtime from the Created
+func (m *Migration) GetCreated() int64 {
+ t, err := time.Parse(M_DATE_FORMAT, m.Created)
+ if err != nil {
+ return 0
+ }
+ return t.Unix()
+}
+
+// register the Migration in the map
+func Register(name string, m Migrationer) error {
+ if _, ok := migrationMap[name]; ok {
+ return errors.New("already exist name:" + name)
+ }
+ migrationMap[name] = m
+ return nil
+}
+
+// upgrate the migration from lasttime
+func Upgrade(lasttime int64) error {
+ sm := sortMap(migrationMap)
+ i := 0
+ for _, v := range sm {
+ if v.created > lasttime {
+ beego.Info("start upgrade", v.name)
+ v.m.Reset()
+ v.m.Up()
+ err := v.m.Exec(v.name, "up")
+ if err != nil {
+ beego.Error("execute error:", err)
+ time.Sleep(2 * time.Second)
+ return err
+ }
+ beego.Info("end upgrade:", v.name)
+ i++
+ }
+ }
+ beego.Info("total success upgrade:", i, " migration")
+ time.Sleep(2 * time.Second)
+ return nil
+}
+
+//rollback the migration by the name
+func Rollback(name string) error {
+ if v, ok := migrationMap[name]; ok {
+ beego.Info("start rollback")
+ v.Reset()
+ v.Down()
+ err := v.Exec(name, "down")
+ if err != nil {
+ beego.Error("execute error:", err)
+ time.Sleep(2 * time.Second)
+ return err
+ }
+ beego.Info("end rollback")
+ time.Sleep(2 * time.Second)
+ return nil
+ } else {
+ beego.Error("not exist the migrationMap name:" + name)
+ time.Sleep(2 * time.Second)
+ return errors.New("not exist the migrationMap name:" + name)
+ }
+}
+
+// reset all migration
+// run all migration's down function
+func Reset() error {
+ sm := sortMap(migrationMap)
+ i := 0
+ for j := len(sm) - 1; j >= 0; j-- {
+ v := sm[j]
+ if isRollBack(v.name) {
+ beego.Info("skip the", v.name)
+ time.Sleep(1 * time.Second)
+ continue
+ }
+ beego.Info("start reset:", v.name)
+ v.m.Reset()
+ v.m.Down()
+ err := v.m.Exec(v.name, "down")
+ if err != nil {
+ beego.Error("execute error:", err)
+ time.Sleep(2 * time.Second)
+ return err
+ }
+ i++
+ beego.Info("end reset:", v.name)
+ }
+ beego.Info("total success reset:", i, " migration")
+ time.Sleep(2 * time.Second)
+ return nil
+}
+
+// first Reset, then Upgrade
+func Refresh() error {
+ err := Reset()
+ if err != nil {
+ beego.Error("execute error:", err)
+ time.Sleep(2 * time.Second)
+ return err
+ }
+ err = Upgrade(0)
+ return err
+}
+
+type dataSlice []data
+
+type data struct {
+ created int64
+ name string
+ m Migrationer
+}
+
+// Len is part of sort.Interface.
+func (d dataSlice) Len() int {
+ return len(d)
+}
+
+// Swap is part of sort.Interface.
+func (d dataSlice) Swap(i, j int) {
+ d[i], d[j] = d[j], d[i]
+}
+
+// Less is part of sort.Interface. We use count as the value to sort by
+func (d dataSlice) Less(i, j int) bool {
+ return d[i].created < d[j].created
+}
+
+func sortMap(m map[string]Migrationer) dataSlice {
+ s := make(dataSlice, 0, len(m))
+ for k, v := range m {
+ d := data{}
+ d.created = v.GetCreated()
+ d.name = k
+ d.m = v
+ s = append(s, d)
+ }
+ sort.Sort(s)
+ return s
+}
+
+func isRollBack(name string) bool {
+ o := orm.NewOrm()
+ var maps []orm.Params
+ num, err := o.Raw("select * from migrations where `name` = ? order by id_migration desc", name).Values(&maps)
+ if err != nil {
+ beego.Info("get name has error", err)
+ return false
+ }
+ if num <= 0 {
+ return false
+ }
+ if maps[0]["status"] == "rollback" {
+ return true
+ }
+ return false
+}
diff --git a/mime.go b/mime.go
index f611a16e..155e5e12 100644
--- a/mime.go
+++ b/mime.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/namespace.go b/namespace.go
index 512afd69..d0109291 100644
--- a/namespace.go
+++ b/namespace.go
@@ -1,8 +1,17 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package beego
import (
diff --git a/namespace_test.go b/namespace_test.go
index 9142d62c..a92ae3ef 100644
--- a/namespace_test.go
+++ b/namespace_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/orm/README.md b/orm/README.md
index d4721307..74f1b47b 100644
--- a/orm/README.md
+++ b/orm/README.md
@@ -154,10 +154,5 @@ note: not recommend use this in product env.
more details and examples in docs and test
-* [中文](http://beego.me/docs/Models_Overview?lang=zh)
-* [English](http://beego.me/docs/Models_Overview?lang=en)
+[documents](http://beego.me/docs/mvc/model/overview.md)
-## TODO
-- some unrealized api
-- examples
-- docs
diff --git a/orm/cmd.go b/orm/cmd.go
index ecfc3bd5..2358ef3c 100644
--- a/orm/cmd.go
+++ b/orm/cmd.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/cmd_utils.go b/orm/cmd_utils.go
index 63cc5a64..8304da6b 100644
--- a/orm/cmd_utils.go
+++ b/orm/cmd_utils.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
@@ -144,6 +152,10 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
column += " " + "NOT NULL"
}
+ //if fi.initial.String() != "" {
+ // column += " DEFAULT " + fi.initial.String()
+ //}
+
if fi.unique {
column += " " + "UNIQUE"
}
diff --git a/orm/db.go b/orm/db.go
index d8301b75..2addff22 100644
--- a/orm/db.go
+++ b/orm/db.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_alias.go b/orm/db_alias.go
index f9d0ab5a..0a862241 100644
--- a/orm/db_alias.go
+++ b/orm/db_alias.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
@@ -136,7 +144,7 @@ func detectTZ(al *alias) {
if engine != "" {
al.Engine = engine
} else {
- engine = "INNODB"
+ al.Engine = "INNODB"
}
case DR_Sqlite:
diff --git a/orm/db_mysql.go b/orm/db_mysql.go
index 33a01ba4..3c2ad3a4 100644
--- a/orm/db_mysql.go
+++ b/orm/db_mysql.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_oracle.go b/orm/db_oracle.go
index d2253758..1e385c9a 100644
--- a/orm/db_oracle.go
+++ b/orm/db_oracle.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_postgres.go b/orm/db_postgres.go
index 463150dc..296ee6a0 100644
--- a/orm/db_postgres.go
+++ b/orm/db_postgres.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_sqlite.go b/orm/db_sqlite.go
index 94c74a69..0a2f32c8 100644
--- a/orm/db_sqlite.go
+++ b/orm/db_sqlite.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_tables.go b/orm/db_tables.go
index 690b4eaa..a9aa10ab 100644
--- a/orm/db_tables.go
+++ b/orm/db_tables.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/db_utils.go b/orm/db_utils.go
index 8f963f5e..4a3ba464 100644
--- a/orm/db_utils.go
+++ b/orm/db_utils.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/docs/zh/Cmd.md b/orm/docs/zh/Cmd.md
deleted file mode 100644
index 932cb1c6..00000000
--- a/orm/docs/zh/Cmd.md
+++ /dev/null
@@ -1,43 +0,0 @@
-## 命令模式
-
-注册模型与数据库以后,调用 RunCommand 执行 orm 命令
-
-```go
-func main() {
- // orm.RegisterModel...
- // orm.RegisterDataBase...
- ...
- orm.RunCommand()
-}
-```
-
-```bash
-go build main.go
-./main orm
-# 直接执行可以显示帮助
-# 如果你的程序可以支持的话,直接运行 go run main.go orm 也是一样的效果
-```
-
-## 自动建表
-
-```bash
-./main orm syncdb -h
-Usage of orm command: syncdb:
- -db="default": DataBase alias name
- -force=false: drop tables before create
- -v=false: verbose info
-```
-
-使用 `-force=1` 可以 drop table 后再建表
-
-使用 `-v` 可以查看执行的 sql 语句
-
-## 打印建表SQL
-
-```bash
-./main orm sqlall -h
-Usage of orm command: syncdb:
- -db="default": DataBase alias name
-```
-
-默认使用别名为 default 的数据库
diff --git a/orm/docs/zh/CustomFields.md b/orm/docs/zh/CustomFields.md
deleted file mode 100644
index 3a3c835c..00000000
--- a/orm/docs/zh/CustomFields.md
+++ /dev/null
@@ -1,38 +0,0 @@
-## Custom Fields
-
- TypeBooleanField = 1 << iota
-
- // string
- TypeCharField
-
- // string
- TypeTextField
-
- // time.Time
- TypeDateField
- // time.Time
- TypeDateTimeField
-
- // int16
- TypeSmallIntegerField
- // int32
- TypeIntegerField
- // int64
- TypeBigIntegerField
- // uint16
- TypePositiveSmallIntegerField
- // uint32
- TypePositiveIntegerField
- // uint64
- TypePositiveBigIntegerField
-
- // float64
- TypeFloatField
- // float64
- TypeDecimalField
-
- RelForeignKey
- RelOneToOne
- RelManyToMany
- RelReverseOne
- RelReverseMany
\ No newline at end of file
diff --git a/orm/docs/zh/Models.md b/orm/docs/zh/Models.md
deleted file mode 100644
index c8263822..00000000
--- a/orm/docs/zh/Models.md
+++ /dev/null
@@ -1,288 +0,0 @@
-## 模型定义
-
-复杂的模型定义不是必须的,此功能用作数据库数据转换和[自动建表](Cmd.md#自动建表)
-
-默认的表名使用驼峰转蛇形,比如 AuthUser -> auth_user
-
-**自定义表名**
-
-```go
-type User struct {
- Id int
- Name string
-}
-
-func (u *User) TableName() string {
- return "auth_user"
-}
-```
-
-如果[前缀设置](Orm.md#registermodelwithprefix)为`prefix_`那么表名为:prefix_auth_user
-
-## Struct Tag 设置参数
-```go
-orm:"null;rel(fk)"
-```
-
-多个设置间使用 `;` 分隔,设置的值如果是多个,使用 `,` 分隔。
-
-#### 忽略字段
-
-设置 `-` 即可忽略 struct 中的字段
-
-```go
-type User struct {
-...
- AnyField string `orm:"-"`
-...
-```
-
-#### auto
-
-当 Field 类型为 int, int32, int64 时,可以设置字段为自增健
-
-当模型定义里没有主键时,符合上述类型且名称为 `Id` 的 Field 将被视为自增健。
-
-#### pk
-
-设置为主键,适用于自定义其他类型为主键
-
-#### null
-
-数据库表默认为 `NOT NULL`,设置 null 代表 `ALLOW NULL`
-
-#### blank
-
-设置 string 类型的字段允许为空,否则 clean 会返回错误
-
-#### index
-
-为字段增加索引
-
-#### unique
-
-为字段增加 unique 键
-
-#### column
-
-为字段设置 db 字段的名称
-```go
-Name `orm:"column(user_name)"`
-```
-#### default
-
-为字段设置默认值,类型必须符合
-```go
-type User struct {
- ...
- Status int `orm:"default(1)"`
-```
-#### size
-
-string 类型字段默认为 varchar(255)
-
-设置 size 以后,db type 将使用 varchar(size)
-
-```go
-Title string `orm:"size(60)"`
-```
-#### digits / decimals
-
-设置 float32, float64 类型的浮点精度
-```go
-Money float64 `orm:"digits(12);decimals(4)"`
-```
-总长度 12 小数点后 4 位 eg: `99999999.9999`
-
-#### auto_now / auto_now_add
-```go
-Created time.Time `auto_now_add`
-Updated time.Time `auto_now`
-```
-* auto_now 每次 model 保存时都会对时间自动更新
-* auto_now_add 第一次保存时才设置时间
-
-对于批量的 update 此设置是不生效的
-
-#### type
-
-设置为 date 时,time.Time 字段的对应 db 类型使用 date
-
-```go
-Created time.Time `orm:"auto_now_add;type(date)"`
-```
-
-设置为 text 时,string 字段对应的 db 类型使用 text
-
-```go
-Content string `orm:"type(text)"`
-```
-
-## 表关系设置
-
-#### rel / reverse
-
-**RelOneToOne**:
-```go
-type User struct {
- ...
- Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
-```
-对应的反向关系 **RelReverseOne**:
-```go
-type Profile struct {
- ...
- User *User `orm:"reverse(one)" json:"-"`
-```
-**RelForeignKey**:
-```go
-type Post struct {
- ...
- User*User `orm:"rel(fk)"` // RelForeignKey relation
-```
-对应的反向关系 **RelReverseMany**:
-```go
-type User struct {
- ...
- Posts []*Post `orm:"reverse(many)" json:"-"` // fk 的反向关系
-```
-**RelManyToMany**:
-```go
-type Post struct {
- ...
- Tags []*Tag `orm:"rel(m2m)"` // ManyToMany relation
-```
-对应的反向关系 **RelReverseMany**:
-```go
-type Tag struct {
- ...
- Posts []*Post `orm:"reverse(many)" json:"-"`
-```
-#### rel_table / rel_through
-
-此设置针对 `orm:"rel(m2m)"` 的关系字段
-
- rel_table 设置自动生成的 m2m 关系表的名称
- rel_through 如果要在 m2m 关系中使用自定义的 m2m 关系表
- 通过这个设置其名称,格式为 pkg.path.ModelName
- eg: app.models.PostTagRel
- PostTagRel 表需要有到 Post 和 Tag 的关系
-
-当设置 rel_table 时会忽略 rel_through
-
-#### on_delete
-
-设置对应的 rel 关系删除时,如何处理关系字段。
-
- cascade 级联删除(默认值)
- set_null 设置为 NULL,需要设置 null = true
- set_default 设置为默认值,需要设置 default 值
- do_nothing 什么也不做,忽略
-
-```go
-type User struct {
- ...
- Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
-...
-type Profile struct {
- ...
- User *User `orm:"reverse(one)" json:"-"`
-
-// 删除 Profile 时将设置 User.Profile 的数据库字段为 NULL
-```
-
-
-## 模型字段与数据库类型的对应
-
-在此列出 orm 推荐的对应数据库类型,自动建表功能也会以此为标准。
-
-默认所有的字段都是 **NOT NULL**
-
-#### MySQL
-
-| go |mysql
-| :--- | :---
-| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTO_INCREMENT
-| bool | bool
-| string - 默认为 size 255 | varchar(size)
-| string - 设置 type(text) 时 | longtext
-| time.Time - 设置 type 为 date 时 | date
-| time.TIme | datetime
-| byte | tinyint unsigned
-| rune | integer
-| int | integer
-| int8 | tinyint
-| int16 | smallint
-| int32 | integer
-| int64 | bigint
-| uint | integer unsigned
-| uint8 | tinyint unsigned
-| uint16 | smallint unsigned
-| uint32 | integer unsigned
-| uint64 | bigint unsigned
-| float32 | double precision
-| float64 | double precision
-| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
-
-#### Sqlite3
-
-| go | sqlite3
-| :--- | :---
-| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTOINCREMENT
-| bool | bool
-| string - 默认为 size 255 | varchar(size)
-| string - 设置 type(text) 时 | text
-| time.Time - 设置 type 为 date 时 | date
-| time.TIme | datetime
-| byte | tinyint unsigned
-| rune | integer
-| int | integer
-| int8 | tinyint
-| int16 | smallint
-| int32 | integer
-| int64 | bigint
-| uint | integer unsigned
-| uint8 | tinyint unsigned
-| uint16 | smallint unsigned
-| uint32 | integer unsigned
-| uint64 | bigint unsigned
-| float32 | real
-| float64 | real
-| float64 - 设置 digits, decimals 时 | decimal
-
-#### PostgreSQL
-
-| go | postgres
-| :--- | :---
-| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | serial
-| bool | bool
-| string - 默认为 size 255 | varchar(size)
-| string - 设置 type(text) 时 | text
-| time.Time - 设置 type 为 date 时 | date
-| time.TIme | timestamp with time zone
-| byte | smallint CHECK("column" >= 0 AND "column" <= 255)
-| rune | integer
-| int | integer
-| int8 | smallint CHECK("column" >= -127 AND "column" <= 128)
-| int16 | smallint
-| int32 | integer
-| int64 | bigint
-| uint | bigint CHECK("column" >= 0)
-| uint8 | smallint CHECK("column" >= 0 AND "column" <= 255)
-| uint16 | integer CHECK("column" >= 0)
-| uint32 | bigint CHECK("column" >= 0)
-| uint64 | bigint CHECK("column" >= 0)
-| float32 | double precision
-| float64 | double precision
-| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
-
-
-## 关系型字段
-
-其字段类型取决于对应的主键。
-
-* RelForeignKey
-* RelOneToOne
-* RelManyToMany
-* RelReverseOne
-* RelReverseMany
\ No newline at end of file
diff --git a/orm/docs/zh/Models.sql b/orm/docs/zh/Models.sql
deleted file mode 100644
index 2d9d5ce0..00000000
--- a/orm/docs/zh/Models.sql
+++ /dev/null
@@ -1,83 +0,0 @@
-SET NAMES utf8;
-SET FOREIGN_KEY_CHECKS = 0;
-
--- ----------------------------
--- Table structure for `comment`
--- ----------------------------
-DROP TABLE IF EXISTS `comment`;
-CREATE TABLE `comment` (
- `id` int(11) NOT NULL,
- `post_id` bigint(200) NOT NULL,
- `content` longtext NOT NULL,
- `parent_id` int(11) DEFAULT NULL,
- `status` smallint(4) NOT NULL,
- `created` datetime NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Table structure for `post`
--- ----------------------------
-DROP TABLE IF EXISTS `post`;
-CREATE TABLE `post` (
- `id` int(11) NOT NULL,
- `user_id` int(11) NOT NULL,
- `title` varchar(60) NOT NULL,
- `content` longtext NOT NULL,
- `created` datetime NOT NULL,
- `updated` datetime NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Table structure for `post_tag_rel`
--- ----------------------------
-DROP TABLE IF EXISTS `post_tag_rel`;
-CREATE TABLE `post_tag_rel` (
- `id` int(11) NOT NULL,
- `post_id` int(11) NOT NULL,
- `tag_id` int(11) NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Table structure for `tag`
--- ----------------------------
-DROP TABLE IF EXISTS `tag`;
-CREATE TABLE `tag` (
- `id` int(11) NOT NULL,
- `name` varchar(30) NOT NULL,
- `status` smallint(4) NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Table structure for `user`
--- ----------------------------
-DROP TABLE IF EXISTS `user`;
-CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `user_name` varchar(30) NOT NULL,
- `email` varchar(100) NOT NULL,
- `password` varchar(30) NOT NULL,
- `status` smallint(4) NOT NULL,
- `is_staff` tinyint(1) NOT NULL,
- `is_active` tinyint(1) NOT NULL,
- `created` date NOT NULL,
- `updated` datetime NOT NULL,
- `profile_id` int(11) DEFAULT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Table structure for `profile`
--- ----------------------------
-DROP TABLE IF EXISTS `profile`;
-CREATE TABLE `profile` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `age` smallint(4) NOT NULL,
- `money` double NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
-SET FOREIGN_KEY_CHECKS = 1;
diff --git a/orm/docs/zh/Object.md b/orm/docs/zh/Object.md
deleted file mode 100644
index f1a2e0e1..00000000
--- a/orm/docs/zh/Object.md
+++ /dev/null
@@ -1,59 +0,0 @@
-## 对象的CRUD操作
-
-对 object 操作简单的三个方法 Read / Insert / Update / Delete
-```go
-o := orm.NewOrm()
-user := new(User)
-user.Name = "slene"
-
-fmt.Println(o.Insert(user))
-
-user.Name = "Your"
-fmt.Println(o.Update(user))
-fmt.Println(o.Read(user))
-fmt.Println(o.Delete(user))
-```
-### Read
-```go
-o := orm.NewOrm()
-user := User{Id: 1}
-
-err = o.Read(&user)
-
-if err == sql.ErrNoRows {
- fmt.Println("查询不到")
-} else if err == orm.ErrMissPK {
- fmt.Println("找不到主键")
-} else {
- fmt.Println(user.Id, user.Name)
-}
-```
-### Insert
-```go
-o := orm.NewOrm()
-var user User
-user.Name = "slene"
-user.IsActive = true
-
-fmt.Println(o.Insert(&user))
-fmt.Println(user.Id)
-```
-创建后会自动对 auto 的 field 赋值
-
-### Update
-```go
-o := orm.NewOrm()
-user := User{Id: 1}
-if o.Read(&user) == nil {
- user.Name = "MyName"
- o.Update(&user)
-}
-```
-### Delete
-```go
-o := orm.NewOrm()
-o.Delete(&User{Id: 1})
-```
-Delete 操作会对反向关系进行操作,此例中 Post 拥有一个到 User 的外键。删除 User 的时候。如果 on_delete 设置为默认的级联操作,将删除对应的 Post
-
-删除以后会清除 auto field 的值
diff --git a/orm/docs/zh/Orm.md b/orm/docs/zh/Orm.md
deleted file mode 100644
index 6d3b6b06..00000000
--- a/orm/docs/zh/Orm.md
+++ /dev/null
@@ -1,316 +0,0 @@
-## Orm 使用方法
-
-beego/orm 的使用例子
-
-后文例子如无特殊说明都以这个为基础。
-
-##### models.go:
-
-```go
-package main
-
-import (
- "github.com/astaxie/beego/orm"
-)
-
-type User struct {
- Id int
- Name string
- Profile *Profile `orm:"rel(one)"` // OneToOne relation
-}
-
-type Profile struct {
- Id int
- Age int16
- User *User `orm:"reverse(one)"` // 设置反向关系(可选)
-}
-
-func init() {
- // 需要在init中注册定义的model
- orm.RegisterModel(new(User), new(Profile))
-}
-```
-
-##### main.go
-
-```go
-package main
-
-import (
- "fmt"
- "github.com/astaxie/beego/orm"
- _ "github.com/go-sql-driver/mysql"
-)
-
-func init() {
- orm.RegisterDriver("mysql", orm.DR_MySQL)
-
- orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
-}
-
-func main() {
- o := orm.NewOrm()
- o.Using("default") // 默认使用 default,你可以指定为其他数据库
-
- profile := new(Profile)
- profile.Age = 30
-
- user := new(User)
- user.Profile = profile
- user.Name = "slene"
-
- fmt.Println(o.Insert(profile))
- fmt.Println(o.Insert(user))
-}
-```
-
-## 数据库的设置
-
-目前 orm 支持三种数据库,以下为测试过的 driver
-
-将你需要使用的 driver 加入 import 中
-
-```go
-import (
- _ "github.com/go-sql-driver/mysql"
- _ "github.com/lib/pq"
- _ "github.com/mattn/go-sqlite3"
-)
-```
-
-#### RegisterDriver
-
-三种默认数据库类型
-
-```go
-orm.DR_MySQL
-orm.DR_Sqlite
-orm.DR_Postgres
-```
-
-```go
-// 参数1 driverName
-// 参数2 数据库类型
-// 这个用来设置 driverName 对应的数据库类型
-// mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
-orm.RegisterDriver("mymysql", orm.DR_MySQL)
-```
-
-#### RegisterDataBase
-
-orm 必须注册一个别名为 `default` 的数据库,作为默认使用。
-
-```go
-// 参数1 数据库的别名,用来在orm中切换数据库使用
-// 参数2 driverName
-// 参数3 对应的链接字符串
-// 参数4 设置最大的空闲连接数,使用 golang 自己的连接池
-orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
-```
-
-#### 时区设置
-
-orm 默认使用 time.Local 本地时区
-
-* 作用于 orm 自动创建的时间
-* 从数据库中取回的时间转换成 orm 本地时间
-
-如果需要的话,你也可以进行更改
-
-```go
-// 设置为 UTC 时间
-orm.DefaultTimeLoc = time.UTC
-```
-
-orm 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取的时做相应转换,以匹配时间系统,从而保证时间不会出错。
-
-**注意:** 鉴于 Sqlite3 的设计,存取默认都为 UTC 时间
-
-## 注册模型
-
-如果使用 orm.QuerySeter 进行高级查询的话,这个是必须的。
-
-反之,如果只使用 Raw 查询和 map struct,是无需这一步的。您可以去查看 [Raw SQL 查询](Raw.md)
-
-#### RegisterModel
-
-将你定义的 Model 进行注册,最佳设计是有单独的 models.go 文件,在他的 init 函数中进行注册。
-
-
-迷你版 models.go
-```go
-package main
-
-import "github.com/astaxie/beego/orm"
-
-type User struct {
- Id int
- Name string
-}
-
-func init(){
- orm.RegisterModel(new(User))
-}
-```
-
-RegisterModel 也可以同时注册多个 model
-
-```go
-orm.RegisterModel(new(User), new(Profile), new(Post))
-```
-
-详细的 struct 定义请查看文档 [模型定义](Models.md)
-
-#### RegisterModelWithPrefix
-
-使用表名前缀
-
-```go
-orm.RegisterModelWithPrefix("prefix_", new(User))
-```
-
-创建后的表名为 prefix_user
-
-## ORM 接口使用
-
-使用 orm 必然接触的 Ormer 接口,我们来熟悉一下
-
-```go
-var o Ormer
-o = orm.NewOrm() // 创建一个 Ormer
-// NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。
-```
-
-* type Ormer interface {
- * [Read(Modeler) error](Object.md#read)
- * [Insert(Modeler) (int64, error)](Object.md#insert)
- * [Update(Modeler) (int64, error)](Object.md#update)
- * [Delete(Modeler) (int64, error)](Object.md#delete)
- * [M2mAdd(Modeler, string, ...interface{}) (int64, error)](Object.md#m2madd)
- * [M2mDel(Modeler, string, ...interface{}) (int64, error)](Object.md#m2mdel)
- * [LoadRel(Modeler, string) (int64, error)](Object.md#loadRel)
- * [QueryTable(interface{}) QuerySeter](#querytable)
- * [Using(string) error](#using)
- * [Begin() error](Transaction.md)
- * [Commit() error](Transaction.md)
- * [Rollback() error](Transaction.md)
- * [Raw(string, ...interface{}) RawSeter](#raw)
- * [Driver() Driver](#driver)
-* }
-
-
-#### QueryTable
-
-传入表名,或者 Modeler 对象,返回一个 [QuerySeter](Query.md#queryseter)
-
-```go
-o := orm.NewOrm()
-var qs QuerySeter
-qs = o.QueryTable("user")
-// 如果表没有定义过,会立刻 panic
-```
-
-#### Using
-
-切换为其他数据库
-
-```go
-orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
-orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
-
-o1 := orm.NewOrm()
-o1.Using("db1")
-
-o2 := orm.NewOrm()
-o2.Using("db2")
-
-// 切换为其他数据库以后
-// 这个 Ormer 对象的其下的 api 调用都将使用这个数据库
-
-```
-
-默认使用 `default` 数据库,无需调用 Using
-
-#### Raw
-
-使用 sql 语句直接进行操作
-
-Raw 函数,返回一个 [RawSeter](Raw.md) 用以对设置的 sql 语句和参数进行操作
-
-```go
-o := NewOrm()
-var r RawSeter
-r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
-```
-
-#### Driver
-
-返回当前 orm 使用的 db 信息
-
-```go
-type Driver interface {
- Name() string
- Type() DriverType
-}
-```
-
-```go
-orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
-orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
-
-o1 := orm.NewOrm()
-o1.Using("db1")
-dr := o1.Driver()
-fmt.Println(dr.Name() == "db1") // true
-fmt.Println(dr.Type() == orm.DR_MySQL) // true
-
-o2 := orm.NewOrm()
-o2.Using("db2")
-dr = o2.Driver()
-fmt.Println(dr.Name() == "db2") // true
-fmt.Println(dr.Type() == orm.DR_Sqlite) // true
-
-```
-
-## 调试模式打印查询语句
-
-简单的设置 Debug 为 true 打印查询的语句
-
-可能存在性能问题,不建议使用在产品模式
-
-```go
-func main() {
- orm.Debug = true
-...
-```
-
-默认使用 os.Stderr 输出日志信息
-
-改变输出到你自己的 io.Writer
-
-```go
-var w io.Writer
-...
-// 设置为你的 io.Writer
-...
-orm.DebugLog = orm.NewLog(w)
-```
-
-日志格式
-
-```go
-[ORM] - 时间 - [Queries/数据库名] - [执行操作/执行时间] - [SQL语句] - 使用标点 `,` 分隔的参数列表 - 打印遇到的错误
-```
-
-```go
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `user` (`name`) VALUES (?)] - `slene`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.5ms] - [UPDATE `user` SET `name` = ? WHERE `id` = ?] - `astaxie`, `14`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [db.QueryRow / 0.4ms] - [SELECT `id`, `name` FROM `user` WHERE `id` = ?] - `14`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `post` (`user_id`,`title`,`content`) VALUES (?, ?, ?)] - `14`, `beego orm`, `powerful amazing`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.4ms] - [SELECT T1.`name` `User__Name`, T0.`user_id` `User`, T1.`id` `User__Id` FROM `post` T0 INNER JOIN `user` T1 ON T1.`id` = T0.`user_id` WHERE T0.`id` = ? LIMIT 1000] - `68`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `user` WHERE `id` = ?] - `14`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.3ms] - [SELECT T0.`id` FROM `post` T0 WHERE T0.`user_id` IN (?) ] - `14`
-[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `post` WHERE `id` IN (?)] - `68`
-```
-
-日志内容包括 **所有的数据库操作**,事务,Prepare,等
diff --git a/orm/docs/zh/Query.md b/orm/docs/zh/Query.md
deleted file mode 100644
index cfc4073c..00000000
--- a/orm/docs/zh/Query.md
+++ /dev/null
@@ -1,411 +0,0 @@
-## 高级查询
-
-orm 以 **QuerySeter** 来组织查询,每个返回 **QuerySeter** 的方法都会获得一个新的 **QuerySeter** 对象。
-
-基本使用方法:
-```go
-o := orm.NewOrm()
-
-// 获取 QuerySeter 对象,user 为表名
-qs := o.QueryTable("user")
-
-// 也可以直接使用对象作为表名
-user := new(User)
-qs = o.QueryTable(user) // 返回 QuerySeter
-```
-## expr
-
-QuerySeter 中用于描述字段和 sql 操作符,使用简单的 expr 查询方法
-
-字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 `Profile__Age` 注意,字段的分隔符号使用双下划线 `__`,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 `Profile__Age__gt` 代表 Profile.Age > 18 的条件查询。
-
-注释后面将描述对应的 sql 语句,仅仅是描述 expr 的类似结果,并不代表实际生成的语句。
-```go
-qs.Filter("id", 1) // WHERE id = 1
-qs.Filter("profile__age", 18) // WHERE profile.age = 18
-qs.Filter("Profile__Age", 18) // 使用字段名和Field名都是允许的
-qs.Filter("profile__age", 18) // WHERE profile.age = 18
-qs.Filter("profile__age__gt", 18) // WHERE profile.age > 18
-qs.Filter("profile__age__gte", 18) // WHERE profile.age >= 18
-qs.Filter("profile__age__in", 18, 20) // WHERE profile.age IN (18, 20)
-
-qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
-// WHERE profile.age IN (18, 20) AND NOT profile_id < 1000
-```
-## Operators
-
-当前支持的操作符号:
-
-* [exact](#exact) / [iexact](#iexact) 等于
-* [contains](#contains) / [icontains](#icontains) 包含
-* [gt / gte](#gt / gte) 大于 / 大于等于
-* [lt / lte](#lt / lte) 小于 / 小于等于
-* [startswith](#startswith) / [istartswith](#istartswith) 以...起始
-* [endswith](#endswith) / [iendswith](#iendswith) 以...结束
-* [in](#in)
-* [isnull](#isnull)
-
-后面以 `i` 开头的表示:大小写不敏感
-
-#### exact
-
-Filter / Exclude / Condition expr 的默认值
-```go
-qs.Filter("name", "slene") // WHERE name = 'slene'
-qs.Filter("name__exact", "slene") // WHERE name = 'slene'
-// 使用 = 匹配,大小写是否敏感取决于数据表使用的 collation
-qs.Filter("profile", nil) // WHERE profile_id IS NULL
-```
-#### iexact
-```go
-qs.Filter("name__iexact", "slene")
-// WHERE name LIKE 'slene'
-// 大小写不敏感,匹配任意 'Slene' 'sLENE'
-```
-#### contains
-```go
-qs.Filter("name__contains", "slene")
-// WHERE name LIKE BINARY '%slene%'
-// 大小写敏感, 匹配包含 slene 的字符
-```
-#### icontains
-```go
-qs.Filter("name__icontains", "slene")
-// WHERE name LIKE '%slene%'
-// 大小写不敏感, 匹配任意 'im Slene', 'im sLENE'
-```
-#### in
-```go
-qs.Filter("profile__age__in", 17, 18, 19, 20)
-// WHERE profile.age IN (17, 18, 19, 20)
-```
-#### gt / gte
-```go
-qs.Filter("profile__age__gt", 17)
-// WHERE profile.age > 17
-
-qs.Filter("profile__age__gte", 18)
-// WHERE profile.age >= 18
-```
-#### lt / lte
-```go
-qs.Filter("profile__age__lt", 17)
-// WHERE profile.age < 17
-
-qs.Filter("profile__age__lte", 18)
-// WHERE profile.age <= 18
-```
-#### startswith
-```go
-qs.Filter("name__startswith", "slene")
-// WHERE name LIKE BINARY 'slene%'
-// 大小写敏感, 匹配以 'slene' 起始的字符串
-```
-#### istartswith
-```go
-qs.Filter("name__istartswith", "slene")
-// WHERE name LIKE 'slene%'
-// 大小写不敏感, 匹配任意以 'slene', 'Slene' 起始的字符串
-```
-#### endswith
-```go
-qs.Filter("name__endswith", "slene")
-// WHERE name LIKE BINARY '%slene'
-// 大小写敏感, 匹配以 'slene' 结束的字符串
-```
-#### iendswith
-```go
-qs.Filter("name__startswith", "slene")
-// WHERE name LIKE '%slene'
-// 大小写不敏感, 匹配任意以 'slene', 'Slene' 结束的字符串
-```
-#### isnull
-```go
-qs.Filter("profile__isnull", true)
-qs.Filter("profile_id__isnull", true)
-// WHERE profile_id IS NULL
-
-qs.Filter("profile__isnull", false)
-// WHERE profile_id IS NOT NULL
-```
-## 高级查询接口使用
-
-QuerySeter 是高级查询使用的接口,我们来熟悉下他的接口方法
-
-* type QuerySeter interface {
- * [Filter(string, ...interface{}) QuerySeter](#filter)
- * [Exclude(string, ...interface{}) QuerySeter](#exclude)
- * [SetCond(*Condition) QuerySeter](#setcond)
- * [Limit(int, ...int64) QuerySeter](#limit)
- * [Offset(int64) QuerySeter](#offset)
- * [OrderBy(...string) QuerySeter](#orderby)
- * [RelatedSel(...interface{}) QuerySeter](#relatedsel)
- * [Count() (int64, error)](#count)
- * [Update(Params) (int64, error)](#update)
- * [Delete() (int64, error)](#delete)
- * [PrepareInsert() (Inserter, error)](#prepareinsert)
- * [All(interface{}) (int64, error)](#all)
- * [One(Modeler) error](#one)
- * [Values(*[]Params, ...string) (int64, error)](#values)
- * [ValuesList(*[]ParamsList, ...string) (int64, error)](#valueslist)
- * [ValuesFlat(*ParamsList, string) (int64, error)](#valuesflat)
-* }
-
-* 每个返回 QuerySeter 的 api 调用时都会新建一个 QuerySeter,不影响之前创建的。
-
-* 高级查询使用 Filter 和 Exclude 来做常用的条件查询。囊括两种清晰的过滤规则:包含, 排除
-
-#### Filter
-
-用来过滤查询结果,起到 **包含条件** 的作用
-
-多个 Filter 之间使用 `AND` 连接
-```go
-qs.Filter("profile__isnull", true).Filter("name", "slene")
-// WHERE profile_id IS NULL AND name = 'slene'
-```
-
-#### Exclude
-
-用来过滤查询结果,起到 **排除条件** 的作用
-
-使用 `NOT` 排除条件
-
-多个 Exclude 之间使用 `AND` 连接
-```go
-qs.Exclude("profile__isnull", true).Filter("name", "slene")
-// WHERE NOT profile_id IS NULL AND name = 'slene'
-```
-
-#### SetCond
-
-自定义条件表达式
-
-```go
-cond := NewCondition()
-cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000)
-
-qs := orm.QueryTable("user")
-qs = qs.SetCond(cond1)
-// WHERE ... AND ... AND NOT ... OR ...
-
-cond2 := cond.AndCond(cond1).OrCond(cond.And("name", "slene"))
-qs = qs.SetCond(cond2).Count()
-// WHERE (... AND ... AND NOT ... OR ...) OR ( ... )
-```
-
-#### Limit
-
-限制最大返回数据行数,第二个参数可以设置 `Offset`
-```go
-var DefaultRowsLimit = 1000 // orm 默认的 limit 值为 1000
-
-// 默认情况下 select 查询的最大行数为 1000
-// LIMIT 1000
-
-qs.Limit(10)
-// LIMIT 10
-
-qs.Limit(10, 20)
-// LIMIT 10 OFFSET 20
-
-qs.Limit(-1)
-// no limit
-
-qs.Limit(-1, 100)
-// LIMIT 18446744073709551615 OFFSET 100
-// 18446744073709551615 是 1<<64 - 1 用来指定无 limit 限制 但有 offset 偏移的情况
-```
-
-#### Offset
-
-设置 偏移行数
-```go
-qs.Offset(20)
-// LIMIT 1000 OFFSET 20
-```
-
-#### OrderBy
-
-参数使用 **expr**
-
-在 expr 前使用减号 `-` 表示 `DESC` 的排列
-```go
-qs.OrderBy("id", "-profile__age")
-// ORDER BY id ASC, profile.age DESC
-
-qs.OrderBy("-profile__age", "profile")
-// ORDER BY profile.age DESC, profile_id ASC
-```
-
-#### RelatedSel
-
-关系查询,参数使用 **expr**
-```go
-var DefaultRelsDepth = 5 // 默认情况下直接调用 RelatedSel 将进行最大 5 层的关系查询
-
-qs := o.QueryTable("post")
-
-qs.RelateSel()
-// INNER JOIN user ... LEFT OUTER JOIN profile ...
-
-qs.RelateSel("user")
-// INNER JOIN user ...
-// 设置 expr 只对设置的字段进行关系查询
-
-// 对设置 null 属性的 Field 将使用 LEFT OUTER JOIN
-```
-
-#### Count
-依据当前的查询条件,返回结果行数
-```go
-cnt, err := o.QueryTable("user").Count() // SELECT COUNT(*) FROM USER
-fmt.Printf("Count Num: %s, %s", cnt, err)
-```
-
-#### Update
-依据当前查询条件,进行批量更新操作
-```go
-num, err := o.QueryTable("user").Filter("name", "slene").Update(orm.Params{
- "name": "astaxie",
-})
-fmt.Printf("Affected Num: %s, %s", num, err)
-// SET name = "astaixe" WHERE name = "slene"
-```
-
-#### Delete
-依据当前查询条件,进行批量删除操作
-```go
-num, err := o.QueryTable("user").Filter("name", "slene").Delete()
-fmt.Printf("Affected Num: %s, %s", num, err)
-// DELETE FROM user WHERE name = "slene"
-```
-
-#### PrepareInsert
-
-用于一次 prepare 多次 insert 插入,以提高批量插入的速度。
-
-```go
-var users []*User
-...
-qs := o.QueryTable("user")
-i, _ := qs.PrepareInsert()
-for _, user := range users {
- id, err := i.Insert(user)
- if err != nil {
- ...
- }
-}
-// PREPARE INSERT INTO user (`name`, ...) VALUES (?, ...)
-// EXECUTE INSERT INTO user (`name`, ...) VALUES ("slene", ...)
-// EXECUTE ...
-// ...
-i.Close() // 别忘记关闭 statement
-```
-
-#### All
-返回对应的结果集对象
-```go
-var users []*User
-num, err := o.QueryTable("user").Filter("name", "slene").All(&users)
-fmt.Printf("Returned Rows Num: %s, %s", num, err)
-```
-
-#### One
-
-尝试返回单条记录
-
-```go
-var user *User
-err := o.QueryTable("user").Filter("name", "slene").One(&user)
-if err == orm.ErrMultiRows {
- // 多条的时候报错
- fmt.Printf("Returned Multi Rows Not One")
-}
-if err == orm.ErrNoRows {
- // 没有找到记录
- fmt.Printf("Not row found")
-}
-```
-
-#### Values
-返回结果集的 key => value 值
-
-key 为 Model 里的 Field name,value 的值 以 string 保存
-
-```go
-var maps []orm.Params
-num, err := o.QueryTable("user").Values(&maps)
-if err != nil {
- fmt.Printf("Result Nums: %d\n", num)
- for _, m := range maps {
- fmt.Println(m["Id"], m["Name"])
- }
-}
-```
-
-返回指定的 Field 数据
-
-**TODO**: 暂不支持级联查询 **RelatedSel** 直接返回 Values
-
-但可以直接指定 expr 级联返回需要的数据
-
-```go
-var maps []orm.Params
-num, err := o.QueryTable("user").Values(&maps, "id", "name", "profile", "profile__age")
-if err != nil {
- fmt.Printf("Result Nums: %d\n", num)
- for _, m := range maps {
- fmt.Println(m["Id"], m["Name"], m["Profile"], m["Profile__Age"])
- // map 中的数据都是展开的,没有复杂的嵌套
- }
-}
-```
-
-#### ValuesList
-
-顾名思义,返回的结果集以slice存储
-
-结果的排列与 Model 中定义的 Field 顺序一致
-
-返回的每个元素值以 string 保存
-
-```go
-var lists []orm.ParamsList
-num, err := o.QueryTable("user").ValuesList(&lists)
-if err != nil {
- fmt.Printf("Result Nums: %d\n", num)
- for _, row := range lists {
- fmt.Println(row)
- }
-}
-```
-
-当然也可以指定 expr 返回指定的 Field
-
-```go
-var lists []orm.ParamsList
-num, err := o.QueryTable("user").ValuesList(&lists, "name", "profile__age")
-if err != nil {
- fmt.Printf("Result Nums: %d\n", num)
- for _, row := range lists {
- fmt.Printf("Name: %s, Age: %s\m", row[0], row[1])
- }
-}
-```
-
-#### ValuesFlat
-
-只返回特定的 Field 值,讲结果集展开到单个 slice 里
-
-```go
-var list orm.ParamsList
-num, err := o.QueryTable("user").ValuesFlat(&list, "name")
-if err != nil {
- fmt.Printf("Result Nums: %d\n", num)
- fmt.Printf("All User Names: %s", strings.Join(list, ", ")
-}
-```
-
-
-
diff --git a/orm/docs/zh/README.md b/orm/docs/zh/README.md
deleted file mode 100644
index e01c8cad..00000000
--- a/orm/docs/zh/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-最新文档请查看 beedoc
-
-* [中文](http://beego.me/docs/Models_Overview?lang=zh)
-* [English](http://beego.me/docs/Models_Overview?lang=en)
-
-## 文档目录
-
-1. [Orm 使用方法](Orm.md)
- - [数据库的设置](Orm.md#数据库的设置)
- * [驱动类型设置](Orm.md#registerdriver)
- * [参数设置](Orm.md#registerdatabase)
- * [时区设置](Orm.md#时区设置)
- - [注册模型](Orm.md#注册模型)
- - [ORM 接口使用](Orm.md#orm-接口使用)
- - [调试模式打印查询语句](Orm.md#调试模式打印查询语句)
-2. [对象的CRUD操作](Object.md)
-3. [高级查询](Query.md)
- - [使用的表达式语法](Query.md#expr)
- - [支持的操作符号](Query.md#operators)
- - [高级查询接口使用](Query.md#高级查询接口使用)
-4. [使用SQL语句进行查询](Raw.md)
-5. [事务处理](Transaction.md)
-6. [模型定义](Models.md)
- - [Struct Tag 设置参数](Models.md#struct-tag-设置参数)
- - [表关系设置](Models.md#表关系设置)
- - [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应)
-7. [命令模式](Cmd.md)
- - [自动建表](Cmd.md#自动建表)
- - [打印建表SQL](Cmd.md#打印建表sql)
-8. [Test ORM](Test.md)
-9. Custom Fields
-10. Faq
-
-
-### 文档更新记录
-
-* 2013-08-20: 这里不再更新,最新文档在 beedoc, [中文](http://beego.me/docs/Models_Overview?lang=zh) / [English](http://beego.me/docs/Models_Overview?lang=en)
-* 2013-08-19: 增加[自动建表](Cmd.md#自动建表)功能
-* 2013-08-13: ORM 的 [时区设置](Orm.md#时区设置)
-* 2013-08-13: [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型
diff --git a/orm/docs/zh/Raw.md b/orm/docs/zh/Raw.md
deleted file mode 100644
index 0d571edf..00000000
--- a/orm/docs/zh/Raw.md
+++ /dev/null
@@ -1,116 +0,0 @@
-## 使用SQL语句进行查询
-
-* 使用 Raw SQL 查询,无需使用 ORM 表定义
-* 多数据库,都可直接使用占位符号 `?`,自动转换
-* 查询时的参数,支持使用 Model Struct 和 Slice, Array
-
-```go
-ids := []int{1, 2, 3}
-p.Raw("SELECT name FROM user WHERE id IN (?, ?, ?)", ids)
-```
-
-创建一个 **RawSeter**
-
-```go
-o := NewOrm()
-var r RawSeter
-r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
-```
-
-* type RawSeter interface {
- * [Exec() (int64, error)](#exec)
- * [QueryRow(...interface{}) error](#queryrow)
- * [QueryRows(...interface{}) (int64, error)](#queryrows)
- * [SetArgs(...interface{}) RawSeter](#setargs)
- * [Values(*[]Params) (int64, error)](#values)
- * [ValuesList(*[]ParamsList) (int64, error)](#valueslist)
- * [ValuesFlat(*ParamsList) (int64, error)](#valuesflat)
- * [Prepare() (RawPreparer, error)](#prepare)
-* }
-
-#### Exec
-
-执行sql语句
-
-```go
-num, err := r.Exec()
-```
-
-#### QueryRow
-
-TODO
-
-#### QueryRows
-
-TODO
-
-#### SetArgs
-
-改变 Raw(sql, args...) 中的 args 参数,返回一个新的 RawSeter
-
-用于单条 sql 语句,重复利用,替换参数然后执行。
-
-```go
-num, err := r.SetArgs("arg1", "arg2").Exec()
-num, err := r.SetArgs("arg1", "arg2").Exec()
-...
-```
-#### Values / ValuesList / ValuesFlat
-
-Raw SQL 查询获得的结果集 Value 为 `string` 类型,NULL 字段的值为空 ``
-
-#### Values
-
-
-返回结果集的 key => value 值
-
-```go
-var maps []orm.Params
-num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps)
-if err == nil && num > 0 {
- fmt.Println(maps[0]["user_name"]) // slene
-}
-```
-
-#### ValuesList
-
-返回结果集 slice
-
-```go
-var lists []orm.ParamsList
-num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).ValuesList(&lists)
-if err == nil && num > 0 {
- fmt.Println(lists[0][0]) // slene
-}
-```
-
-#### ValuesFlat
-
-返回单一字段的平铺 slice 数据
-
-```go
-var list orm.ParamsList
-num, err = o.Raw("SELECT id FROM user WHERE id < ?", 10).ValuesList(&list)
-if err == nil && num > 0 {
- fmt.Println(list) // []{"1","2","3",...}
-}
-```
-
-#### Prepare
-
-用于一次 prepare 多次 exec,以提高批量执行的速度。
-
-```go
-p, err := o.Raw("UPDATE user SET name = ? WHERE name = ?").Prepare()
-num, err := p.Exec("testing", "slene")
-num, err = p.Exec("testing", "astaxie")
-...
-...
-p.Close() // 别忘记关闭 statement
-```
-
-## FAQ
-
-1. 我的 app 需要支持多类型数据库,如何在使用 Raw SQL 的时候判断当前使用的数据库类型。
-
-使用 Ormer 的 [Driver方法](Orm.md#driver) 可以进行判断
diff --git a/orm/docs/zh/Test.md b/orm/docs/zh/Test.md
deleted file mode 100644
index c2146336..00000000
--- a/orm/docs/zh/Test.md
+++ /dev/null
@@ -1,34 +0,0 @@
-## Test ORM
-
-测试代码参见
-
-```bash
-models_test.go // 表定义
-orm_test.go // 测试用例
-```
-
-#### MySQL
-```bash
-mysql -u root -e 'create database orm_test;'
-export ORM_DRIVER=mysql
-export ORM_SOURCE="root:@/orm_test?charset=utf8"
-go test -v github.com/astaxie/beego/orm
-```
-
-
-#### Sqlite3
-```bash
-touch /path/to/orm_test.db
-export ORM_DRIVER=sqlite3
-export ORM_SOURCE=/path/to/orm_test.db
-go test -v github.com/astaxie/beego/orm
-```
-
-
-#### PostgreSQL
-```bash
-psql -c 'create database orm_test;' -U postgres
-export ORM_DRIVER=postgres
-export ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
-go test -v github.com/astaxie/beego/orm
-```
\ No newline at end of file
diff --git a/orm/docs/zh/Transaction.md b/orm/docs/zh/Transaction.md
deleted file mode 100644
index 51172c09..00000000
--- a/orm/docs/zh/Transaction.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## 事务处理
-
-orm 可以简单的进行事务操作
-
-```go
-o := NewOrm()
-err := o.Begin()
-// 事务处理过程
-...
-...
-// 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内
-if SomeError {
- err = o.Rollback()
-} else {
- err = o.Commit()
-}
-```
diff --git a/orm/models.go b/orm/models.go
index ff71ee62..dcb32b55 100644
--- a/orm/models.go
+++ b/orm/models.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_boot.go b/orm/models_boot.go
index 0abaf98f..cb44bc05 100644
--- a/orm/models_boot.go
+++ b/orm/models_boot.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_fields.go b/orm/models_fields.go
index c1c9b7e2..f038dd0f 100644
--- a/orm/models_fields.go
+++ b/orm/models_fields.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_info_f.go b/orm/models_info_f.go
index 8ec2bbeb..a79ffab2 100644
--- a/orm/models_info_f.go
+++ b/orm/models_info_f.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_info_m.go b/orm/models_info_m.go
index 265c6379..3600ee7c 100644
--- a/orm/models_info_m.go
+++ b/orm/models_info_m.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_test.go b/orm/models_test.go
index 775c2856..fe78c45f 100644
--- a/orm/models_test.go
+++ b/orm/models_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/models_utils.go b/orm/models_utils.go
index c448c55e..ffde40ea 100644
--- a/orm/models_utils.go
+++ b/orm/models_utils.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
@@ -128,6 +136,9 @@ func getFieldType(val reflect.Value) (ft int, err error) {
case reflect.String:
ft = TypeCharField
default:
+ if elm.Interface() == nil {
+ panic(fmt.Errorf("%s is nil pointer, may be miss setting tag", val))
+ }
switch elm.Interface().(type) {
case sql.NullInt64:
ft = TypeBigIntegerField
diff --git a/orm/orm.go b/orm/orm.go
index 5503256e..cdb7f27c 100644
--- a/orm/orm.go
+++ b/orm/orm.go
@@ -1,9 +1,53 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Simple Usage
+//
+// package main
+//
+// import (
+// "fmt"
+// "github.com/astaxie/beego/orm"
+// _ "github.com/go-sql-driver/mysql" // import your used driver
+// )
+//
+// // Model Struct
+// type User struct {
+// Id int `orm:"auto"`
+// Name string `orm:"size(100)"`
+// }
+//
+// func init() {
+// orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30)
+// }
+//
+// func main() {
+// o := orm.NewOrm()
+// user := User{Name: "slene"}
+// // insert
+// id, err := o.Insert(&user)
+// // update
+// user.Name = "astaxie"
+// num, err := o.Update(&user)
+// // read one
+// u := User{Id: user.Id}
+// err = o.Read(&u)
+// // delete
+// num, err = o.Delete(&u)
+// }
+//
+// more docs: http://beego.me/docs/mvc/model/overview.md
package orm
import (
diff --git a/orm/orm_conds.go b/orm/orm_conds.go
index 4b0cfa65..6344653a 100644
--- a/orm/orm_conds.go
+++ b/orm/orm_conds.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_log.go b/orm/orm_log.go
index e132992d..419d8e11 100644
--- a/orm/orm_log.go
+++ b/orm/orm_log.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_object.go b/orm/orm_object.go
index 44d4aebc..df5a6600 100644
--- a/orm/orm_object.go
+++ b/orm/orm_object.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_querym2m.go b/orm/orm_querym2m.go
index 370de60d..1eaccf72 100644
--- a/orm/orm_querym2m.go
+++ b/orm/orm_querym2m.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_queryset.go b/orm/orm_queryset.go
index 6d2dd418..4f5d5485 100644
--- a/orm/orm_queryset.go
+++ b/orm/orm_queryset.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_raw.go b/orm/orm_raw.go
index ea701cce..1393d414 100644
--- a/orm/orm_raw.go
+++ b/orm/orm_raw.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/orm_test.go b/orm/orm_test.go
index 5859f426..e7420bcb 100644
--- a/orm/orm_test.go
+++ b/orm/orm_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/types.go b/orm/types.go
index 0f1b37ba..c342e1c2 100644
--- a/orm/types.go
+++ b/orm/types.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/orm/utils.go b/orm/utils.go
index e53042d9..df6147c1 100644
--- a/orm/utils.go
+++ b/orm/utils.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors slene
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package orm
diff --git a/parser.go b/parser.go
index 5b2cd616..65144f5d 100644
--- a/parser.go
+++ b/parser.go
@@ -1,8 +1,17 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package beego
import (
@@ -61,7 +70,9 @@ func parserPkg(pkgRealpath, pkgpath string) error {
for _, d := range fl.Decls {
switch specDecl := d.(type) {
case *ast.FuncDecl:
- parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath)
+ if specDecl.Recv != nil {
+ parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath)
+ }
}
}
}
@@ -110,7 +121,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
}
func genRouterCode() {
- os.Mkdir(path.Join(AppPath, "routers"), 0755)
+ os.Mkdir(path.Join(workPath, "routers"), 0755)
Info("generate router from comments")
var globalinfo string
for k, cList := range genInfoList {
@@ -144,7 +155,7 @@ func genRouterCode() {
}
}
if globalinfo != "" {
- f, err := os.Create(path.Join(AppPath, "routers", "commentsRouter.go"))
+ f, err := os.Create(path.Join(workPath, "routers", "commentsRouter.go"))
if err != nil {
panic(err)
}
@@ -154,18 +165,21 @@ func genRouterCode() {
}
func compareFile(pkgRealpath string) bool {
- if utils.FileExists(path.Join(AppPath, lastupdateFilename)) {
- content, err := ioutil.ReadFile(path.Join(AppPath, lastupdateFilename))
+ if !utils.FileExists(path.Join(workPath, "routers", "commentsRouter.go")) {
+ return true
+ }
+ if utils.FileExists(path.Join(workPath, lastupdateFilename)) {
+ content, err := ioutil.ReadFile(path.Join(workPath, lastupdateFilename))
if err != nil {
return true
}
json.Unmarshal(content, &pkgLastupdate)
- ft, err := os.Lstat(pkgRealpath)
+ lastupdate, err := getpathTime(pkgRealpath)
if err != nil {
return true
}
if v, ok := pkgLastupdate[pkgRealpath]; ok {
- if ft.ModTime().UnixNano() <= v {
+ if lastupdate <= v {
return false
}
}
@@ -174,14 +188,27 @@ func compareFile(pkgRealpath string) bool {
}
func savetoFile(pkgRealpath string) {
- ft, err := os.Lstat(pkgRealpath)
+ lastupdate, err := getpathTime(pkgRealpath)
if err != nil {
return
}
- pkgLastupdate[pkgRealpath] = ft.ModTime().UnixNano()
+ pkgLastupdate[pkgRealpath] = lastupdate
d, err := json.Marshal(pkgLastupdate)
if err != nil {
return
}
- ioutil.WriteFile(path.Join(AppPath, lastupdateFilename), d, os.ModePerm)
+ ioutil.WriteFile(path.Join(workPath, lastupdateFilename), d, os.ModePerm)
+}
+
+func getpathTime(pkgRealpath string) (lastupdate int64, err error) {
+ fl, err := ioutil.ReadDir(pkgRealpath)
+ if err != nil {
+ return lastupdate, err
+ }
+ for _, f := range fl {
+ if lastupdate < f.ModTime().UnixNano() {
+ lastupdate = f.ModTime().UnixNano()
+ }
+ }
+ return lastupdate, nil
}
diff --git a/plugins/auth/basic.go b/plugins/auth/basic.go
index a74bcf22..ed8bc4bd 100644
--- a/plugins/auth/basic.go
+++ b/plugins/auth/basic.go
@@ -1,21 +1,39 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// Package auth provides handlers to enable basic auth support.
+// Simple Usage:
+// import(
+// "github.com/astaxie/beego"
+// "github.com/astaxie/beego/plugins/auth"
+// )
+//
+// func main(){
+// // authenticate every request
+// beego.InsertFilter("*", beego.BeforeRouter,auth.Basic("username","secretpassword"))
+// beego.Run()
+// }
+//
+//
+// Advanced Usage:
+// func SecretAuth(username, password string) bool {
+// return username == "astaxie" && password == "helloBeego"
+// }
+// authPlugin := auth.NewBasicAuthenticator(SecretAuth, "Authorization Required")
+// beego.InsertFilter("*", beego.BeforeRouter,authPlugin)
package auth
-// Example:
-// func SecretAuth(username, password string) bool {
-// if username == "astaxie" && password == "helloBeego" {
-// return true
-// }
-// return false
-// }
-// authPlugin := auth.NewBasicAuthenticator(SecretAuth, "My Realm")
-// beego.AddFilter("*","AfterStatic",authPlugin)
-
import (
"encoding/base64"
"net/http"
@@ -25,6 +43,15 @@ import (
"github.com/astaxie/beego/context"
)
+var defaultRealm = "Authorization Required"
+
+func Basic(username string, password string) beego.FilterFunc {
+ secrets := func(user, pass string) bool {
+ return user == username && pass == password
+ }
+ return NewBasicAuthenticator(secrets, defaultRealm)
+}
+
func NewBasicAuthenticator(secrets SecretProvider, Realm string) beego.FilterFunc {
return func(ctx *context.Context) {
a := &BasicAuth{Secrets: secrets, Realm: Realm}
@@ -41,13 +68,10 @@ type BasicAuth struct {
Realm string
}
-/*
- Checks the username/password combination from the request. Returns
- either an empty string (authentication failed) or the name of the
- authenticated user.
-
- Supports MD5 and SHA1 password entries
-*/
+//Checks the username/password combination from the request. Returns
+//either an empty string (authentication failed) or the name of the
+//authenticated user.
+//Supports MD5 and SHA1 password entries
func (a *BasicAuth) CheckAuth(r *http.Request) string {
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(s) != 2 || s[0] != "Basic" {
@@ -69,10 +93,8 @@ func (a *BasicAuth) CheckAuth(r *http.Request) string {
return ""
}
-/*
- http.Handler for BasicAuth which initiates the authentication process
- (or requires reauthentication).
-*/
+//http.Handler for BasicAuth which initiates the authentication process
+//(or requires reauthentication).
func (a *BasicAuth) RequireAuth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="`+a.Realm+`"`)
w.WriteHeader(401)
diff --git a/plugins/cors/cors.go b/plugins/cors/cors.go
new file mode 100644
index 00000000..dce750eb
--- /dev/null
+++ b/plugins/cors/cors.go
@@ -0,0 +1,228 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package cors provides handlers to enable CORS support.
+// Usage
+// import (
+// "github.com/astaxie/beego"
+// "github.com/astaxie/beego/plugins/cors"
+// )
+//
+// func main() {
+// // CORS for https://foo.* origins, allowing:
+// // - PUT and PATCH methods
+// // - Origin header
+// // - Credentials share
+// beego.InsertFilter("*", beego.BeforeRouter,cors.Allow(&cors.Options{
+// AllowOrigins: []string{"https://*.foo.com"},
+// AllowMethods: []string{"PUT", "PATCH"},
+// AllowHeaders: []string{"Origin"},
+// ExposeHeaders: []string{"Content-Length"},
+// AllowCredentials: true,
+// }))
+// beego.Run()
+// }
+package cors
+
+import (
+ "net/http"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
+)
+
+const (
+ headerAllowOrigin = "Access-Control-Allow-Origin"
+ headerAllowCredentials = "Access-Control-Allow-Credentials"
+ headerAllowHeaders = "Access-Control-Allow-Headers"
+ headerAllowMethods = "Access-Control-Allow-Methods"
+ headerExposeHeaders = "Access-Control-Expose-Headers"
+ headerMaxAge = "Access-Control-Max-Age"
+
+ headerOrigin = "Origin"
+ headerRequestMethod = "Access-Control-Request-Method"
+ headerRequestHeaders = "Access-Control-Request-Headers"
+)
+
+var (
+ defaultAllowHeaders = []string{"Origin", "Accept", "Content-Type", "Authorization"}
+ // Regex patterns are generated from AllowOrigins. These are used and generated internally.
+ allowOriginPatterns = []string{}
+)
+
+// Options represents Access Control options.
+type Options struct {
+ // If set, all origins are allowed.
+ AllowAllOrigins bool
+ // A list of allowed origins. Wild cards and FQDNs are supported.
+ AllowOrigins []string
+ // If set, allows to share auth credentials such as cookies.
+ AllowCredentials bool
+ // A list of allowed HTTP methods.
+ AllowMethods []string
+ // A list of allowed HTTP headers.
+ AllowHeaders []string
+ // A list of exposed HTTP headers.
+ ExposeHeaders []string
+ // Max age of the CORS headers.
+ MaxAge time.Duration
+}
+
+// Header converts options into CORS headers.
+func (o *Options) Header(origin string) (headers map[string]string) {
+ headers = make(map[string]string)
+ // if origin is not allowed, don't extend the headers
+ // with CORS headers.
+ if !o.AllowAllOrigins && !o.IsOriginAllowed(origin) {
+ return
+ }
+
+ // add allow origin
+ if o.AllowAllOrigins {
+ headers[headerAllowOrigin] = "*"
+ } else {
+ headers[headerAllowOrigin] = origin
+ }
+
+ // add allow credentials
+ headers[headerAllowCredentials] = strconv.FormatBool(o.AllowCredentials)
+
+ // add allow methods
+ if len(o.AllowMethods) > 0 {
+ headers[headerAllowMethods] = strings.Join(o.AllowMethods, ",")
+ }
+
+ // add allow headers
+ if len(o.AllowHeaders) > 0 {
+ headers[headerAllowHeaders] = strings.Join(o.AllowHeaders, ",")
+ }
+
+ // add exposed header
+ if len(o.ExposeHeaders) > 0 {
+ headers[headerExposeHeaders] = strings.Join(o.ExposeHeaders, ",")
+ }
+ // add a max age header
+ if o.MaxAge > time.Duration(0) {
+ headers[headerMaxAge] = strconv.FormatInt(int64(o.MaxAge/time.Second), 10)
+ }
+ return
+}
+
+// PreflightHeader converts options into CORS headers for a preflight response.
+func (o *Options) PreflightHeader(origin, rMethod, rHeaders string) (headers map[string]string) {
+ headers = make(map[string]string)
+ if !o.AllowAllOrigins && !o.IsOriginAllowed(origin) {
+ return
+ }
+ // verify if requested method is allowed
+ for _, method := range o.AllowMethods {
+ if method == rMethod {
+ headers[headerAllowMethods] = strings.Join(o.AllowMethods, ",")
+ break
+ }
+ }
+
+ // verify if requested headers are allowed
+ var allowed []string
+ for _, rHeader := range strings.Split(rHeaders, ",") {
+ rHeader = strings.TrimSpace(rHeader)
+ lookupLoop:
+ for _, allowedHeader := range o.AllowHeaders {
+ if strings.ToLower(rHeader) == strings.ToLower(allowedHeader) {
+ allowed = append(allowed, rHeader)
+ break lookupLoop
+ }
+ }
+ }
+
+ headers[headerAllowCredentials] = strconv.FormatBool(o.AllowCredentials)
+ // add allow origin
+ if o.AllowAllOrigins {
+ headers[headerAllowOrigin] = "*"
+ } else {
+ headers[headerAllowOrigin] = origin
+ }
+
+ // add allowed headers
+ if len(allowed) > 0 {
+ headers[headerAllowHeaders] = strings.Join(allowed, ",")
+ }
+
+ // add exposed headers
+ if len(o.ExposeHeaders) > 0 {
+ headers[headerExposeHeaders] = strings.Join(o.ExposeHeaders, ",")
+ }
+ // add a max age header
+ if o.MaxAge > time.Duration(0) {
+ headers[headerMaxAge] = strconv.FormatInt(int64(o.MaxAge/time.Second), 10)
+ }
+ return
+}
+
+// IsOriginAllowed looks up if the origin matches one of the patterns
+// generated from Options.AllowOrigins patterns.
+func (o *Options) IsOriginAllowed(origin string) (allowed bool) {
+ for _, pattern := range allowOriginPatterns {
+ allowed, _ = regexp.MatchString(pattern, origin)
+ if allowed {
+ return
+ }
+ }
+ return
+}
+
+// Allow enables CORS for requests those match the provided options.
+func Allow(opts *Options) beego.FilterFunc {
+ // Allow default headers if nothing is specified.
+ if len(opts.AllowHeaders) == 0 {
+ opts.AllowHeaders = defaultAllowHeaders
+ }
+
+ for _, origin := range opts.AllowOrigins {
+ pattern := regexp.QuoteMeta(origin)
+ pattern = strings.Replace(pattern, "\\*", ".*", -1)
+ pattern = strings.Replace(pattern, "\\?", ".", -1)
+ allowOriginPatterns = append(allowOriginPatterns, "^"+pattern+"$")
+ }
+
+ return func(ctx *context.Context) {
+ var (
+ origin = ctx.Input.Header(headerOrigin)
+ requestedMethod = ctx.Input.Header(headerRequestMethod)
+ requestedHeaders = ctx.Input.Header(headerRequestHeaders)
+ // additional headers to be added
+ // to the response.
+ headers map[string]string
+ )
+
+ if ctx.Input.Method() == "OPTIONS" &&
+ (requestedMethod != "" || requestedHeaders != "") {
+ headers = opts.PreflightHeader(origin, requestedMethod, requestedHeaders)
+ for key, value := range headers {
+ ctx.Output.Header(key, value)
+ }
+ ctx.Output.SetStatus(http.StatusOK)
+ return
+ }
+ headers = opts.Header(origin)
+
+ for key, value := range headers {
+ ctx.Output.Header(key, value)
+ }
+ }
+}
diff --git a/plugins/cors/cors_test.go b/plugins/cors/cors_test.go
new file mode 100644
index 00000000..5c02ab98
--- /dev/null
+++ b/plugins/cors/cors_test.go
@@ -0,0 +1,252 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cors
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/astaxie/beego"
+ "github.com/astaxie/beego/context"
+)
+
+type HttpHeaderGuardRecorder struct {
+ *httptest.ResponseRecorder
+ savedHeaderMap http.Header
+}
+
+func NewRecorder() *HttpHeaderGuardRecorder {
+ return &HttpHeaderGuardRecorder{httptest.NewRecorder(), nil}
+}
+
+func (gr *HttpHeaderGuardRecorder) WriteHeader(code int) {
+ gr.ResponseRecorder.WriteHeader(code)
+ gr.savedHeaderMap = gr.ResponseRecorder.Header()
+}
+
+func (gr *HttpHeaderGuardRecorder) Header() http.Header {
+ if gr.savedHeaderMap != nil {
+ // headers were written. clone so we don't get updates
+ clone := make(http.Header)
+ for k, v := range gr.savedHeaderMap {
+ clone[k] = v
+ }
+ return clone
+ } else {
+ return gr.ResponseRecorder.Header()
+ }
+}
+
+func Test_AllowAll(t *testing.T) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowAllOrigins: true,
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ handler.ServeHTTP(recorder, r)
+
+ if recorder.HeaderMap.Get(headerAllowOrigin) != "*" {
+ t.Errorf("Allow-Origin header should be *")
+ }
+}
+
+func Test_AllowRegexMatch(t *testing.T) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowOrigins: []string{"https://aaa.com", "https://*.foo.com"},
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ origin := "https://bar.foo.com"
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ r.Header.Add("Origin", origin)
+ handler.ServeHTTP(recorder, r)
+
+ headerValue := recorder.HeaderMap.Get(headerAllowOrigin)
+ if headerValue != origin {
+ t.Errorf("Allow-Origin header should be %v, found %v", origin, headerValue)
+ }
+}
+
+func Test_AllowRegexNoMatch(t *testing.T) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowOrigins: []string{"https://*.foo.com"},
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ origin := "https://ww.foo.com.evil.com"
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ r.Header.Add("Origin", origin)
+ handler.ServeHTTP(recorder, r)
+
+ headerValue := recorder.HeaderMap.Get(headerAllowOrigin)
+ if headerValue != "" {
+ t.Errorf("Allow-Origin header should not exist, found %v", headerValue)
+ }
+}
+
+func Test_OtherHeaders(t *testing.T) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowAllOrigins: true,
+ AllowCredentials: true,
+ AllowMethods: []string{"PATCH", "GET"},
+ AllowHeaders: []string{"Origin", "X-whatever"},
+ ExposeHeaders: []string{"Content-Length", "Hello"},
+ MaxAge: 5 * time.Minute,
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ handler.ServeHTTP(recorder, r)
+
+ credentialsVal := recorder.HeaderMap.Get(headerAllowCredentials)
+ methodsVal := recorder.HeaderMap.Get(headerAllowMethods)
+ headersVal := recorder.HeaderMap.Get(headerAllowHeaders)
+ exposedHeadersVal := recorder.HeaderMap.Get(headerExposeHeaders)
+ maxAgeVal := recorder.HeaderMap.Get(headerMaxAge)
+
+ if credentialsVal != "true" {
+ t.Errorf("Allow-Credentials is expected to be true, found %v", credentialsVal)
+ }
+
+ if methodsVal != "PATCH,GET" {
+ t.Errorf("Allow-Methods is expected to be PATCH,GET; found %v", methodsVal)
+ }
+
+ if headersVal != "Origin,X-whatever" {
+ t.Errorf("Allow-Headers is expected to be Origin,X-whatever; found %v", headersVal)
+ }
+
+ if exposedHeadersVal != "Content-Length,Hello" {
+ t.Errorf("Expose-Headers are expected to be Content-Length,Hello. Found %v", exposedHeadersVal)
+ }
+
+ if maxAgeVal != "300" {
+ t.Errorf("Max-Age is expected to be 300, found %v", maxAgeVal)
+ }
+}
+
+func Test_DefaultAllowHeaders(t *testing.T) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowAllOrigins: true,
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ handler.ServeHTTP(recorder, r)
+
+ headersVal := recorder.HeaderMap.Get(headerAllowHeaders)
+ if headersVal != "Origin,Accept,Content-Type,Authorization" {
+ t.Errorf("Allow-Headers is expected to be Origin,Accept,Content-Type,Authorization; found %v", headersVal)
+ }
+}
+
+func Test_Preflight(t *testing.T) {
+ recorder := NewRecorder()
+ handler := beego.NewControllerRegister()
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowAllOrigins: true,
+ AllowMethods: []string{"PUT", "PATCH"},
+ AllowHeaders: []string{"Origin", "X-whatever", "X-CaseSensitive"},
+ }))
+
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(200)
+ })
+
+ r, _ := http.NewRequest("OPTIONS", "/foo", nil)
+ r.Header.Add(headerRequestMethod, "PUT")
+ r.Header.Add(headerRequestHeaders, "X-whatever, x-casesensitive")
+ handler.ServeHTTP(recorder, r)
+
+ headers := recorder.Header()
+ methodsVal := headers.Get(headerAllowMethods)
+ headersVal := headers.Get(headerAllowHeaders)
+ originVal := headers.Get(headerAllowOrigin)
+
+ if methodsVal != "PUT,PATCH" {
+ t.Errorf("Allow-Methods is expected to be PUT,PATCH, found %v", methodsVal)
+ }
+
+ if !strings.Contains(headersVal, "X-whatever") {
+ t.Errorf("Allow-Headers is expected to contain X-whatever, found %v", headersVal)
+ }
+
+ if !strings.Contains(headersVal, "x-casesensitive") {
+ t.Errorf("Allow-Headers is expected to contain x-casesensitive, found %v", headersVal)
+ }
+
+ if originVal != "*" {
+ t.Errorf("Allow-Origin is expected to be *, found %v", originVal)
+ }
+
+ if recorder.Code != http.StatusOK {
+ t.Errorf("Status code is expected to be 200, found %d", recorder.Code)
+ }
+}
+
+func Benchmark_WithoutCORS(b *testing.B) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ beego.RunMode = "prod"
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ b.ResetTimer()
+ for i := 0; i < 100; i++ {
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ handler.ServeHTTP(recorder, r)
+ }
+}
+
+func Benchmark_WithCORS(b *testing.B) {
+ recorder := httptest.NewRecorder()
+ handler := beego.NewControllerRegister()
+ beego.RunMode = "prod"
+ handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{
+ AllowAllOrigins: true,
+ AllowCredentials: true,
+ AllowMethods: []string{"PATCH", "GET"},
+ AllowHeaders: []string{"Origin", "X-whatever"},
+ MaxAge: 5 * time.Minute,
+ }))
+ handler.Any("/foo", func(ctx *context.Context) {
+ ctx.Output.SetStatus(500)
+ })
+ b.ResetTimer()
+ for i := 0; i < 100; i++ {
+ r, _ := http.NewRequest("PUT", "/foo", nil)
+ handler.ServeHTTP(recorder, r)
+ }
+}
diff --git a/router.go b/router.go
index 0041c273..6f8bd769 100644
--- a/router.go
+++ b/router.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -29,7 +37,8 @@ import (
const (
// default filter execution points
- BeforeRouter = iota
+ BeforeStatic = iota
+ BeforeRouter
BeforeExec
AfterExec
FinishRouter
@@ -62,6 +71,8 @@ var (
"DelSession", "SessionRegenerateID", "DestroySession", "IsAjax", "GetSecureCookie",
"SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml",
"GetControllerAndAction"}
+
+ url_placeholder = "{{placeholder}}"
)
// To append a slice's value into "exceptMethod", for controller's methods shouldn't reflect to AutoRouter
@@ -342,19 +353,23 @@ func (p *ControllerRegistor) AddAutoPrefix(prefix string, c ControllerInterface)
reflectVal := reflect.ValueOf(c)
rt := reflectVal.Type()
ct := reflect.Indirect(reflectVal).Type()
- controllerName := strings.ToLower(strings.TrimSuffix(ct.Name(), "Controller"))
+ controllerName := strings.TrimSuffix(ct.Name(), "Controller")
for i := 0; i < rt.NumMethod(); i++ {
if !utils.InSlice(rt.Method(i).Name, exceptMethod) {
route := &controllerInfo{}
route.routerType = routerTypeBeego
route.methods = map[string]string{"*": rt.Method(i).Name}
route.controllerType = ct
- pattern := path.Join(prefix, controllerName, strings.ToLower(rt.Method(i).Name), "*")
- patternfix := path.Join(prefix, controllerName, strings.ToLower(rt.Method(i).Name))
+ pattern := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name), "*")
+ patternInit := path.Join(prefix, controllerName, rt.Method(i).Name, "*")
+ patternfix := path.Join(prefix, strings.ToLower(controllerName), strings.ToLower(rt.Method(i).Name))
+ patternfixInit := path.Join(prefix, controllerName, rt.Method(i).Name)
route.pattern = pattern
for _, m := range HTTPMETHOD {
p.addToRouter(m, pattern, route)
+ p.addToRouter(m, patternInit, route)
p.addToRouter(m, patternfix, route)
+ p.addToRouter(m, patternfixInit, route)
}
}
}
@@ -420,6 +435,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
}
}
if t.wildcard != nil {
+ url = path.Join(url, url_placeholder)
ok, u := p.geturl(t.wildcard, url, controllName, methodName, params)
if ok {
return ok, u
@@ -448,15 +464,14 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
if find {
if l.regexps == nil {
if len(l.wildcards) == 0 {
- return true, url
+ return true, strings.Replace(url, "/"+url_placeholder, "", 1) + tourl(params)
}
if len(l.wildcards) == 1 {
if v, ok := params[l.wildcards[0]]; ok {
delete(params, l.wildcards[0])
- return true, url + "/" + v + tourl(params)
- }
- if l.wildcards[0] == ":splat" {
- return true, url + tourl(params)
+ return true, strings.Replace(url, url_placeholder, v, 1) + tourl(params)
+ } else {
+ return false, ""
}
}
if len(l.wildcards) == 3 && l.wildcards[0] == "." {
@@ -464,7 +479,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
if e, isok := params[":ext"]; isok {
delete(params, ":path")
delete(params, ":ext")
- return true, url + "/" + p + "." + e + tourl(params)
+ return true, strings.Replace(url, url_placeholder, p+"."+e, -1) + tourl(params)
}
}
}
@@ -475,7 +490,8 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
continue
}
if u, ok := params[v]; ok {
- url += "/" + u
+ delete(params, v)
+ url = strings.Replace(url, url_placeholder, u, 1)
} else {
if canskip {
canskip = false
@@ -485,7 +501,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
}
}
}
- return true, url
+ return true, url + tourl(params)
} else {
var i int
var startreg bool
@@ -508,11 +524,11 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
}
}
if l.regexps.MatchString(regurl) {
- if url == "/" {
- return true, url + regurl + tourl(params)
- } else {
- return true, url + "/" + regurl + tourl(params)
+ ps := strings.Split(regurl, "/")
+ for _, p := range ps {
+ url = strings.Replace(url, url_placeholder, p, 1)
}
+ return true, url + tourl(params)
}
}
}
@@ -567,6 +583,23 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
return false
}
+ // filter wrong httpmethod
+ if _, ok := HTTPMETHOD[r.Method]; !ok {
+ http.Error(w, "Method Not Allowed", 405)
+ goto Admin
+ }
+
+ // filter for static file
+ if do_filter(BeforeStatic) {
+ goto Admin
+ }
+
+ serverStaticRouter(context)
+ if w.started {
+ findrouter = true
+ goto Admin
+ }
+
// session init
if SessionOn {
context.Input.CruSession = GlobalSessions.SessionStart(w, r)
@@ -575,11 +608,6 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}()
}
- if _, ok := HTTPMETHOD[r.Method]; !ok {
- http.Error(w, "Method Not Allowed", 405)
- goto Admin
- }
-
if r.Method != "GET" && r.Method != "HEAD" {
if CopyRequestBody && !context.Input.IsUpload() {
context.Input.CopyBody()
@@ -710,12 +738,11 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
}
//render template
- if !w.started {
+ if !w.started && context.Output.Status == 0 {
if AutoRender {
if err := execController.Render(); err != nil {
panic(err)
}
-
}
}
}
@@ -746,11 +773,22 @@ Admin:
}
if RunMode == "dev" {
+ var devinfo string
if findrouter {
- Info("beego: router defined " + routerInfo.pattern + " " + r.URL.Path + " +" + timeend.String())
+ if routerInfo != nil {
+ devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s | % -40s |", r.Method, r.URL.Path, timeend.String(), "match", routerInfo.pattern)
+ } else {
+ devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "match")
+ }
} else {
- Info("beego:" + r.URL.Path + " 404" + " +" + timeend.String())
+ devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "notmatch")
}
+ Debug(devinfo)
+ }
+
+ // Call WriteHeader if status code has been set changed
+ if context.Output.Status != 0 {
+ w.writer.WriteHeader(context.Output.Status)
}
}
diff --git a/router_test.go b/router_test.go
index b80000f4..d378589b 100644
--- a/router_test.go
+++ b/router_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -91,10 +99,10 @@ func TestUrlFor(t *testing.T) {
func TestUrlFor3(t *testing.T) {
handler := NewControllerRegister()
handler.AddAuto(&TestController{})
- if a := handler.UrlFor("TestController.Myext"); a != "/test/myext" {
+ if a := handler.UrlFor("TestController.Myext"); a != "/test/myext" && a != "/Test/Myext" {
t.Errorf("TestController.Myext must equal to /test/myext, but get " + a)
}
- if a := handler.UrlFor("TestController.GetUrl"); a != "/test/geturl" {
+ if a := handler.UrlFor("TestController.GetUrl"); a != "/test/geturl" && a != "/Test/GetUrl" {
t.Errorf("TestController.GetUrl must equal to /test/geturl, but get " + a)
}
}
@@ -102,8 +110,14 @@ func TestUrlFor3(t *testing.T) {
func TestUrlFor2(t *testing.T) {
handler := NewControllerRegister()
handler.Add("/v1/:v/cms_:id(.+)_:page(.+).html", &TestController{}, "*:List")
+ handler.Add("/v1/:username/edit", &TestController{}, "get:GetUrl")
handler.Add("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", &TestController{}, "*:Param")
handler.Add("/:year:int/:month:int/:title/:entid", &TestController{})
+ if handler.UrlFor("TestController.GetUrl", ":username", "astaxie") != "/v1/astaxie/edit" {
+ Info(handler.UrlFor("TestController.GetUrl"))
+ t.Errorf("TestController.List must equal to /v1/astaxie/edit")
+ }
+
if handler.UrlFor("TestController.List", ":v", "za", ":id", "12", ":page", "123") !=
"/v1/za/cms_12_123.html" {
Info(handler.UrlFor("TestController.List"))
@@ -158,6 +172,18 @@ func TestAutoFunc(t *testing.T) {
}
}
+func TestAutoFunc2(t *testing.T) {
+ r, _ := http.NewRequest("GET", "/Test/List", nil)
+ w := httptest.NewRecorder()
+
+ handler := NewControllerRegister()
+ handler.AddAuto(&TestController{})
+ handler.ServeHTTP(w, r)
+ if w.Body.String() != "i am list" {
+ t.Errorf("user define func can't run")
+ }
+}
+
func TestAutoFuncParams(t *testing.T) {
r, _ := http.NewRequest("GET", "/test/params/2009/11/12", nil)
w := httptest.NewRecorder()
diff --git a/session/couchbase/sess_couchbase.go b/session/couchbase/sess_couchbase.go
index 9f68b946..827d55d9 100644
--- a/session/couchbase/sess_couchbase.go
+++ b/session/couchbase/sess_couchbase.go
@@ -1,9 +1,35 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package couchbase for session provider
+//
+// depend on github.com/couchbaselabs/go-couchbasee
+//
+// go install github.com/couchbaselabs/go-couchbase
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/session/couchbase"
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("couchbase", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"http://host:port/, Pool, Bucket"}``)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
package session
import (
@@ -72,12 +98,6 @@ func (cs *CouchbaseSessionStore) SessionID() string {
func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
defer cs.b.Close()
- // if rs.values is empty, return directly
- if len(cs.values) < 1 {
- cs.b.Delete(cs.sid)
- return
- }
-
bo, err := session.EncodeGob(cs.values)
if err != nil {
return
diff --git a/session/memcache/sess_memcache.go b/session/memcache/sess_memcache.go
index fa8fa165..5827a0a9 100644
--- a/session/memcache/sess_memcache.go
+++ b/session/memcache/sess_memcache.go
@@ -1,25 +1,52 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package memcache for session provider
+//
+// depend on github.com/bradfitz/gomemcache/memcache
+//
+// go install github.com/bradfitz/gomemcache/memcache
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/session/memcache"
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("memcache", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:11211"}``)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
package session
import (
"net/http"
+ "strings"
"sync"
"github.com/astaxie/beego/session"
- "github.com/beego/memcache"
+ "github.com/bradfitz/gomemcache/memcache"
)
var mempder = &MemProvider{}
+var client *memcache.Client
// memcache session store
type MemcacheSessionStore struct {
- c *memcache.Connection
sid string
lock sync.RWMutex
values map[interface{}]interface{}
@@ -61,133 +88,138 @@ func (rs *MemcacheSessionStore) Flush() error {
return nil
}
-// get redis session id
+// get memcache session id
func (rs *MemcacheSessionStore) SessionID() string {
return rs.sid
}
-// save session values to redis
+// save session values to memcache
func (rs *MemcacheSessionStore) SessionRelease(w http.ResponseWriter) {
- defer rs.c.Close()
- // if rs.values is empty, return directly
- if len(rs.values) < 1 {
- rs.c.Delete(rs.sid)
- return
- }
-
b, err := session.EncodeGob(rs.values)
if err != nil {
return
}
- rs.c.Set(rs.sid, 0, uint64(rs.maxlifetime), b)
+ item := memcache.Item{Key: rs.sid, Value: b, Expiration: int32(rs.maxlifetime)}
+ client.Set(&item)
}
-// redis session provider
+// memcahe session provider
type MemProvider struct {
maxlifetime int64
- savePath string
+ conninfo []string
poolsize int
password string
}
-// init redis session
+// init memcache session
// savepath like
// e.g. 127.0.0.1:9090
func (rp *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
rp.maxlifetime = maxlifetime
- rp.savePath = savePath
+ rp.conninfo = strings.Split(savePath, ";")
+ client = memcache.New(rp.conninfo...)
return nil
}
-// read redis session by sid
+// read memcache session by sid
func (rp *MemProvider) SessionRead(sid string) (session.SessionStore, error) {
- conn, err := rp.connectInit()
+ if client == nil {
+ if err := rp.connectInit(); err != nil {
+ return nil, err
+ }
+ }
+ item, err := client.Get(sid)
if err != nil {
return nil, err
}
- kvs, err := conn.Get(sid)
- if err != nil {
- return nil, err
- }
- var contain []byte
- if len(kvs) > 0 {
- contain = kvs[0].Value
- }
var kv map[interface{}]interface{}
- if len(contain) == 0 {
+ if len(item.Value) == 0 {
kv = make(map[interface{}]interface{})
} else {
- kv, err = session.DecodeGob(contain)
+ kv, err = session.DecodeGob(item.Value)
if err != nil {
return nil, err
}
}
- rs := &MemcacheSessionStore{c: conn, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
+ rs := &MemcacheSessionStore{sid: sid, values: kv, maxlifetime: rp.maxlifetime}
return rs, nil
}
-// check redis session exist by sid
+// check memcache session exist by sid
func (rp *MemProvider) SessionExist(sid string) bool {
- conn, err := rp.connectInit()
- if err != nil {
- return false
+ if client == nil {
+ if err := rp.connectInit(); err != nil {
+ return false
+ }
}
- defer conn.Close()
- if kvs, err := conn.Get(sid); err != nil || len(kvs) == 0 {
+ if item, err := client.Get(sid); err != nil || len(item.Value) == 0 {
return false
} else {
return true
}
}
-// generate new sid for redis session
+// generate new sid for memcache session
func (rp *MemProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
- conn, err := rp.connectInit()
- if err != nil {
- return nil, err
+ if client == nil {
+ if err := rp.connectInit(); err != nil {
+ return nil, err
+ }
}
var contain []byte
- if kvs, err := conn.Get(sid); err != nil || len(kvs) == 0 {
+ if item, err := client.Get(sid); err != nil || len(item.Value) == 0 {
// oldsid doesn't exists, set the new sid directly
// ignore error here, since if it return error
// the existed value will be 0
- conn.Set(sid, 0, uint64(rp.maxlifetime), []byte(""))
+ item.Key = sid
+ item.Value = []byte("")
+ item.Expiration = int32(rp.maxlifetime)
+ client.Set(item)
} else {
- conn.Delete(oldsid)
- conn.Set(sid, 0, uint64(rp.maxlifetime), kvs[0].Value)
- contain = kvs[0].Value
+ client.Delete(oldsid)
+ item.Key = sid
+ item.Value = item.Value
+ item.Expiration = int32(rp.maxlifetime)
+ client.Set(item)
+ contain = item.Value
}
var kv map[interface{}]interface{}
if len(contain) == 0 {
kv = make(map[interface{}]interface{})
} else {
+ var err error
kv, err = session.DecodeGob(contain)
if err != nil {
return nil, err
}
}
- rs := &MemcacheSessionStore{c: conn, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
+ rs := &MemcacheSessionStore{sid: sid, values: kv, maxlifetime: rp.maxlifetime}
return rs, nil
}
-// delete redis session by id
+// delete memcache session by id
func (rp *MemProvider) SessionDestroy(sid string) error {
- conn, err := rp.connectInit()
- if err != nil {
- return err
+ if client == nil {
+ if err := rp.connectInit(); err != nil {
+ return err
+ }
}
- defer conn.Close()
- _, err = conn.Delete(sid)
+ err := client.Delete(sid)
if err != nil {
return err
}
return nil
}
+func (rp *MemProvider) connectInit() error {
+ client = memcache.New(rp.conninfo...)
+ return nil
+}
+
// Impelment method, no used.
func (rp *MemProvider) SessionGC() {
return
@@ -198,15 +230,6 @@ func (rp *MemProvider) SessionAll() int {
return 0
}
-// connect to memcache and keep the connection.
-func (rp *MemProvider) connectInit() (*memcache.Connection, error) {
- c, err := memcache.Connect(rp.savePath)
- if err != nil {
- return nil, err
- }
- return c, nil
-}
-
func init() {
session.Register("memcache", mempder)
}
diff --git a/session/mysql/sess_mysql.go b/session/mysql/sess_mysql.go
index 530ca158..0f6d3e4f 100644
--- a/session/mysql/sess_mysql.go
+++ b/session/mysql/sess_mysql.go
@@ -1,11 +1,23 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
-
-package session
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package mysql for session provider
+//
+// depends on github.com/go-sql-driver/mysql:
+//
+// go install github.com/go-sql-driver/mysql
+//
// mysql session support need create table as sql:
// CREATE TABLE `session` (
// `session_key` char(64) NOT NULL,
@@ -13,6 +25,20 @@ package session
// `session_expiry` int(11) unsigned NOT NULL,
// PRIMARY KEY (`session_key`)
// ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/session/mysql"
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]"}``)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
+package session
import (
"database/sql"
diff --git a/session/postgres/sess_postgresql.go b/session/postgres/sess_postgresql.go
index 7f905997..ac9a1612 100644
--- a/session/postgres/sess_postgresql.go
+++ b/session/postgres/sess_postgresql.go
@@ -1,40 +1,55 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package postgresql for session provider
+//
+// depends on github.com/lib/pq:
+//
+// go install github.com/lib/pq
+//
+//
+// needs this table in your database:
+//
+// CREATE TABLE session (
+// session_key char(64) NOT NULL,
+// session_data bytea,
+// session_expiry timestamp NOT NULL,
+// CONSTRAINT session_key PRIMARY KEY(session_key)
+// );
+
+// will be activated with these settings in app.conf:
+
+// SessionOn = true
+// SessionProvider = postgresql
+// SessionSavePath = "user=a password=b dbname=c sslmode=disable"
+// SessionName = session
+//
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/session/postgresql"
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("postgresql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"user=pqgotest dbname=pqgotest sslmode=verify-full"}``)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
package session
-/*
-
-beego session provider for postgresql
--------------------------------------
-
-depends on github.com/lib/pq:
-
-go install github.com/lib/pq
-
-
-needs this table in your database:
-
-CREATE TABLE session (
-session_key char(64) NOT NULL,
-session_data bytea,
-session_expiry timestamp NOT NULL,
-CONSTRAINT session_key PRIMARY KEY(session_key)
-);
-
-
-will be activated with these settings in app.conf:
-
-SessionOn = true
-SessionProvider = postgresql
-SessionSavePath = "user=a password=b dbname=c sslmode=disable"
-SessionName = session
-
-*/
-
import (
"database/sql"
"net/http"
diff --git a/session/redis/sess_redis.go b/session/redis/sess_redis.go
index 3ad19792..f2b0b29b 100644
--- a/session/redis/sess_redis.go
+++ b/session/redis/sess_redis.go
@@ -1,9 +1,35 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package redis for session provider
+//
+// depend on github.com/garyburd/redigo/redis
+//
+// go install github.com/garyburd/redigo/redis
+//
+// Usage:
+// import(
+// _ "github.com/astaxie/beego/session/redis"
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
package session
import (
@@ -14,7 +40,7 @@ import (
"github.com/astaxie/beego/session"
- "github.com/beego/redigo/redis"
+ "github.com/garyburd/redigo/redis"
)
var redispder = &RedisProvider{}
@@ -78,12 +104,6 @@ func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
c := rs.p.Get()
defer c.Close()
- // if rs.values is empty, return directly
- if len(rs.values) < 1 {
- c.Do("DEL", rs.sid)
- return
- }
-
b, err := session.EncodeGob(rs.values)
if err != nil {
return
diff --git a/session/sess_cookie.go b/session/sess_cookie.go
index 1a06add6..01dc505c 100644
--- a/session/sess_cookie.go
+++ b/session/sess_cookie.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/sess_cookie_test.go b/session/sess_cookie_test.go
index 9ab321f5..4f40a7ba 100644
--- a/session/sess_cookie_test.go
+++ b/session/sess_cookie_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/sess_file.go b/session/sess_file.go
index 74b71223..b1084acf 100644
--- a/session/sess_file.go
+++ b/session/sess_file.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
@@ -26,7 +34,6 @@ var (
// File session store
type FileSessionStore struct {
- f *os.File
sid string
lock sync.RWMutex
values map[interface{}]interface{}
@@ -74,14 +81,23 @@ func (fs *FileSessionStore) SessionID() string {
// Write file session to local file with Gob string
func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
- defer fs.f.Close()
b, err := EncodeGob(fs.values)
if err != nil {
return
}
- fs.f.Truncate(0)
- fs.f.Seek(0, 0)
- fs.f.Write(b)
+ _, err = os.Stat(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid))
+ var f *os.File
+ if err == nil {
+ f, err = os.OpenFile(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid), os.O_RDWR, 0777)
+ } else if os.IsNotExist(err) {
+ f, err = os.Create(path.Join(filepder.savePath, string(fs.sid[0]), string(fs.sid[1]), fs.sid))
+ } else {
+ return
+ }
+ f.Truncate(0)
+ f.Seek(0, 0)
+ f.Write(b)
+ f.Close()
}
// File session provider
@@ -134,8 +150,7 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
}
}
f.Close()
- f, err = os.OpenFile(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), os.O_WRONLY|os.O_CREATE, 0777)
- ss := &FileSessionStore{f: f, sid: sid, values: kv}
+ ss := &FileSessionStore{sid: sid, values: kv}
return ss, nil
}
@@ -232,9 +247,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err
return nil, err
}
}
-
- newf, err = os.OpenFile(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), os.O_WRONLY|os.O_CREATE, 0777)
- ss := &FileSessionStore{f: newf, sid: sid, values: kv}
+ ss := &FileSessionStore{sid: sid, values: kv}
return ss, nil
}
diff --git a/session/sess_mem.go b/session/sess_mem.go
index e440b2f5..627a3246 100644
--- a/session/sess_mem.go
+++ b/session/sess_mem.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/sess_mem_test.go b/session/sess_mem_test.go
index 5e54c634..03927c76 100644
--- a/session/sess_mem_test.go
+++ b/session/sess_mem_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/sess_test.go b/session/sess_test.go
index 1db55a64..5ba910f2 100644
--- a/session/sess_test.go
+++ b/session/sess_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/sess_utils.go b/session/sess_utils.go
index b9a965c3..9ae74528 100644
--- a/session/sess_utils.go
+++ b/session/sess_utils.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package session
diff --git a/session/session.go b/session/session.go
index eb9162b8..88e94d59 100644
--- a/session/session.go
+++ b/session/session.go
@@ -1,9 +1,30 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// package session provider
+//
+// Usage:
+// import(
+// "github.com/astaxie/beego/session"
+// )
+//
+// func init() {
+// globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "sessionIDHashFunc": "sha1", "sessionIDHashKey": "", "cookieLifeTime": 3600, "providerConfig": ""}`)
+// go globalSessions.GC()
+// }
+//
+// more docs: http://beego.me/docs/module/session.md
package session
import (
@@ -69,6 +90,7 @@ type managerConfig struct {
SessionIDHashKey string `json:"sessionIDHashKey"`
CookieLifeTime int `json:"cookieLifeTime"`
ProviderConfig string `json:"providerConfig"`
+ Domain string `json:"domain"`
}
// Manager contains Provider and its configuration.
@@ -131,7 +153,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
Value: url.QueryEscape(sid),
Path: "/",
HttpOnly: true,
- Secure: manager.config.Secure}
+ Secure: manager.config.Secure,
+ Domain: manager.config.Domain}
if manager.config.CookieLifeTime >= 0 {
cookie.MaxAge = manager.config.CookieLifeTime
}
@@ -150,7 +173,8 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
Value: url.QueryEscape(sid),
Path: "/",
HttpOnly: true,
- Secure: manager.config.Secure}
+ Secure: manager.config.Secure,
+ Domain: manager.config.Domain}
if manager.config.CookieLifeTime >= 0 {
cookie.MaxAge = manager.config.CookieLifeTime
}
@@ -205,6 +229,7 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque
Path: "/",
HttpOnly: true,
Secure: manager.config.Secure,
+ Domain: manager.config.Domain,
}
} else {
oldsid, _ := url.QueryUnescape(cookie.Value)
diff --git a/staticfile.go b/staticfile.go
index 09f3018f..a9deabe9 100644
--- a/staticfile.go
+++ b/staticfile.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -19,16 +27,22 @@ import (
)
func serverStaticRouter(ctx *context.Context) {
+ if ctx.Input.Method() != "GET" && ctx.Input.Method() != "HEAD" {
+ return
+ }
requestPath := path.Clean(ctx.Input.Request.URL.Path)
for prefix, staticDir := range StaticDir {
if len(prefix) == 0 {
continue
}
- if requestPath == "/favicon.ico" {
+ if requestPath == "/favicon.ico" || requestPath == "/robots.txt" {
file := path.Join(staticDir, requestPath)
if utils.FileExists(file) {
http.ServeFile(ctx.ResponseWriter, ctx.Request, file)
return
+ } else {
+ http.NotFound(ctx.ResponseWriter, ctx.Request)
+ return
}
}
if strings.HasPrefix(requestPath, prefix) {
diff --git a/swagger/docsSpec.go b/swagger/docsSpec.go
index 94ff75ef..6f8fe1db 100644
--- a/swagger/docsSpec.go
+++ b/swagger/docsSpec.go
@@ -1,3 +1,18 @@
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// swagger struct definition
package swagger
const SwaggerVersion = "1.2"
diff --git a/template.go b/template.go
index 9411930c..2ca84f22 100644
--- a/template.go
+++ b/template.go
@@ -1,13 +1,19 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
-//@todo add template funcs
-
import (
"errors"
"fmt"
diff --git a/template_test.go b/template_test.go
index 15014980..b35da5ce 100644
--- a/template_test.go
+++ b/template_test.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
diff --git a/templatefunc.go b/templatefunc.go
index ef7658d6..a365718d 100644
--- a/templatefunc.go
+++ b/templatefunc.go
@@ -1,8 +1,16 @@
-// Beego (http://beego.me/)
-// @description beego is an open-source, high-performance web framework for the Go programming language.
-// @link http://github.com/astaxie/beego for the canonical source repository
-// @license http://github.com/astaxie/beego/blob/master/LICENSE
-// @authors astaxie
+// Copyright 2014 beego Author. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
package beego
@@ -24,6 +32,9 @@ func Substr(s string, start, length int) string {
if start < 0 {
start = 0
}
+ if start > len(bt) {
+ start = start % len(bt)
+ }
var end int
if (start + length) > (len(bt) - 1) {
end = len(bt)
@@ -37,23 +48,20 @@ func Substr(s string, start, length int) string {
func Html2str(html string) string {
src := string(html)
- //将HTML标签全转换成小写
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
src = re.ReplaceAllStringFunc(src, strings.ToLower)
- //去除STYLE
+ //remove STYLE
re, _ = regexp.Compile("\\