mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 20:50:54 +00:00
Merge branch 'astaxie-master'
This commit is contained in:
commit
baf2c63d5c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
16
.go_style
Normal file
16
.go_style
Normal file
@ -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"
|
||||||
|
]
|
||||||
|
}
|
23
README.md
23
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)
|
[![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.
|
beego is an open-source, high-performance, modularity, full-stack web framework.
|
||||||
|
|
||||||
It is a simple & powerful web framework.
|
|
||||||
|
|
||||||
More info [beego.me](http://beego.me)
|
More info [beego.me](http://beego.me)
|
||||||
|
|
||||||
@ -12,20 +10,18 @@ More info [beego.me](http://beego.me)
|
|||||||
|
|
||||||
* RESTful support
|
* RESTful support
|
||||||
* MVC architecture
|
* MVC architecture
|
||||||
* Session support (store in memory, file, Redis or MySQL)
|
* modularity
|
||||||
* Cache support (store in memory, Redis or Memcache)
|
* auto API documents
|
||||||
* Global Config
|
* annotation router
|
||||||
* Intelligent routing
|
* namespace
|
||||||
* Thread-safe map
|
* powerful develop tools
|
||||||
* Friendly displaying of errors
|
* full stack for web & API
|
||||||
* Useful template functions
|
|
||||||
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[English](http://beego.me/docs/intro/)
|
[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/)
|
[中文文档](http://beego.me/docs/intro/)
|
||||||
|
|
||||||
@ -34,6 +30,3 @@ More info [beego.me](http://beego.me)
|
|||||||
|
|
||||||
beego is licensed under the Apache Licence, Version 2.0
|
beego is licensed under the Apache Licence, Version 2.0
|
||||||
(http://www.apache.org/licenses/LICENSE-2.0.html).
|
(http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||||
|
|
||||||
[![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
|
|
408
admin.go
408
admin.go
@ -1,15 +1,25 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/toolbox"
|
"github.com/astaxie/beego/toolbox"
|
||||||
@ -46,7 +56,6 @@ func init() {
|
|||||||
beeAdminApp.Route("/prof", profIndex)
|
beeAdminApp.Route("/prof", profIndex)
|
||||||
beeAdminApp.Route("/healthcheck", healthcheck)
|
beeAdminApp.Route("/healthcheck", healthcheck)
|
||||||
beeAdminApp.Route("/task", taskStatus)
|
beeAdminApp.Route("/task", taskStatus)
|
||||||
beeAdminApp.Route("/runtask", runTask)
|
|
||||||
beeAdminApp.Route("/listconf", listConf)
|
beeAdminApp.Route("/listconf", listConf)
|
||||||
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
|
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
|
||||||
}
|
}
|
||||||
@ -54,22 +63,24 @@ func init() {
|
|||||||
// AdminIndex is the default http.Handler for admin module.
|
// AdminIndex is the default http.Handler for admin module.
|
||||||
// it matches url pattern "/".
|
// it matches url pattern "/".
|
||||||
func adminIndex(rw http.ResponseWriter, r *http.Request) {
|
func adminIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
rw.Write([]byte("<html><head><title>beego admin dashboard</title></head><body>"))
|
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
||||||
rw.Write([]byte("Welcome to Admin Dashboard<br>\n"))
|
tmpl = template.Must(tmpl.Parse(indexTpl))
|
||||||
rw.Write([]byte("There are servral functions:<br>\n"))
|
tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
|
||||||
rw.Write([]byte("1. Record all request and request time, <a href='/qps'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/qps</a><br>\n"))
|
data := make(map[interface{}]interface{})
|
||||||
rw.Write([]byte("2. Get runtime profiling data by the pprof, <a href='/prof'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/prof</a><br>\n"))
|
tmpl.Execute(rw, data)
|
||||||
rw.Write([]byte("3. Get healthcheck result from <a href='/healthcheck'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/healthcheck</a><br>\n"))
|
|
||||||
rw.Write([]byte("4. Get current task infomation from task <a href='/task'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/task</a><br> \n"))
|
|
||||||
rw.Write([]byte("5. To run a task passed a param <a href='/runtask'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/runtask</a><br>\n"))
|
|
||||||
rw.Write([]byte("6. Get all confige & router infomation <a href='/listconf'>http://localhost:" + strconv.Itoa(AdminHttpPort) + "/listconf</a><br>\n"))
|
|
||||||
rw.Write([]byte("</body></html>"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
|
// 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.
|
// it's registered with url pattern "/qbs" in admin module.
|
||||||
func qpsIndex(rw http.ResponseWriter, r *http.Request) {
|
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.
|
// 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()
|
r.ParseForm()
|
||||||
command := r.Form.Get("command")
|
command := r.Form.Get("command")
|
||||||
if command != "" {
|
if command != "" {
|
||||||
|
data := make(map[interface{}]interface{})
|
||||||
switch command {
|
switch command {
|
||||||
case "conf":
|
case "conf":
|
||||||
fmt.Fprintln(rw, "list all beego's conf:")
|
m := make(map[string]interface{})
|
||||||
fmt.Fprintln(rw, "AppName:", AppName)
|
|
||||||
fmt.Fprintln(rw, "AppPath:", AppPath)
|
m["AppName"] = AppName
|
||||||
fmt.Fprintln(rw, "AppConfigPath:", AppConfigPath)
|
m["AppPath"] = AppPath
|
||||||
fmt.Fprintln(rw, "StaticDir:", StaticDir)
|
m["AppConfigPath"] = AppConfigPath
|
||||||
fmt.Fprintln(rw, "StaticExtensionsToGzip:", StaticExtensionsToGzip)
|
m["StaticDir"] = StaticDir
|
||||||
fmt.Fprintln(rw, "HttpAddr:", HttpAddr)
|
m["StaticExtensionsToGzip"] = StaticExtensionsToGzip
|
||||||
fmt.Fprintln(rw, "HttpPort:", HttpPort)
|
m["HttpAddr"] = HttpAddr
|
||||||
fmt.Fprintln(rw, "HttpTLS:", EnableHttpTLS)
|
m["HttpPort"] = HttpPort
|
||||||
fmt.Fprintln(rw, "HttpCertFile:", HttpCertFile)
|
m["HttpTLS"] = EnableHttpTLS
|
||||||
fmt.Fprintln(rw, "HttpKeyFile:", HttpKeyFile)
|
m["HttpCertFile"] = HttpCertFile
|
||||||
fmt.Fprintln(rw, "RecoverPanic:", RecoverPanic)
|
m["HttpKeyFile"] = HttpKeyFile
|
||||||
fmt.Fprintln(rw, "AutoRender:", AutoRender)
|
m["RecoverPanic"] = RecoverPanic
|
||||||
fmt.Fprintln(rw, "ViewsPath:", ViewsPath)
|
m["AutoRender"] = AutoRender
|
||||||
fmt.Fprintln(rw, "RunMode:", RunMode)
|
m["ViewsPath"] = ViewsPath
|
||||||
fmt.Fprintln(rw, "SessionOn:", SessionOn)
|
m["RunMode"] = RunMode
|
||||||
fmt.Fprintln(rw, "SessionProvider:", SessionProvider)
|
m["SessionOn"] = SessionOn
|
||||||
fmt.Fprintln(rw, "SessionName:", SessionName)
|
m["SessionProvider"] = SessionProvider
|
||||||
fmt.Fprintln(rw, "SessionGCMaxLifetime:", SessionGCMaxLifetime)
|
m["SessionName"] = SessionName
|
||||||
fmt.Fprintln(rw, "SessionSavePath:", SessionSavePath)
|
m["SessionGCMaxLifetime"] = SessionGCMaxLifetime
|
||||||
fmt.Fprintln(rw, "SessionHashFunc:", SessionHashFunc)
|
m["SessionSavePath"] = SessionSavePath
|
||||||
fmt.Fprintln(rw, "SessionHashKey:", SessionHashKey)
|
m["SessionHashFunc"] = SessionHashFunc
|
||||||
fmt.Fprintln(rw, "SessionCookieLifeTime:", SessionCookieLifeTime)
|
m["SessionHashKey"] = SessionHashKey
|
||||||
fmt.Fprintln(rw, "UseFcgi:", UseFcgi)
|
m["SessionCookieLifeTime"] = SessionCookieLifeTime
|
||||||
fmt.Fprintln(rw, "MaxMemory:", MaxMemory)
|
m["UseFcgi"] = UseFcgi
|
||||||
fmt.Fprintln(rw, "EnableGzip:", EnableGzip)
|
m["MaxMemory"] = MaxMemory
|
||||||
fmt.Fprintln(rw, "DirectoryIndex:", DirectoryIndex)
|
m["EnableGzip"] = EnableGzip
|
||||||
fmt.Fprintln(rw, "HttpServerTimeOut:", HttpServerTimeOut)
|
m["DirectoryIndex"] = DirectoryIndex
|
||||||
fmt.Fprintln(rw, "ErrorsShow:", ErrorsShow)
|
m["HttpServerTimeOut"] = HttpServerTimeOut
|
||||||
fmt.Fprintln(rw, "XSRFKEY:", XSRFKEY)
|
m["ErrorsShow"] = ErrorsShow
|
||||||
fmt.Fprintln(rw, "EnableXSRF:", EnableXSRF)
|
m["XSRFKEY"] = XSRFKEY
|
||||||
fmt.Fprintln(rw, "XSRFExpire:", XSRFExpire)
|
m["EnableXSRF"] = EnableXSRF
|
||||||
fmt.Fprintln(rw, "CopyRequestBody:", CopyRequestBody)
|
m["XSRFExpire"] = XSRFExpire
|
||||||
fmt.Fprintln(rw, "TemplateLeft:", TemplateLeft)
|
m["CopyRequestBody"] = CopyRequestBody
|
||||||
fmt.Fprintln(rw, "TemplateRight:", TemplateRight)
|
m["TemplateLeft"] = TemplateLeft
|
||||||
fmt.Fprintln(rw, "BeegoServerName:", BeegoServerName)
|
m["TemplateRight"] = TemplateRight
|
||||||
fmt.Fprintln(rw, "EnableAdmin:", EnableAdmin)
|
m["BeegoServerName"] = BeegoServerName
|
||||||
fmt.Fprintln(rw, "AdminHttpAddr:", AdminHttpAddr)
|
m["EnableAdmin"] = EnableAdmin
|
||||||
fmt.Fprintln(rw, "AdminHttpPort:", AdminHttpPort)
|
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":
|
case "router":
|
||||||
fmt.Fprintln(rw, "Print all router infomation:")
|
resultList := new([][]string)
|
||||||
for method, t := range BeeApp.Handlers.routers {
|
|
||||||
fmt.Fprintln(rw)
|
var result = []string{
|
||||||
fmt.Fprintln(rw)
|
fmt.Sprintf("header"),
|
||||||
fmt.Fprintln(rw, " Method:", method)
|
fmt.Sprintf("Router Pattern"),
|
||||||
printTree(rw, t)
|
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":
|
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 {
|
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 {
|
if bf, ok := BeeApp.Handlers.filters[BeforeRouter]; ok {
|
||||||
for _, f := range bf {
|
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 {
|
if bf, ok := BeeApp.Handlers.filters[BeforeExec]; ok {
|
||||||
for _, f := range bf {
|
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 {
|
if bf, ok := BeeApp.Handlers.filters[AfterExec]; ok {
|
||||||
for _, f := range bf {
|
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 {
|
if bf, ok := BeeApp.Handlers.filters[FinishRouter]; ok {
|
||||||
for _, f := range bf {
|
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:
|
default:
|
||||||
rw.Write([]byte("command not support"))
|
rw.Write([]byte("command not support"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rw.Write([]byte("<html><head><title>beego admin dashboard</title></head><body>"))
|
|
||||||
rw.Write([]byte("ListConf support this command:<br>\n"))
|
|
||||||
rw.Write([]byte("1. <a href='?command=conf'>command=conf</a><br>\n"))
|
|
||||||
rw.Write([]byte("2. <a href='?command=router'>command=router</a><br>\n"))
|
|
||||||
rw.Write([]byte("3. <a href='?command=filter'>command=filter</a><br>\n"))
|
|
||||||
rw.Write([]byte("</body></html>"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printTree(rw http.ResponseWriter, t *Tree) {
|
func printTree(resultList *[][]string, t *Tree) {
|
||||||
for _, tr := range t.fixrouters {
|
for _, tr := range t.fixrouters {
|
||||||
printTree(rw, tr)
|
printTree(resultList, tr)
|
||||||
}
|
}
|
||||||
if t.wildcard != nil {
|
if t.wildcard != nil {
|
||||||
printTree(rw, t.wildcard)
|
printTree(resultList, t.wildcard)
|
||||||
}
|
}
|
||||||
for _, l := range t.leaves {
|
for _, l := range t.leaves {
|
||||||
if v, ok := l.runObject.(*controllerInfo); ok {
|
if v, ok := l.runObject.(*controllerInfo); ok {
|
||||||
if v.routerType == routerTypeBeego {
|
if v.routerType == routerTypeBeego {
|
||||||
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 {
|
} 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 {
|
} 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,60 +313,129 @@ func printTree(rw http.ResponseWriter, t *Tree) {
|
|||||||
func profIndex(rw http.ResponseWriter, r *http.Request) {
|
func profIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
command := r.Form.Get("command")
|
command := r.Form.Get("command")
|
||||||
|
format := r.Form.Get("format")
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
|
||||||
|
var result bytes.Buffer
|
||||||
if command != "" {
|
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 {
|
} else {
|
||||||
rw.Write([]byte("<html><head><title>beego admin dashboard</title></head><body>"))
|
|
||||||
rw.Write([]byte("request url like '/prof?command=lookup goroutine'<br>\n"))
|
|
||||||
rw.Write([]byte("the command have below types:<br>\n"))
|
|
||||||
rw.Write([]byte("1. <a href='?command=lookup goroutine'>lookup goroutine</a><br>\n"))
|
|
||||||
rw.Write([]byte("2. <a href='?command=lookup heap'>lookup heap</a><br>\n"))
|
|
||||||
rw.Write([]byte("3. <a href='?command=lookup threadcreate'>lookup threadcreate</a><br>\n"))
|
|
||||||
rw.Write([]byte("4. <a href='?command=lookup block'>lookup block</a><br>\n"))
|
|
||||||
rw.Write([]byte("5. <a href='?command=start cpuprof'>start cpuprof</a><br>\n"))
|
|
||||||
rw.Write([]byte("6. <a href='?command=stop cpuprof'>stop cpuprof</a><br>\n"))
|
|
||||||
rw.Write([]byte("7. <a href='?command=get memprof'>get memprof</a><br>\n"))
|
|
||||||
rw.Write([]byte("8. <a href='?command=gc summary'>gc summary</a><br>\n"))
|
|
||||||
rw.Write([]byte("</body></html>"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Healthcheck is a http.Handler calling health checking and showing the result.
|
// Healthcheck is a http.Handler calling health checking and showing the result.
|
||||||
// it's in "/healthcheck" pattern in admin module.
|
// it's in "/healthcheck" pattern in admin module.
|
||||||
func healthcheck(rw http.ResponseWriter, req *http.Request) {
|
func healthcheck(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
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 {
|
for name, h := range toolbox.AdminCheckList {
|
||||||
if err := h.Check(); err != nil {
|
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 {
|
} 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).
|
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
||||||
// it's in "/task" pattern in admin module.
|
// it's in "/task" pattern in admin module.
|
||||||
func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
||||||
for tname, tk := range toolbox.AdminTaskList {
|
data := make(map[interface{}]interface{})
|
||||||
fmt.Fprintf(rw, "%s:%s:%s", tname, tk.GetStatus(), tk.GetPrev().String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunTask is a http.Handler to run a Task from the "query string.
|
// Run Task
|
||||||
// the request url likes /runtask?taskname=sendmail.
|
|
||||||
func runTask(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
req.ParseForm()
|
req.ParseForm()
|
||||||
taskname := req.Form.Get("taskname")
|
taskname := req.Form.Get("taskname")
|
||||||
|
if taskname != "" {
|
||||||
|
|
||||||
if t, ok := toolbox.AdminTaskList[taskname]; ok {
|
if t, ok := toolbox.AdminTaskList[taskname]; ok {
|
||||||
err := t.Run()
|
err := t.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(rw, "%v", err)
|
data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(rw, "%s run success,Now the Status is %s", taskname, t.GetStatus())
|
data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is %s", taskname, t.GetStatus())}
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(rw, "there's no task which named:%s", taskname)
|
data["Message"] = []string{"warning", fmt.Sprintf("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.
|
// adminApp is an http.HandlerFunc map used as beeAdminApp.
|
||||||
type adminApp struct {
|
type adminApp struct {
|
||||||
routers map[string]http.HandlerFunc
|
routers map[string]http.HandlerFunc
|
||||||
|
345
adminui.go
Normal file
345
adminui.go
Normal file
File diff suppressed because one or more lines are too long
20
app.go
20
app.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
@ -66,6 +74,7 @@ func (app *App) Run() {
|
|||||||
|
|
||||||
if EnableHttpTLS {
|
if EnableHttpTLS {
|
||||||
go func() {
|
go func() {
|
||||||
|
time.Sleep(20 * time.Microsecond)
|
||||||
if HttpsPort != 0 {
|
if HttpsPort != 0 {
|
||||||
app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort)
|
app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort)
|
||||||
}
|
}
|
||||||
@ -80,6 +89,7 @@ func (app *App) Run() {
|
|||||||
|
|
||||||
if EnableHttpListen {
|
if EnableHttpListen {
|
||||||
go func() {
|
go func() {
|
||||||
|
app.Server.Addr = addr
|
||||||
err := app.Server.ListenAndServe()
|
err := app.Server.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
BeeLogger.Critical("ListenAndServe: ", err)
|
BeeLogger.Critical("ListenAndServe: ", err)
|
||||||
|
41
beego.go
41
beego.go
@ -1,9 +1,28 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -19,7 +38,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// beego web framework version.
|
// beego web framework version.
|
||||||
const VERSION = "1.3.1"
|
const VERSION = "1.4.0"
|
||||||
|
|
||||||
type hookfunc func() error //hook function to run
|
type hookfunc func() error //hook function to run
|
||||||
var hooks []hookfunc //hook function slice to store the hookfunc
|
var hooks []hookfunc //hook function slice to store the hookfunc
|
||||||
@ -359,6 +378,7 @@ func initBeforeHttpRun() {
|
|||||||
`"sessionIDHashFunc":"` + SessionHashFunc + `",` +
|
`"sessionIDHashFunc":"` + SessionHashFunc + `",` +
|
||||||
`"sessionIDHashKey":"` + SessionHashKey + `",` +
|
`"sessionIDHashKey":"` + SessionHashKey + `",` +
|
||||||
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
|
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
|
||||||
|
`"domain":"` + SessionDomain + `",` +
|
||||||
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
|
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
|
||||||
}
|
}
|
||||||
GlobalSessions, err = session.NewManager(SessionProvider,
|
GlobalSessions, err = session.NewManager(SessionProvider,
|
||||||
@ -380,14 +400,13 @@ func initBeforeHttpRun() {
|
|||||||
middleware.AppName = AppName
|
middleware.AppName = AppName
|
||||||
middleware.RegisterErrorHandler()
|
middleware.RegisterErrorHandler()
|
||||||
|
|
||||||
for u, _ := range StaticDir {
|
|
||||||
Get(u, serverStaticRouter)
|
|
||||||
Get(u+"/*", serverStaticRouter)
|
|
||||||
}
|
|
||||||
if EnableDocs {
|
if EnableDocs {
|
||||||
Get("/docs", serverDocs)
|
Get("/docs", serverDocs)
|
||||||
Get("/docs/*", serverDocs)
|
Get("/docs/*", serverDocs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//init mime
|
||||||
|
AddAPPStartHook(initMime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function is for test package init
|
// this function is for test package init
|
||||||
@ -406,6 +425,4 @@ func TestBeegoInit(apppath string) {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
hooks = make([]hookfunc, 0)
|
hooks = make([]hookfunc, 0)
|
||||||
//init mime
|
|
||||||
AddAPPStartHook(initMime)
|
|
||||||
}
|
}
|
||||||
|
2
cache/README.md
vendored
2
cache/README.md
vendored
@ -22,7 +22,7 @@ First you must import it
|
|||||||
|
|
||||||
Then init a Cache (example with memory adapter)
|
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:
|
Use it like this:
|
||||||
|
|
||||||
|
53
cache/cache.go
vendored
53
cache/cache.go
vendored
@ -1,9 +1,33 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,7 +37,7 @@ import (
|
|||||||
// Cache interface contains all behaviors for cache adapter.
|
// Cache interface contains all behaviors for cache adapter.
|
||||||
// usage:
|
// usage:
|
||||||
// cache.Register("file",cache.NewFileCache()) // this operation is run in init method of file.go.
|
// 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)
|
// c.Put("key",value,3600)
|
||||||
// v := c.Get("key")
|
// v := c.Get("key")
|
||||||
//
|
//
|
||||||
@ -31,11 +55,11 @@ type Cache interface {
|
|||||||
Incr(key string) error
|
Incr(key string) error
|
||||||
// decrease cached int value by key, as a counter.
|
// decrease cached int value by key, as a counter.
|
||||||
Decr(key string) error
|
Decr(key string) error
|
||||||
// check cached value is existed or not.
|
// check if cached value exists or not.
|
||||||
IsExist(key string) bool
|
IsExist(key string) bool
|
||||||
// clear all cache.
|
// clear all cache.
|
||||||
ClearAll() error
|
ClearAll() error
|
||||||
// start gc routine via config string setting.
|
// start gc routine based on config string settings.
|
||||||
StartAndGC(config string) error
|
StartAndGC(config string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,23 +72,24 @@ func Register(name string, adapter Cache) {
|
|||||||
if adapter == nil {
|
if adapter == nil {
|
||||||
panic("cache: Register adapter is 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)
|
panic("cache: Register called twice for adapter " + name)
|
||||||
}
|
}
|
||||||
adapters[name] = adapter
|
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}.
|
// config need to be correct JSON as string: {"interval":360}.
|
||||||
// it will start gc automatically.
|
// 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]
|
adapter, ok := adapters[adapterName]
|
||||||
if !ok {
|
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)
|
err := adapter.StartAndGC(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
adapter = nil
|
||||||
}
|
}
|
||||||
return adapter, nil
|
return
|
||||||
}
|
}
|
||||||
|
18
cache/cache_test.go
vendored
18
cache/cache_test.go
vendored
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 cache
|
||||||
|
|
||||||
|
56
cache/conv.go
vendored
56
cache/conv.go
vendored
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 cache
|
||||||
|
|
||||||
@ -19,12 +27,11 @@ func GetString(v interface{}) string {
|
|||||||
case []byte:
|
case []byte:
|
||||||
return string(result)
|
return string(result)
|
||||||
default:
|
default:
|
||||||
if v == nil {
|
if v != nil {
|
||||||
return ""
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%v", result)
|
return fmt.Sprintf("%v", result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to int.
|
// convert interface to int.
|
||||||
@ -37,14 +44,11 @@ func GetInt(v interface{}) int {
|
|||||||
case int64:
|
case int64:
|
||||||
return int(result)
|
return int(result)
|
||||||
default:
|
default:
|
||||||
d := GetString(v)
|
if d := GetString(v); d != "" {
|
||||||
if d != "" {
|
value, _ := strconv.Atoi(d)
|
||||||
value, err := strconv.Atoi(d)
|
|
||||||
if err == nil {
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,12 +62,10 @@ func GetInt64(v interface{}) int64 {
|
|||||||
case int64:
|
case int64:
|
||||||
return result
|
return result
|
||||||
default:
|
default:
|
||||||
d := GetString(v)
|
|
||||||
if d != "" {
|
if d := GetString(v); d != "" {
|
||||||
result, err := strconv.ParseInt(d, 10, 64)
|
value, _ := strconv.ParseInt(d, 10, 64)
|
||||||
if err == nil {
|
return value
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@ -75,14 +77,11 @@ func GetFloat64(v interface{}) float64 {
|
|||||||
case float64:
|
case float64:
|
||||||
return result
|
return result
|
||||||
default:
|
default:
|
||||||
d := GetString(v)
|
if d := GetString(v); d != "" {
|
||||||
if d != "" {
|
value, _ := strconv.ParseFloat(d, 64)
|
||||||
value, err := strconv.ParseFloat(d, 64)
|
|
||||||
if err == nil {
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,12 +91,9 @@ func GetBool(v interface{}) bool {
|
|||||||
case bool:
|
case bool:
|
||||||
return result
|
return result
|
||||||
default:
|
default:
|
||||||
d := GetString(v)
|
if d := GetString(v); d != "" {
|
||||||
if d != "" {
|
value, _ := strconv.ParseBool(d)
|
||||||
result, err := strconv.ParseBool(d)
|
return value
|
||||||
if err == nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
18
cache/conv_test.go
vendored
18
cache/conv_test.go
vendored
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 cache
|
||||||
|
|
||||||
|
136
cache/file.go
vendored
136
cache/file.go
vendored
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 cache
|
||||||
|
|
||||||
@ -57,12 +65,10 @@ func NewFileCache() *FileCache {
|
|||||||
|
|
||||||
// Start and begin gc for file cache.
|
// Start and begin gc for file cache.
|
||||||
// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}
|
// 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
|
var cfg map[string]string
|
||||||
json.Unmarshal([]byte(config), &cfg)
|
json.Unmarshal([]byte(config), &cfg)
|
||||||
//fmt.Println(cfg)
|
|
||||||
//fmt.Println(config)
|
|
||||||
if _, ok := cfg["CachePath"]; !ok {
|
if _, ok := cfg["CachePath"]; !ok {
|
||||||
cfg["CachePath"] = FileCachePath
|
cfg["CachePath"] = FileCachePath
|
||||||
}
|
}
|
||||||
@ -75,69 +81,53 @@ func (this *FileCache) StartAndGC(config string) error {
|
|||||||
if _, ok := cfg["EmbedExpiry"]; !ok {
|
if _, ok := cfg["EmbedExpiry"]; !ok {
|
||||||
cfg["EmbedExpiry"] = strconv.FormatInt(FileCacheEmbedExpiry, 10)
|
cfg["EmbedExpiry"] = strconv.FormatInt(FileCacheEmbedExpiry, 10)
|
||||||
}
|
}
|
||||||
this.CachePath = cfg["CachePath"]
|
fc.CachePath = cfg["CachePath"]
|
||||||
this.FileSuffix = cfg["FileSuffix"]
|
fc.FileSuffix = cfg["FileSuffix"]
|
||||||
this.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
|
fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
|
||||||
this.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
|
fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
|
||||||
|
|
||||||
this.Init()
|
fc.Init()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init will make new dir for file cache if not exist.
|
// 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])
|
app := filepath.Dir(os.Args[0])
|
||||||
this.CachePath = filepath.Join(app, this.CachePath)
|
fc.CachePath = filepath.Join(app, fc.CachePath)
|
||||||
ok, err := exists(this.CachePath)
|
if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
|
||||||
if err != nil { // print error
|
_ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
|
||||||
//fmt.Println(err)
|
|
||||||
}
|
}
|
||||||
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.
|
// 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()
|
m := md5.New()
|
||||||
io.WriteString(m, key)
|
io.WriteString(m, key)
|
||||||
keyMd5 := hex.EncodeToString(m.Sum(nil))
|
keyMd5 := hex.EncodeToString(m.Sum(nil))
|
||||||
cachePath := this.CachePath
|
cachePath := fc.CachePath
|
||||||
//fmt.Println("cachepath : " , cachePath)
|
switch fc.DirectoryLevel {
|
||||||
//fmt.Println("md5" , keyMd5);
|
|
||||||
switch this.DirectoryLevel {
|
|
||||||
case 2:
|
case 2:
|
||||||
cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4])
|
cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4])
|
||||||
case 1:
|
case 1:
|
||||||
cachePath = filepath.Join(cachePath, keyMd5[0:2])
|
cachePath = filepath.Join(cachePath, keyMd5[0:2])
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, err := exists(cachePath)
|
if ok, _ := exists(cachePath); !ok { // todo : error handle
|
||||||
if err != nil {
|
_ = os.MkdirAll(cachePath, os.ModePerm) // todo : error handle
|
||||||
//fmt.Println(err)
|
|
||||||
}
|
}
|
||||||
if !ok {
|
|
||||||
if err = os.MkdirAll(cachePath, os.ModePerm); err != nil {
|
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix))
|
||||||
//fmt.Println(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, this.FileSuffix))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get value from file cache.
|
// Get value from file cache.
|
||||||
// if non-exist or expired, return empty string.
|
// if non-exist or expired, return empty string.
|
||||||
func (this *FileCache) Get(key string) interface{} {
|
func (fc *FileCache) Get(key string) interface{} {
|
||||||
filename := this.getCacheFileName(key)
|
fileData, err := File_get_contents(fc.getCacheFileName(key))
|
||||||
filedata, err := File_get_contents(filename)
|
|
||||||
//fmt.Println("get length:" , len(filedata));
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
var to FileCacheItem
|
var to FileCacheItem
|
||||||
Gob_decode(filedata, &to)
|
Gob_decode(fileData, &to)
|
||||||
if to.Expired < time.Now().Unix() {
|
if to.Expired < time.Now().Unix() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -147,12 +137,10 @@ func (this *FileCache) Get(key string) interface{} {
|
|||||||
// Put value into file cache.
|
// Put value into file cache.
|
||||||
// timeout means how long to keep this file, unit of ms.
|
// timeout means how long to keep this file, unit of ms.
|
||||||
// if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever.
|
// 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)
|
gob.Register(val)
|
||||||
|
|
||||||
filename := this.getCacheFileName(key)
|
item := FileCacheItem{Data: val}
|
||||||
var item FileCacheItem
|
|
||||||
item.Data = val
|
|
||||||
if timeout == FileCacheEmbedExpiry {
|
if timeout == FileCacheEmbedExpiry {
|
||||||
item.Expired = time.Now().Unix() + (86400 * 365 * 10) // ten years
|
item.Expired = time.Now().Unix() + (86400 * 365 * 10) // ten years
|
||||||
} else {
|
} else {
|
||||||
@ -163,13 +151,12 @@ func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = File_put_contents(filename, data)
|
return File_put_contents(fc.getCacheFileName(key), data)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete file cache value.
|
// Delete file cache value.
|
||||||
func (this *FileCache) Delete(key string) error {
|
func (fc *FileCache) Delete(key string) error {
|
||||||
filename := this.getCacheFileName(key)
|
filename := fc.getCacheFileName(key)
|
||||||
if ok, _ := exists(filename); ok {
|
if ok, _ := exists(filename); ok {
|
||||||
return os.Remove(filename)
|
return os.Remove(filename)
|
||||||
}
|
}
|
||||||
@ -177,44 +164,41 @@ func (this *FileCache) Delete(key string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Increase cached int value.
|
// Increase cached int value.
|
||||||
// this value is saving forever unless Delete.
|
// fc value is saving forever unless Delete.
|
||||||
func (this *FileCache) Incr(key string) error {
|
func (fc *FileCache) Incr(key string) error {
|
||||||
data := this.Get(key)
|
data := fc.Get(key)
|
||||||
var incr int
|
var incr int
|
||||||
//fmt.Println(reflect.TypeOf(data).Name())
|
|
||||||
if reflect.TypeOf(data).Name() != "int" {
|
if reflect.TypeOf(data).Name() != "int" {
|
||||||
incr = 0
|
incr = 0
|
||||||
} else {
|
} else {
|
||||||
incr = data.(int) + 1
|
incr = data.(int) + 1
|
||||||
}
|
}
|
||||||
this.Put(key, incr, FileCacheEmbedExpiry)
|
fc.Put(key, incr, FileCacheEmbedExpiry)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrease cached int value.
|
// Decrease cached int value.
|
||||||
func (this *FileCache) Decr(key string) error {
|
func (fc *FileCache) Decr(key string) error {
|
||||||
data := this.Get(key)
|
data := fc.Get(key)
|
||||||
var decr int
|
var decr int
|
||||||
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
|
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
|
||||||
decr = 0
|
decr = 0
|
||||||
} else {
|
} else {
|
||||||
decr = data.(int) - 1
|
decr = data.(int) - 1
|
||||||
}
|
}
|
||||||
this.Put(key, decr, FileCacheEmbedExpiry)
|
fc.Put(key, decr, FileCacheEmbedExpiry)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check value is exist.
|
// Check value is exist.
|
||||||
func (this *FileCache) IsExist(key string) bool {
|
func (fc *FileCache) IsExist(key string) bool {
|
||||||
filename := this.getCacheFileName(key)
|
ret, _ := exists(fc.getCacheFileName(key))
|
||||||
ret, _ := exists(filename)
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean cached files.
|
// Clean cached files.
|
||||||
// not implemented.
|
// not implemented.
|
||||||
func (this *FileCache) ClearAll() error {
|
func (fc *FileCache) ClearAll() error {
|
||||||
//this.CachePath
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,22 +216,22 @@ func exists(path string) (bool, error) {
|
|||||||
|
|
||||||
// Get bytes to file.
|
// Get bytes to file.
|
||||||
// if non-exist, create this file.
|
// if non-exist, create this file.
|
||||||
func File_get_contents(filename string) ([]byte, error) {
|
func File_get_contents(filename string) (data []byte, e error) {
|
||||||
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
f, e := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return []byte(""), err
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
stat, err := f.Stat()
|
stat, e := f.Stat()
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return []byte(""), err
|
return
|
||||||
}
|
}
|
||||||
data := make([]byte, stat.Size())
|
data = make([]byte, stat.Size())
|
||||||
result, err := f.Read(data)
|
result, e := f.Read(data)
|
||||||
if int64(result) == stat.Size() {
|
if e != nil || int64(result) != stat.Size() {
|
||||||
return data, err
|
return nil, e
|
||||||
}
|
}
|
||||||
return []byte(""), err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put bytes to file.
|
// Put bytes to file.
|
||||||
|
147
cache/memcache/memcache.go
vendored
147
cache/memcache/memcache.go
vendored
@ -1,24 +1,48 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/memcache"
|
"github.com/bradfitz/gomemcache/memcache"
|
||||||
|
|
||||||
"github.com/astaxie/beego/cache"
|
"github.com/astaxie/beego/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Memcache adapter.
|
// Memcache adapter.
|
||||||
type MemcacheCache struct {
|
type MemcacheCache struct {
|
||||||
c *memcache.Connection
|
conn *memcache.Client
|
||||||
conninfo string
|
conninfo []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new memcache adapter.
|
// create new memcache adapter.
|
||||||
@ -28,32 +52,21 @@ func NewMemCache() *MemcacheCache {
|
|||||||
|
|
||||||
// get value from memcache.
|
// get value from memcache.
|
||||||
func (rc *MemcacheCache) Get(key string) interface{} {
|
func (rc *MemcacheCache) Get(key string) interface{} {
|
||||||
if rc.c == nil {
|
if rc.conn == nil {
|
||||||
var err error
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v, err := rc.c.Get(key)
|
if item, err := rc.conn.Get(key); err == nil {
|
||||||
if err != nil {
|
return string(item.Value)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var contain interface{}
|
|
||||||
if len(v) > 0 {
|
|
||||||
contain = string(v[0].Value)
|
|
||||||
} else {
|
|
||||||
contain = nil
|
|
||||||
}
|
|
||||||
return contain
|
|
||||||
}
|
|
||||||
|
|
||||||
// put value to memcache. only support string.
|
// put value to memcache. only support string.
|
||||||
func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
|
func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
|
||||||
if rc.c == nil {
|
if rc.conn == nil {
|
||||||
var err error
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,69 +74,64 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("val must string")
|
return errors.New("val must string")
|
||||||
}
|
}
|
||||||
stored, err := rc.c.Set(key, 0, uint64(timeout), []byte(v))
|
item := memcache.Item{Key: key, Value: []byte(v), Expiration: int32(timeout)}
|
||||||
if err == nil && stored == false {
|
return rc.conn.Set(&item)
|
||||||
return errors.New("stored fail")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete value in memcache.
|
// delete value in memcache.
|
||||||
func (rc *MemcacheCache) Delete(key string) error {
|
func (rc *MemcacheCache) Delete(key string) error {
|
||||||
if rc.c == nil {
|
if rc.conn == nil {
|
||||||
var err error
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := rc.c.Delete(key)
|
return rc.conn.Delete(key)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Not Support]
|
|
||||||
// increase counter.
|
// increase counter.
|
||||||
func (rc *MemcacheCache) Incr(key string) error {
|
func (rc *MemcacheCache) Incr(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.Increment(key, 1)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Not Support]
|
|
||||||
// decrease counter.
|
// decrease counter.
|
||||||
func (rc *MemcacheCache) Decr(key string) error {
|
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.
|
// check value exists in memcache.
|
||||||
func (rc *MemcacheCache) IsExist(key string) bool {
|
func (rc *MemcacheCache) IsExist(key string) bool {
|
||||||
if rc.c == nil {
|
if rc.conn == nil {
|
||||||
var err error
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := rc.conn.Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
v, err := rc.c.Get(key)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(v) == 0 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// clear all cached in memcache.
|
// clear all cached in memcache.
|
||||||
func (rc *MemcacheCache) ClearAll() error {
|
func (rc *MemcacheCache) ClearAll() error {
|
||||||
if rc.c == nil {
|
if rc.conn == nil {
|
||||||
var err error
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := rc.c.FlushAll()
|
return rc.conn.FlushAll()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// start memcache adapter.
|
// start memcache adapter.
|
||||||
@ -135,24 +143,19 @@ func (rc *MemcacheCache) StartAndGC(config string) error {
|
|||||||
if _, ok := cf["conn"]; !ok {
|
if _, ok := cf["conn"]; !ok {
|
||||||
return errors.New("config has no conn key")
|
return errors.New("config has no conn key")
|
||||||
}
|
}
|
||||||
rc.conninfo = cf["conn"]
|
rc.conninfo = strings.Split(cf["conn"], ";")
|
||||||
var err error
|
if rc.conn == nil {
|
||||||
if rc.c != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
rc.c, err = rc.connectInit()
|
return err
|
||||||
if err != nil {
|
|
||||||
return errors.New("dial tcp conn error")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect to memcache and keep the connection.
|
// connect to memcache and keep the connection.
|
||||||
func (rc *MemcacheCache) connectInit() (*memcache.Connection, error) {
|
func (rc *MemcacheCache) connectInit() error {
|
||||||
c, err := memcache.Connect(rc.conninfo)
|
rc.conn = memcache.New(rc.conninfo...)
|
||||||
if err != nil {
|
return nil
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
34
cache/memory.go
vendored
34
cache/memory.go
vendored
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 cache
|
||||||
|
|
||||||
@ -46,28 +54,26 @@ func NewMemoryCache() *MemoryCache {
|
|||||||
func (bc *MemoryCache) Get(name string) interface{} {
|
func (bc *MemoryCache) Get(name string) interface{} {
|
||||||
bc.lock.RLock()
|
bc.lock.RLock()
|
||||||
defer bc.lock.RUnlock()
|
defer bc.lock.RUnlock()
|
||||||
itm, ok := bc.items[name]
|
if itm, ok := bc.items[name]; ok {
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired {
|
if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired {
|
||||||
go bc.Delete(name)
|
go bc.Delete(name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return itm.val
|
return itm.val
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Put cache to memory.
|
// Put cache to memory.
|
||||||
// if expired is 0, it will be cleaned by next gc operation ( default gc clock is 1 minute).
|
// if expired is 0, it will be cleaned by next gc operation ( default gc clock is 1 minute).
|
||||||
func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error {
|
func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error {
|
||||||
bc.lock.Lock()
|
bc.lock.Lock()
|
||||||
defer bc.lock.Unlock()
|
defer bc.lock.Unlock()
|
||||||
t := MemoryItem{
|
bc.items[name] = &MemoryItem{
|
||||||
val: value,
|
val: value,
|
||||||
Lastaccess: time.Now(),
|
Lastaccess: time.Now(),
|
||||||
expired: expired,
|
expired: expired,
|
||||||
}
|
}
|
||||||
bc.items[name] = &t
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +85,7 @@ func (bc *MemoryCache) Delete(name string) error {
|
|||||||
return errors.New("key not exist")
|
return errors.New("key not exist")
|
||||||
}
|
}
|
||||||
delete(bc.items, name)
|
delete(bc.items, name)
|
||||||
_, valid := bc.items[name]
|
if _, ok := bc.items[name]; ok {
|
||||||
if valid {
|
|
||||||
return errors.New("delete key error")
|
return errors.New("delete key error")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -211,8 +216,7 @@ func (bc *MemoryCache) item_expired(name string) bool {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
sec := time.Now().Unix() - itm.Lastaccess.Unix()
|
if time.Now().Unix()-itm.Lastaccess.Unix() >= itm.expired {
|
||||||
if sec >= itm.expired {
|
|
||||||
delete(bc.items, name)
|
delete(bc.items, name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
104
cache/redis/redis.go
vendored
104
cache/redis/redis.go
vendored
@ -1,17 +1,40 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beego/redigo/redis"
|
"github.com/garyburd/redigo/redis"
|
||||||
|
|
||||||
"github.com/astaxie/beego/cache"
|
"github.com/astaxie/beego/cache"
|
||||||
)
|
)
|
||||||
@ -43,52 +66,74 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa
|
|||||||
|
|
||||||
// Get cache from redis.
|
// Get cache from redis.
|
||||||
func (rc *RedisCache) Get(key string) interface{} {
|
func (rc *RedisCache) Get(key string) interface{} {
|
||||||
v, err := rc.do("HGET", rc.key, key)
|
if v, err := rc.do("GET", key); err == nil {
|
||||||
if err != nil {
|
return v
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return v
|
// put cache to redis.
|
||||||
|
func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
|
||||||
|
var err error
|
||||||
|
if _, err = rc.do("SET", key, val); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// put cache to redis.
|
if _, err = rc.do("HSET", rc.key, key, true); err != nil {
|
||||||
// timeout is ignored.
|
return err
|
||||||
func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
|
}
|
||||||
_, err := rc.do("HSET", rc.key, key, val)
|
_, err = rc.do("EXPIRE", key, timeout)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete cache in redis.
|
// delete cache in redis.
|
||||||
func (rc *RedisCache) Delete(key string) error {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check cache exist in redis.
|
// check cache's existence in redis.
|
||||||
func (rc *RedisCache) IsExist(key string) bool {
|
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 {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if v == false {
|
||||||
|
if _, err = rc.do("HDEL", rc.key, key); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase counter in redis.
|
// increase counter in redis.
|
||||||
func (rc *RedisCache) Incr(key string) error {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease counter in redis.
|
// decrease counter in redis.
|
||||||
func (rc *RedisCache) Decr(key string) error {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean all cache in redis. delete this redis collection.
|
// clean all cache in redis. delete this redis collection.
|
||||||
func (rc *RedisCache) ClearAll() error {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,26 +159,21 @@ func (rc *RedisCache) StartAndGC(config string) error {
|
|||||||
|
|
||||||
c := rc.p.Get()
|
c := rc.p.Get()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
if err := c.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return c.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect to redis.
|
// connect to redis.
|
||||||
func (rc *RedisCache) connectInit() {
|
func (rc *RedisCache) connectInit() {
|
||||||
|
dialFunc := func() (c redis.Conn, err error) {
|
||||||
|
c, err = redis.Dial("tcp", rc.conninfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
// initialize a new pool
|
// initialize a new pool
|
||||||
rc.p = &redis.Pool{
|
rc.p = &redis.Pool{
|
||||||
MaxIdle: 3,
|
MaxIdle: 3,
|
||||||
IdleTimeout: 180 * time.Second,
|
IdleTimeout: 180 * time.Second,
|
||||||
Dial: func() (redis.Conn, error) {
|
Dial: dialFunc,
|
||||||
c, err := redis.Dial("tcp", rc.conninfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
cache/redis/redis_test.go
vendored
Normal file
85
cache/redis/redis_test.go
vendored
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
114
config.go
114
config.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
@ -52,6 +60,7 @@ var (
|
|||||||
SessionHashKey string // session hash salt string.
|
SessionHashKey string // session hash salt string.
|
||||||
SessionCookieLifeTime int // the life time of session id in cookie.
|
SessionCookieLifeTime int // the life time of session id in cookie.
|
||||||
SessionAutoSetCookie bool // auto setcookie
|
SessionAutoSetCookie bool // auto setcookie
|
||||||
|
SessionDomain string // the cookie domain default is empty
|
||||||
UseFcgi bool
|
UseFcgi bool
|
||||||
MaxMemory int64
|
MaxMemory int64
|
||||||
EnableGzip bool // flag of enable gzip
|
EnableGzip bool // flag of enable gzip
|
||||||
@ -180,147 +189,147 @@ func ParseConfig() (err error) {
|
|||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if v, err := getConfig("string", "HttpAddr"); err == nil {
|
if v, err := GetConfig("string", "HttpAddr"); err == nil {
|
||||||
HttpAddr = v.(string)
|
HttpAddr = v.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := getConfig("int", "HttpPort"); err == nil {
|
if v, err := GetConfig("int", "HttpPort"); err == nil {
|
||||||
HttpPort = v.(int)
|
HttpPort = v.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := getConfig("bool", "EnableHttpListen"); err == nil {
|
if v, err := GetConfig("bool", "EnableHttpListen"); err == nil {
|
||||||
EnableHttpListen = v.(bool)
|
EnableHttpListen = v.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxmemory, err := getConfig("int64", "MaxMemory"); err == nil {
|
if maxmemory, err := GetConfig("int64", "MaxMemory"); err == nil {
|
||||||
MaxMemory = maxmemory.(int64)
|
MaxMemory = maxmemory.(int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
if appname, _ := getConfig("string", "AppName"); appname != "" {
|
if appname, _ := GetConfig("string", "AppName"); appname != "" {
|
||||||
AppName = appname.(string)
|
AppName = appname.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if runmode, _ := getConfig("string", "RunMode"); runmode != "" {
|
if runmode, _ := GetConfig("string", "RunMode"); runmode != "" {
|
||||||
RunMode = runmode.(string)
|
RunMode = runmode.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if autorender, err := getConfig("bool", "AutoRender"); err == nil {
|
if autorender, err := GetConfig("bool", "AutoRender"); err == nil {
|
||||||
AutoRender = autorender.(bool)
|
AutoRender = autorender.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if autorecover, err := getConfig("bool", "RecoverPanic"); err == nil {
|
if autorecover, err := GetConfig("bool", "RecoverPanic"); err == nil {
|
||||||
RecoverPanic = autorecover.(bool)
|
RecoverPanic = autorecover.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if views, _ := getConfig("string", "ViewsPath"); views != "" {
|
if views, _ := GetConfig("string", "ViewsPath"); views != "" {
|
||||||
ViewsPath = views.(string)
|
ViewsPath = views.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessionon, err := getConfig("bool", "SessionOn"); err == nil {
|
if sessionon, err := GetConfig("bool", "SessionOn"); err == nil {
|
||||||
SessionOn = sessionon.(bool)
|
SessionOn = sessionon.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessProvider, _ := getConfig("string", "SessionProvider"); sessProvider != "" {
|
if sessProvider, _ := GetConfig("string", "SessionProvider"); sessProvider != "" {
|
||||||
SessionProvider = sessProvider.(string)
|
SessionProvider = sessProvider.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessName, _ := getConfig("string", "SessionName"); sessName != "" {
|
if sessName, _ := GetConfig("string", "SessionName"); sessName != "" {
|
||||||
SessionName = sessName.(string)
|
SessionName = sessName.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sesssavepath, _ := getConfig("string", "SessionSavePath"); sesssavepath != "" {
|
if sesssavepath, _ := GetConfig("string", "SessionSavePath"); sesssavepath != "" {
|
||||||
SessionSavePath = sesssavepath.(string)
|
SessionSavePath = sesssavepath.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sesshashfunc, _ := getConfig("string", "SessionHashFunc"); sesshashfunc != "" {
|
if sesshashfunc, _ := GetConfig("string", "SessionHashFunc"); sesshashfunc != "" {
|
||||||
SessionHashFunc = sesshashfunc.(string)
|
SessionHashFunc = sesshashfunc.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sesshashkey, _ := getConfig("string", "SessionHashKey"); sesshashkey != "" {
|
if sesshashkey, _ := GetConfig("string", "SessionHashKey"); sesshashkey != "" {
|
||||||
SessionHashKey = sesshashkey.(string)
|
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)
|
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)
|
SessionCookieLifeTime = sesscookielifetime.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if usefcgi, err := getConfig("bool", "UseFcgi"); err == nil {
|
if usefcgi, err := GetConfig("bool", "UseFcgi"); err == nil {
|
||||||
UseFcgi = usefcgi.(bool)
|
UseFcgi = usefcgi.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enablegzip, err := getConfig("bool", "EnableGzip"); err == nil {
|
if enablegzip, err := GetConfig("bool", "EnableGzip"); err == nil {
|
||||||
EnableGzip = enablegzip.(bool)
|
EnableGzip = enablegzip.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if directoryindex, err := getConfig("bool", "DirectoryIndex"); err == nil {
|
if directoryindex, err := GetConfig("bool", "DirectoryIndex"); err == nil {
|
||||||
DirectoryIndex = directoryindex.(bool)
|
DirectoryIndex = directoryindex.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if timeout, err := getConfig("int64", "HttpServerTimeOut"); err == nil {
|
if timeout, err := GetConfig("int64", "HttpServerTimeOut"); err == nil {
|
||||||
HttpServerTimeOut = timeout.(int64)
|
HttpServerTimeOut = timeout.(int64)
|
||||||
}
|
}
|
||||||
|
|
||||||
if errorsshow, err := getConfig("bool", "ErrorsShow"); err == nil {
|
if errorsshow, err := GetConfig("bool", "ErrorsShow"); err == nil {
|
||||||
ErrorsShow = errorsshow.(bool)
|
ErrorsShow = errorsshow.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if copyrequestbody, err := getConfig("bool", "CopyRequestBody"); err == nil {
|
if copyrequestbody, err := GetConfig("bool", "CopyRequestBody"); err == nil {
|
||||||
CopyRequestBody = copyrequestbody.(bool)
|
CopyRequestBody = copyrequestbody.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if xsrfkey, _ := getConfig("string", "XSRFKEY"); xsrfkey != "" {
|
if xsrfkey, _ := GetConfig("string", "XSRFKEY"); xsrfkey != "" {
|
||||||
XSRFKEY = xsrfkey.(string)
|
XSRFKEY = xsrfkey.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enablexsrf, err := getConfig("bool", "EnableXSRF"); err == nil {
|
if enablexsrf, err := GetConfig("bool", "EnableXSRF"); err == nil {
|
||||||
EnableXSRF = enablexsrf.(bool)
|
EnableXSRF = enablexsrf.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if expire, err := getConfig("int", "XSRFExpire"); err == nil {
|
if expire, err := GetConfig("int", "XSRFExpire"); err == nil {
|
||||||
XSRFExpire = expire.(int)
|
XSRFExpire = expire.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tplleft, _ := getConfig("string", "TemplateLeft"); tplleft != "" {
|
if tplleft, _ := GetConfig("string", "TemplateLeft"); tplleft != "" {
|
||||||
TemplateLeft = tplleft.(string)
|
TemplateLeft = tplleft.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tplright, _ := getConfig("string", "TemplateRight"); tplright != "" {
|
if tplright, _ := GetConfig("string", "TemplateRight"); tplright != "" {
|
||||||
TemplateRight = tplright.(string)
|
TemplateRight = tplright.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if httptls, err := getConfig("bool", "EnableHttpTLS"); err == nil {
|
if httptls, err := GetConfig("bool", "EnableHttpTLS"); err == nil {
|
||||||
EnableHttpTLS = httptls.(bool)
|
EnableHttpTLS = httptls.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if httpsport, err := getConfig("int", "HttpsPort"); err == nil {
|
if httpsport, err := GetConfig("int", "HttpsPort"); err == nil {
|
||||||
HttpsPort = httpsport.(int)
|
HttpsPort = httpsport.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if certfile, _ := getConfig("string", "HttpCertFile"); certfile != "" {
|
if certfile, _ := GetConfig("string", "HttpCertFile"); certfile != "" {
|
||||||
HttpCertFile = certfile.(string)
|
HttpCertFile = certfile.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyfile, _ := getConfig("string", "HttpKeyFile"); keyfile != "" {
|
if keyfile, _ := GetConfig("string", "HttpKeyFile"); keyfile != "" {
|
||||||
HttpKeyFile = keyfile.(string)
|
HttpKeyFile = keyfile.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if serverName, _ := getConfig("string", "BeegoServerName"); serverName != "" {
|
if serverName, _ := GetConfig("string", "BeegoServerName"); serverName != "" {
|
||||||
BeegoServerName = serverName.(string)
|
BeegoServerName = serverName.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flashname, _ := getConfig("string", "FlashName"); flashname != "" {
|
if flashname, _ := GetConfig("string", "FlashName"); flashname != "" {
|
||||||
FlashName = flashname.(string)
|
FlashName = flashname.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if flashseperator, _ := getConfig("string", "FlashSeperator"); flashseperator != "" {
|
if flashseperator, _ := GetConfig("string", "FlashSeperator"); flashseperator != "" {
|
||||||
FlashSeperator = flashseperator.(string)
|
FlashSeperator = flashseperator.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sd, _ := getConfig("string", "StaticDir"); sd != "" {
|
if sd, _ := GetConfig("string", "StaticDir"); sd != "" {
|
||||||
for k := range StaticDir {
|
for k := range StaticDir {
|
||||||
delete(StaticDir, k)
|
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), ",")
|
extensions := strings.Split(sgz.(string), ",")
|
||||||
if len(extensions) > 0 {
|
if len(extensions) > 0 {
|
||||||
StaticExtensionsToGzip = []string{}
|
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)
|
EnableAdmin = enableadmin.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if adminhttpaddr, _ := getConfig("string", "AdminHttpAddr"); adminhttpaddr != "" {
|
if adminhttpaddr, _ := GetConfig("string", "AdminHttpAddr"); adminhttpaddr != "" {
|
||||||
AdminHttpAddr = adminhttpaddr.(string)
|
AdminHttpAddr = adminhttpaddr.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if adminhttpport, err := getConfig("int", "AdminHttpPort"); err == nil {
|
if adminhttpport, err := GetConfig("int", "AdminHttpPort"); err == nil {
|
||||||
AdminHttpPort = adminhttpport.(int)
|
AdminHttpPort = adminhttpport.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enabledocs, err := getConfig("bool", "EnableDocs"); err == nil {
|
if enabledocs, err := GetConfig("bool", "EnableDocs"); err == nil {
|
||||||
EnableDocs = enabledocs.(bool)
|
EnableDocs = enabledocs.(bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
switch typ {
|
||||||
case "string":
|
case "string":
|
||||||
v := AppConfig.String(RunMode + "::" + key)
|
v := AppConfig.String(RunMode + "::" + key)
|
||||||
|
@ -1,9 +1,44 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -19,12 +54,21 @@ type ConfigContainer interface {
|
|||||||
Int64(key string) (int64, error)
|
Int64(key string) (int64, error)
|
||||||
Bool(key string) (bool, error)
|
Bool(key string) (bool, error)
|
||||||
Float(key string) (float64, 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)
|
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.
|
// Config is the adapter interface for parsing config file to get raw data to ConfigContainer.
|
||||||
type Config interface {
|
type Config interface {
|
||||||
Parse(key string) (ConfigContainer, error)
|
Parse(key string) (ConfigContainer, error)
|
||||||
|
ParseData(data []byte) (ConfigContainer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var adapters = make(map[string]Config)
|
var adapters = make(map[string]Config)
|
||||||
@ -36,7 +80,7 @@ func Register(name string, adapter Config) {
|
|||||||
if adapter == nil {
|
if adapter == nil {
|
||||||
panic("config: Register adapter is 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)
|
panic("config: Register called twice for adapter " + name)
|
||||||
}
|
}
|
||||||
adapters[name] = adapter
|
adapters[name] = adapter
|
||||||
@ -51,3 +95,13 @@ func NewConfig(adapterName, fileaname string) (ConfigContainer, error) {
|
|||||||
}
|
}
|
||||||
return adapter.Parse(fileaname)
|
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)
|
||||||
|
}
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 config
|
||||||
|
|
||||||
@ -17,13 +25,11 @@ type fakeConfigContainer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeConfigContainer) getData(key string) string {
|
func (c *fakeConfigContainer) getData(key string) string {
|
||||||
key = strings.ToLower(key)
|
return c.data[strings.ToLower(key)]
|
||||||
return c.data[key]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeConfigContainer) Set(key, val string) error {
|
func (c *fakeConfigContainer) Set(key, val string) error {
|
||||||
key = strings.ToLower(key)
|
c.data[strings.ToLower(key)] = val
|
||||||
c.data[key] = val
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,34 +37,89 @@ func (c *fakeConfigContainer) String(key string) string {
|
|||||||
return c.getData(key)
|
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 {
|
func (c *fakeConfigContainer) Strings(key string) []string {
|
||||||
return strings.Split(c.getData(key), ";")
|
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) {
|
func (c *fakeConfigContainer) Int(key string) (int, error) {
|
||||||
return strconv.Atoi(c.getData(key))
|
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) {
|
func (c *fakeConfigContainer) Int64(key string) (int64, error) {
|
||||||
return strconv.ParseInt(c.getData(key), 10, 64)
|
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) {
|
func (c *fakeConfigContainer) Bool(key string) (bool, error) {
|
||||||
return strconv.ParseBool(c.getData(key))
|
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) {
|
func (c *fakeConfigContainer) Float(key string) (float64, error) {
|
||||||
return strconv.ParseFloat(c.getData(key), 64)
|
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) {
|
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
|
||||||
key = strings.ToLower(key)
|
if v, ok := c.data[strings.ToLower(key)]; ok {
|
||||||
if v, ok := c.data[key]; ok {
|
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("key not find")
|
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)
|
var _ ConfigContainer = new(fakeConfigContainer)
|
||||||
|
|
||||||
func NewFakeConfig() ConfigContainer {
|
func NewFakeConfig() ConfigContainer {
|
||||||
|
224
config/ini.go
224
config/ini.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 config
|
||||||
|
|
||||||
@ -10,11 +18,15 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,6 +39,7 @@ var (
|
|||||||
bDQuote = []byte{'"'} // quote signal
|
bDQuote = []byte{'"'} // quote signal
|
||||||
sectionStart = []byte{'['} // section start signal
|
sectionStart = []byte{'['} // section start signal
|
||||||
sectionEnd = []byte{']'} // section end signal
|
sectionEnd = []byte{']'} // section end signal
|
||||||
|
lineBreak = "\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IniConfig implements Config to parse ini file.
|
// 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) {
|
if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) {
|
||||||
section = string(line[1 : len(line)-1])
|
section = strings.ToLower(string(line[1 : len(line)-1])) // section name case insensitive
|
||||||
section = strings.ToLower(section) // section name case insensitive
|
|
||||||
if comment.Len() > 0 {
|
if comment.Len() > 0 {
|
||||||
cfg.sectionComment[section] = comment.String()
|
cfg.sectionComment[section] = comment.String()
|
||||||
comment.Reset()
|
comment.Reset()
|
||||||
@ -89,67 +101,124 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
|||||||
if _, ok := cfg.data[section]; !ok {
|
if _, ok := cfg.data[section]; !ok {
|
||||||
cfg.data[section] = make(map[string]string)
|
cfg.data[section] = make(map[string]string)
|
||||||
}
|
}
|
||||||
} else {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := cfg.data[section]; !ok {
|
if _, ok := cfg.data[section]; !ok {
|
||||||
cfg.data[section] = make(map[string]string)
|
cfg.data[section] = make(map[string]string)
|
||||||
}
|
}
|
||||||
keyval := bytes.SplitN(line, bEqual, 2)
|
keyValue := bytes.SplitN(line, bEqual, 2)
|
||||||
val := bytes.TrimSpace(keyval[1])
|
val := bytes.TrimSpace(keyValue[1])
|
||||||
if bytes.HasPrefix(val, bDQuote) {
|
if bytes.HasPrefix(val, bDQuote) {
|
||||||
val = bytes.Trim(val, `"`)
|
val = bytes.Trim(val, `"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
key := string(bytes.TrimSpace(keyval[0])) // key name case insensitive
|
key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive
|
||||||
key = strings.ToLower(key)
|
key = strings.ToLower(key)
|
||||||
cfg.data[section][key] = string(val)
|
cfg.data[section][key] = string(val)
|
||||||
if comment.Len() > 0 {
|
if comment.Len() > 0 {
|
||||||
cfg.keycomment[section+"."+key] = comment.String()
|
cfg.keyComment[section+"."+key] = comment.String()
|
||||||
comment.Reset()
|
comment.Reset()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return cfg, nil
|
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.
|
// A Config represents the ini configuration.
|
||||||
// When set and get value, support key as section:name type.
|
// When set and get value, support key as section:name type.
|
||||||
type IniConfigContainer struct {
|
type IniConfigContainer struct {
|
||||||
filename string
|
filename string
|
||||||
data map[string]map[string]string // section=> key:val
|
data map[string]map[string]string // section=> key:val
|
||||||
sectionComment map[string]string // section : comment
|
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
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool returns the boolean value for a given key.
|
// Bool returns the boolean value for a given key.
|
||||||
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
||||||
key = strings.ToLower(key)
|
return strconv.ParseBool(c.getdata(strings.ToLower(key)))
|
||||||
return strconv.ParseBool(c.getdata(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.
|
// Int returns the integer value for a given key.
|
||||||
func (c *IniConfigContainer) Int(key string) (int, error) {
|
func (c *IniConfigContainer) Int(key string) (int, error) {
|
||||||
key = strings.ToLower(key)
|
return strconv.Atoi(c.getdata(strings.ToLower(key)))
|
||||||
return strconv.Atoi(c.getdata(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.
|
// Int64 returns the int64 value for a given key.
|
||||||
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
||||||
key = strings.ToLower(key)
|
return strconv.ParseInt(c.getdata(strings.ToLower(key)), 10, 64)
|
||||||
return strconv.ParseInt(c.getdata(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.
|
// Float returns the float value for a given key.
|
||||||
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
||||||
key = strings.ToLower(key)
|
return strconv.ParseFloat(c.getdata(strings.ToLower(key)), 64)
|
||||||
return strconv.ParseFloat(c.getdata(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.
|
// String returns the string value for a given key.
|
||||||
func (c *IniConfigContainer) String(key string) string {
|
func (c *IniConfigContainer) String(key string) string {
|
||||||
key = strings.ToLower(key)
|
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.
|
// 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), ";")
|
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.
|
// WriteValue writes a new value for key.
|
||||||
// if write to one section, the key need be "section::key".
|
// if write to one section, the key need be "section::key".
|
||||||
// if the section is not existed, it panics.
|
// 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")
|
return errors.New("key is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
var section, k string
|
var (
|
||||||
key = strings.ToLower(key)
|
section, k string
|
||||||
sectionkey := strings.Split(key, "::")
|
sectionKey []string = strings.Split(key, "::")
|
||||||
if len(sectionkey) >= 2 {
|
)
|
||||||
section = sectionkey[0]
|
|
||||||
k = sectionkey[1]
|
if len(sectionKey) >= 2 {
|
||||||
|
section = sectionKey[0]
|
||||||
|
k = sectionKey[1]
|
||||||
} else {
|
} else {
|
||||||
section = DEFAULT_SECTION
|
section = DEFAULT_SECTION
|
||||||
k = sectionkey[0]
|
k = sectionKey[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := c.data[section]; !ok {
|
if _, ok := c.data[section]; !ok {
|
||||||
c.data[section] = make(map[string]string)
|
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.
|
// DIY returns the raw value by a given key.
|
||||||
func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
|
func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
key = strings.ToLower(key)
|
if v, ok := c.data[strings.ToLower(key)]; ok {
|
||||||
if v, ok := c.data[key]; ok {
|
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return v, errors.New("key not find")
|
return v, errors.New("key not find")
|
||||||
@ -201,18 +344,19 @@ func (c *IniConfigContainer) getdata(key string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var section, k string
|
var (
|
||||||
key = strings.ToLower(key)
|
section, k string
|
||||||
sectionkey := strings.Split(key, "::")
|
sectionKey []string = strings.Split(key, "::")
|
||||||
if len(sectionkey) >= 2 {
|
)
|
||||||
section = sectionkey[0]
|
if len(sectionKey) >= 2 {
|
||||||
k = sectionkey[1]
|
section = sectionKey[0]
|
||||||
|
k = sectionKey[1]
|
||||||
} else {
|
} else {
|
||||||
section = DEFAULT_SECTION
|
section = DEFAULT_SECTION
|
||||||
k = sectionkey[0]
|
k = sectionKey[0]
|
||||||
}
|
}
|
||||||
if v, ok := c.data[section]; ok {
|
if v, ok := c.data[section]; ok {
|
||||||
if vv, o := v[k]; o {
|
if vv, ok := v[k]; ok {
|
||||||
return vv
|
return vv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 config
|
||||||
|
|
||||||
|
167
config/json.go
167
config/json.go
@ -1,18 +1,29 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JsonConfig is a json config parser and implements Config interface.
|
// 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
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
x := &JsonConfigContainer{
|
|
||||||
data: make(map[string]interface{}),
|
|
||||||
}
|
|
||||||
content, err := ioutil.ReadAll(file)
|
content, err := ioutil.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
x := &JsonConfigContainer{
|
||||||
|
data: make(map[string]interface{}),
|
||||||
|
}
|
||||||
err = json.Unmarshal(content, &x.data)
|
err = json.Unmarshal(content, &x.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var wrappingArray []interface{}
|
var wrappingArray []interface{}
|
||||||
@ -45,6 +56,16 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
|
|||||||
return x, nil
|
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.
|
// A Config represents the json configuration.
|
||||||
// Only when get value, support key as section:name type.
|
// Only when get value, support key as section:name type.
|
||||||
type JsonConfigContainer struct {
|
type JsonConfigContainer struct {
|
||||||
@ -54,71 +75,110 @@ type JsonConfigContainer struct {
|
|||||||
|
|
||||||
// Bool returns the boolean value for a given key.
|
// Bool returns the boolean value for a given key.
|
||||||
func (c *JsonConfigContainer) Bool(key string) (bool, error) {
|
func (c *JsonConfigContainer) Bool(key string) (bool, error) {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
if v, ok := val.(bool); ok {
|
if v, ok := val.(bool); ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
} else {
|
}
|
||||||
return false, errors.New("not bool value")
|
return false, errors.New("not bool value")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return false, errors.New("not exist key:" + key)
|
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 v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int returns the integer value for a given key.
|
// Int returns the integer value for a given key.
|
||||||
func (c *JsonConfigContainer) Int(key string) (int, error) {
|
func (c *JsonConfigContainer) Int(key string) (int, error) {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
if v, ok := val.(float64); ok {
|
if v, ok := val.(float64); ok {
|
||||||
return int(v), nil
|
return int(v), nil
|
||||||
} else {
|
}
|
||||||
return 0, errors.New("not int value")
|
return 0, errors.New("not int value")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return 0, errors.New("not exist key:" + key)
|
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 v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 returns the int64 value for a given key.
|
// Int64 returns the int64 value for a given key.
|
||||||
func (c *JsonConfigContainer) Int64(key string) (int64, error) {
|
func (c *JsonConfigContainer) Int64(key string) (int64, error) {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
if v, ok := val.(float64); ok {
|
if v, ok := val.(float64); ok {
|
||||||
return int64(v), nil
|
return int64(v), nil
|
||||||
} else {
|
}
|
||||||
return 0, errors.New("not int64 value")
|
return 0, errors.New("not int64 value")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return 0, errors.New("not exist key:" + key)
|
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 v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float returns the float value for a given key.
|
// Float returns the float value for a given key.
|
||||||
func (c *JsonConfigContainer) Float(key string) (float64, error) {
|
func (c *JsonConfigContainer) Float(key string) (float64, error) {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
if v, ok := val.(float64); ok {
|
if v, ok := val.(float64); ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
} else {
|
}
|
||||||
return 0.0, errors.New("not float64 value")
|
return 0.0, errors.New("not float64 value")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return 0.0, errors.New("not exist key:" + key)
|
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 v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string value for a given key.
|
// String returns the string value for a given key.
|
||||||
func (c *JsonConfigContainer) String(key string) string {
|
func (c *JsonConfigContainer) String(key string) string {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
if v, ok := val.(string); ok {
|
if v, ok := val.(string); ok {
|
||||||
return v
|
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 {
|
} else {
|
||||||
return ""
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +187,41 @@ func (c *JsonConfigContainer) Strings(key string) []string {
|
|||||||
return strings.Split(c.String(key), ";")
|
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.
|
// WriteValue writes a new value for key.
|
||||||
func (c *JsonConfigContainer) Set(key, val string) error {
|
func (c *JsonConfigContainer) Set(key, val string) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
@ -137,40 +232,38 @@ func (c *JsonConfigContainer) Set(key, val string) error {
|
|||||||
|
|
||||||
// DIY returns the raw value by a given key.
|
// DIY returns the raw value by a given key.
|
||||||
func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
|
func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
val := c.getdata(key)
|
val := c.getData(key)
|
||||||
if val != nil {
|
if val != nil {
|
||||||
return val, nil
|
return val, nil
|
||||||
} else {
|
|
||||||
return nil, errors.New("not exist key")
|
|
||||||
}
|
}
|
||||||
|
return nil, errors.New("not exist key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// section.key or key
|
// section.key or key
|
||||||
func (c *JsonConfigContainer) getdata(key string) interface{} {
|
func (c *JsonConfigContainer) getData(key string) interface{} {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
defer c.RUnlock()
|
defer c.RUnlock()
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
sectionkey := strings.Split(key, "::")
|
sectionKey := strings.Split(key, "::")
|
||||||
if len(sectionkey) >= 2 {
|
if len(sectionKey) >= 2 {
|
||||||
cruval, ok := c.data[sectionkey[0]]
|
curValue, ok := c.data[sectionKey[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, key := range sectionkey[1:] {
|
for _, key := range sectionKey[1:] {
|
||||||
if v, ok := cruval.(map[string]interface{}); !ok {
|
if v, ok := curValue.(map[string]interface{}); ok {
|
||||||
return nil
|
if curValue, ok = v[key]; !ok {
|
||||||
} else if cruval, ok = v[key]; !ok {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cruval
|
}
|
||||||
} else {
|
return curValue
|
||||||
|
}
|
||||||
if v, ok := c.data[key]; ok {
|
if v, ok := c.data[key]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 config
|
||||||
|
|
||||||
@ -61,11 +69,11 @@ func TestJsonStartsWithArray(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
rootArray, err := jsonconf.DIY("rootArray")
|
rootArray, err := jsonconf.DIY("rootArray")
|
||||||
if (err != nil) {
|
if err != nil {
|
||||||
t.Error("array does not exist as element")
|
t.Error("array does not exist as element")
|
||||||
}
|
}
|
||||||
rootArrayCasted := rootArray.([]interface{})
|
rootArrayCasted := rootArray.([]interface{})
|
||||||
if (rootArrayCasted == nil) {
|
if rootArrayCasted == nil {
|
||||||
t.Error("array from root is nil")
|
t.Error("array from root is nil")
|
||||||
} else {
|
} else {
|
||||||
elem := rootArrayCasted[0].(map[string]interface{})
|
elem := rootArrayCasted[0].(map[string]interface{})
|
||||||
|
@ -1,18 +1,45 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/config"
|
"github.com/astaxie/beego/config"
|
||||||
"github.com/beego/x2j"
|
"github.com/beego/x2j"
|
||||||
@ -21,31 +48,41 @@ import (
|
|||||||
// XmlConfig is a xml config parser and implements Config interface.
|
// XmlConfig is a xml config parser and implements Config interface.
|
||||||
// xml configurations should be included in <config></config> tag.
|
// xml configurations should be included in <config></config> tag.
|
||||||
// only support key/value pair as <key>value</key> as each item.
|
// only support key/value pair as <key>value</key> as each item.
|
||||||
type XMLConfig struct {
|
type XMLConfig struct{}
|
||||||
}
|
|
||||||
|
|
||||||
// Parse returns a ConfigContainer with parsed xml config map.
|
// 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)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
x := &XMLConfigContainer{
|
|
||||||
data: make(map[string]interface{}),
|
x := &XMLConfigContainer{data: make(map[string]interface{})}
|
||||||
}
|
|
||||||
content, err := ioutil.ReadAll(file)
|
content, err := ioutil.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := x2j.DocToMap(string(content))
|
d, err := x2j.DocToMap(string(content))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
x.data = d["config"].(map[string]interface{})
|
x.data = d["config"].(map[string]interface{})
|
||||||
return x, nil
|
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.
|
// A Config represents the xml configuration.
|
||||||
type XMLConfigContainer struct {
|
type XMLConfigContainer struct {
|
||||||
data map[string]interface{}
|
data map[string]interface{}
|
||||||
@ -57,21 +94,61 @@ func (c *XMLConfigContainer) Bool(key string) (bool, error) {
|
|||||||
return strconv.ParseBool(c.data[key].(string))
|
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.
|
// Int returns the integer value for a given key.
|
||||||
func (c *XMLConfigContainer) Int(key string) (int, error) {
|
func (c *XMLConfigContainer) Int(key string) (int, error) {
|
||||||
return strconv.Atoi(c.data[key].(string))
|
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.
|
// Int64 returns the int64 value for a given key.
|
||||||
func (c *XMLConfigContainer) Int64(key string) (int64, error) {
|
func (c *XMLConfigContainer) Int64(key string) (int64, error) {
|
||||||
return strconv.ParseInt(c.data[key].(string), 10, 64)
|
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.
|
// Float returns the float value for a given key.
|
||||||
func (c *XMLConfigContainer) Float(key string) (float64, error) {
|
func (c *XMLConfigContainer) Float(key string) (float64, error) {
|
||||||
return strconv.ParseFloat(c.data[key].(string), 64)
|
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.
|
// String returns the string value for a given key.
|
||||||
func (c *XMLConfigContainer) String(key string) string {
|
func (c *XMLConfigContainer) String(key string) string {
|
||||||
if v, ok := c.data[key].(string); ok {
|
if v, ok := c.data[key].(string); ok {
|
||||||
@ -80,11 +157,56 @@ func (c *XMLConfigContainer) String(key string) string {
|
|||||||
return ""
|
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.
|
// Strings returns the []string value for a given key.
|
||||||
func (c *XMLConfigContainer) Strings(key string) []string {
|
func (c *XMLConfigContainer) Strings(key string) []string {
|
||||||
return strings.Split(c.String(key), ";")
|
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.
|
// WriteValue writes a new value for key.
|
||||||
func (c *XMLConfigContainer) Set(key, val string) error {
|
func (c *XMLConfigContainer) Set(key, val string) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
@ -1,59 +1,92 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/config"
|
"github.com/astaxie/beego/config"
|
||||||
"github.com/beego/goyaml2"
|
"github.com/beego/goyaml2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// YAMLConfig is a yaml config parser and implements Config interface.
|
// 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.
|
// Parse returns a ConfigContainer with parsed yaml config map.
|
||||||
func (yaml *YAMLConfig) Parse(filename string) (config.ConfigContainer, error) {
|
func (yaml *YAMLConfig) Parse(filename string) (y config.ConfigContainer, err error) {
|
||||||
y := &YAMLConfigContainer{
|
|
||||||
data: make(map[string]interface{}),
|
|
||||||
}
|
|
||||||
cnf, err := ReadYmlReader(filename)
|
cnf, err := ReadYmlReader(filename)
|
||||||
if err != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
y.data = cnf
|
return yaml.Parse(tmpName)
|
||||||
return y, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read yaml file to map.
|
// Read yaml file to map.
|
||||||
// if json like, use json package, unless goyaml2 package.
|
// if json like, use json package, unless goyaml2 package.
|
||||||
func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
|
func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
|
||||||
err = nil
|
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
err = nil
|
|
||||||
buf, err := ioutil.ReadAll(f)
|
buf, err := ioutil.ReadAll(f)
|
||||||
if err != nil || len(buf) < 3 {
|
if err != nil || len(buf) < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(buf[0:1]) == "{" {
|
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)
|
err = json.Unmarshal(buf, &cnf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Println("It is Json Map")
|
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))
|
data, err := goyaml2.Read(bytes.NewBuffer(buf))
|
||||||
if _err != nil {
|
if err != nil {
|
||||||
log.Println("Goyaml2 ERR>", string(buf), _err)
|
log.Println("Goyaml2 ERR>", string(buf), err)
|
||||||
//err = goyaml.Unmarshal(buf, &cnf)
|
|
||||||
err = _err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _map == nil {
|
|
||||||
|
if data == nil {
|
||||||
log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf))
|
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 {
|
if !ok {
|
||||||
log.Println("Not a Map? >> ", string(buf), _map)
|
log.Println("Not a Map? >> ", string(buf), data)
|
||||||
cnf = nil
|
cnf = nil
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -93,6 +126,16 @@ func (c *YAMLConfigContainer) Bool(key string) (bool, error) {
|
|||||||
return false, errors.New("not bool value")
|
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.
|
// Int returns the integer value for a given key.
|
||||||
func (c *YAMLConfigContainer) Int(key string) (int, error) {
|
func (c *YAMLConfigContainer) Int(key string) (int, error) {
|
||||||
if v, ok := c.data[key].(int64); ok {
|
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")
|
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.
|
// Int64 returns the int64 value for a given key.
|
||||||
func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
|
func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
|
||||||
if v, ok := c.data[key].(int64); ok {
|
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")
|
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.
|
// Float returns the float value for a given key.
|
||||||
func (c *YAMLConfigContainer) Float(key string) (float64, error) {
|
func (c *YAMLConfigContainer) Float(key string) (float64, error) {
|
||||||
if v, ok := c.data[key].(float64); ok {
|
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")
|
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.
|
// String returns the string value for a given key.
|
||||||
func (c *YAMLConfigContainer) String(key string) string {
|
func (c *YAMLConfigContainer) String(key string) string {
|
||||||
if v, ok := c.data[key].(string); ok {
|
if v, ok := c.data[key].(string); ok {
|
||||||
@ -125,11 +198,52 @@ func (c *YAMLConfigContainer) String(key string) string {
|
|||||||
return ""
|
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.
|
// Strings returns the []string value for a given key.
|
||||||
func (c *YAMLConfigContainer) Strings(key string) []string {
|
func (c *YAMLConfigContainer) Strings(key string) []string {
|
||||||
return strings.Split(c.String(key), ";")
|
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.
|
// WriteValue writes a new value for key.
|
||||||
func (c *YAMLConfigContainer) Set(key, val string) error {
|
func (c *YAMLConfigContainer) Set(key, val string) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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 (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -1,9 +1,24 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -17,6 +32,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/middleware"
|
"github.com/astaxie/beego/middleware"
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
|
// Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
|
||||||
@ -26,20 +42,21 @@ type Context struct {
|
|||||||
Output *BeegoOutput
|
Output *BeegoOutput
|
||||||
Request *http.Request
|
Request *http.Request
|
||||||
ResponseWriter http.ResponseWriter
|
ResponseWriter http.ResponseWriter
|
||||||
|
_xsrf_token string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect does redirection to localurl with http header status code.
|
// Redirect does redirection to localurl with http header status code.
|
||||||
// It sends http response header directly.
|
// It sends http response header directly.
|
||||||
func (ctx *Context) Redirect(status int, localurl string) {
|
func (ctx *Context) Redirect(status int, localurl string) {
|
||||||
ctx.Output.Header("Location", localurl)
|
ctx.Output.Header("Location", localurl)
|
||||||
ctx.Output.SetStatus(status)
|
ctx.ResponseWriter.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abort stops this request.
|
// Abort stops this request.
|
||||||
// if middleware.ErrorMaps exists, panic body.
|
// if middleware.ErrorMaps exists, panic body.
|
||||||
// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string.
|
// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string.
|
||||||
func (ctx *Context) Abort(status int, 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.
|
// first panic from ErrorMaps, is is user defined error functions.
|
||||||
if _, ok := middleware.ErrorMaps[body]; ok {
|
if _, ok := middleware.ErrorMaps[body]; ok {
|
||||||
panic(body)
|
panic(body)
|
||||||
@ -58,7 +75,7 @@ func (ctx *Context) Abort(status int, body string) {
|
|||||||
// Write string to response body.
|
// Write string to response body.
|
||||||
// it sends response body.
|
// it sends response body.
|
||||||
func (ctx *Context) WriteString(content string) {
|
func (ctx *Context) WriteString(content string) {
|
||||||
ctx.Output.Body([]byte(content))
|
ctx.ResponseWriter.Write([]byte(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cookie from request by a given key.
|
// 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}, "|")
|
cookie := strings.Join([]string{vs, timestamp, sig}, "|")
|
||||||
ctx.Output.Cookie(name, cookie, others...)
|
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
|
||||||
|
}
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package context
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package context
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package context
|
||||||
|
|
||||||
@ -68,6 +76,14 @@ func (output *BeegoOutput) Body(content []byte) {
|
|||||||
} else {
|
} else {
|
||||||
output.Header("Content-Length", strconv.Itoa(len(content)))
|
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)
|
output_writer.Write(content)
|
||||||
switch output_writer.(type) {
|
switch output_writer.(type) {
|
||||||
case *gzip.Writer:
|
case *gzip.Writer:
|
||||||
@ -267,7 +283,6 @@ func (output *BeegoOutput) ContentType(ext string) {
|
|||||||
// SetStatus sets response status code.
|
// SetStatus sets response status code.
|
||||||
// It writes response header directly.
|
// It writes response header directly.
|
||||||
func (output *BeegoOutput) SetStatus(status int) {
|
func (output *BeegoOutput) SetStatus(status int) {
|
||||||
output.Context.ResponseWriter.WriteHeader(status)
|
|
||||||
output.Status = status
|
output.Status = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
@ -22,7 +30,6 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
"github.com/astaxie/beego/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//commonly used mime-types
|
//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.
|
// StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
|
||||||
func (c *Controller) StopRun() {
|
func (c *Controller) StopRun() {
|
||||||
panic(USERSTOPRUN)
|
panic(USERSTOPRUN)
|
||||||
@ -474,18 +486,13 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter
|
|||||||
// XsrfToken creates a xsrf token string and returns.
|
// XsrfToken creates a xsrf token string and returns.
|
||||||
func (c *Controller) XsrfToken() string {
|
func (c *Controller) XsrfToken() string {
|
||||||
if c._xsrf_token == "" {
|
if c._xsrf_token == "" {
|
||||||
token, ok := c.GetSecureCookie(XSRFKEY, "_xsrf")
|
|
||||||
if !ok {
|
|
||||||
var expire int64
|
var expire int64
|
||||||
if c.XSRFExpire > 0 {
|
if c.XSRFExpire > 0 {
|
||||||
expire = int64(c.XSRFExpire)
|
expire = int64(c.XSRFExpire)
|
||||||
} else {
|
} else {
|
||||||
expire = int64(XSRFExpire)
|
expire = int64(XSRFExpire)
|
||||||
}
|
}
|
||||||
token = string(utils.RandomCreateBytes(32))
|
c._xsrf_token = c.Ctx.XsrfToken(XSRFKEY, expire)
|
||||||
c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire)
|
|
||||||
}
|
|
||||||
c._xsrf_token = token
|
|
||||||
}
|
}
|
||||||
return c._xsrf_token
|
return c._xsrf_token
|
||||||
}
|
}
|
||||||
@ -497,19 +504,7 @@ func (c *Controller) CheckXsrfCookie() bool {
|
|||||||
if !c.EnableXSRF {
|
if !c.EnableXSRF {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
token := c.GetString("_xsrf")
|
return c.Ctx.CheckXsrfCookie()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XsrfFormHtml writes an input field contains xsrf token value.
|
// XsrfFormHtml writes an input field contains xsrf token value.
|
||||||
|
14
docs.go
14
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
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
// Beego (http://beego.me/)
|
// Beego (http://beego.me/)
|
||||||
|
|
||||||
// @description beego is an open-source, high-performance web framework for the Go programming language.
|
// @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
|
// @link http://github.com/astaxie/beego for the canonical source repository
|
||||||
|
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
||||||
|
|
||||||
// @authors astaxie
|
// @authors astaxie
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
18
filter.go
18
filter.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
18
flash.go
18
flash.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -1,9 +1,33 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package httplib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -52,41 +76,46 @@ func SetDefaultSetting(setting BeegoHttpSettings) {
|
|||||||
// Get returns *BeegoHttpRequest with GET method.
|
// Get returns *BeegoHttpRequest with GET method.
|
||||||
func Get(url string) *BeegoHttpRequest {
|
func Get(url string) *BeegoHttpRequest {
|
||||||
var req http.Request
|
var req http.Request
|
||||||
|
var resp http.Response
|
||||||
req.Method = "GET"
|
req.Method = "GET"
|
||||||
req.Header = http.Header{}
|
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.
|
// Post returns *BeegoHttpRequest with POST method.
|
||||||
func Post(url string) *BeegoHttpRequest {
|
func Post(url string) *BeegoHttpRequest {
|
||||||
var req http.Request
|
var req http.Request
|
||||||
|
var resp http.Response
|
||||||
req.Method = "POST"
|
req.Method = "POST"
|
||||||
req.Header = http.Header{}
|
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.
|
// Put returns *BeegoHttpRequest with PUT method.
|
||||||
func Put(url string) *BeegoHttpRequest {
|
func Put(url string) *BeegoHttpRequest {
|
||||||
var req http.Request
|
var req http.Request
|
||||||
|
var resp http.Response
|
||||||
req.Method = "PUT"
|
req.Method = "PUT"
|
||||||
req.Header = http.Header{}
|
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.
|
// Delete returns *BeegoHttpRequest DELETE GET method.
|
||||||
func Delete(url string) *BeegoHttpRequest {
|
func Delete(url string) *BeegoHttpRequest {
|
||||||
var req http.Request
|
var req http.Request
|
||||||
|
var resp http.Response
|
||||||
req.Method = "DELETE"
|
req.Method = "DELETE"
|
||||||
req.Header = http.Header{}
|
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.
|
// Head returns *BeegoHttpRequest with HEAD method.
|
||||||
func Head(url string) *BeegoHttpRequest {
|
func Head(url string) *BeegoHttpRequest {
|
||||||
var req http.Request
|
var req http.Request
|
||||||
|
var resp http.Response
|
||||||
req.Method = "HEAD"
|
req.Method = "HEAD"
|
||||||
req.Header = http.Header{}
|
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
|
// BeegoHttpSettings
|
||||||
@ -108,6 +137,8 @@ type BeegoHttpRequest struct {
|
|||||||
params map[string]string
|
params map[string]string
|
||||||
files map[string]string
|
files map[string]string
|
||||||
setting BeegoHttpSettings
|
setting BeegoHttpSettings
|
||||||
|
resp *http.Response
|
||||||
|
body []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change request settings
|
// Change request settings
|
||||||
@ -123,7 +154,7 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUserAgent sets User-Agent header field
|
// SetUserAgent sets User-Agent header field
|
||||||
func (b *BeegoHttpRequest) SetAgent(useragent string) *BeegoHttpRequest {
|
func (b *BeegoHttpRequest) SetUserAgent(useragent string) *BeegoHttpRequest {
|
||||||
b.setting.UserAgent = useragent
|
b.setting.UserAgent = useragent
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@ -223,6 +254,9 @@ func (b *BeegoHttpRequest) Body(data interface{}) *BeegoHttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
||||||
|
if b.resp.StatusCode != 0 {
|
||||||
|
return b.resp, nil
|
||||||
|
}
|
||||||
var paramBody string
|
var paramBody string
|
||||||
if len(b.params) > 0 {
|
if len(b.params) > 0 {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -341,6 +375,7 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
b.resp = resp
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +393,9 @@ func (b *BeegoHttpRequest) String() (string, error) {
|
|||||||
// Bytes returns the body []byte in response.
|
// Bytes returns the body []byte in response.
|
||||||
// it calls Response inner.
|
// it calls Response inner.
|
||||||
func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
|
func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
|
||||||
|
if b.body != nil {
|
||||||
|
return b.body, nil
|
||||||
|
}
|
||||||
resp, err := b.getResponse()
|
resp, err := b.getResponse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -370,6 +408,7 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
b.body = data
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,11 +430,8 @@ func (b *BeegoHttpRequest) ToFile(filename string) error {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
_, err = io.Copy(f, resp.Body)
|
_, err = io.Copy(f, resp.Body)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToJson returns the map that marshals from the body bytes as json in response .
|
// ToJson returns the map that marshals from the body bytes as json in response .
|
||||||
// it calls Response inner.
|
// it calls Response inner.
|
||||||
@ -405,25 +441,19 @@ func (b *BeegoHttpRequest) ToJson(v interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(data, v)
|
err = json.Unmarshal(data, v)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToXml returns the map that marshals from the body bytes as xml in response .
|
// ToXml returns the map that marshals from the body bytes as xml in response .
|
||||||
// it calls Response inner.
|
// it calls Response inner.
|
||||||
func (b *BeegoHttpRequest) ToXML(v interface{}) error {
|
func (b *BeegoHttpRequest) ToXml(v interface{}) error {
|
||||||
data, err := b.Bytes()
|
data, err := b.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = xml.Unmarshal(data, v)
|
err = xml.Unmarshal(data, v)
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response executes request client gets response mannually.
|
// Response executes request client gets response mannually.
|
||||||
func (b *BeegoHttpRequest) Response() (*http.Response, error) {
|
func (b *BeegoHttpRequest) Response() (*http.Response, error) {
|
||||||
|
@ -1,100 +1,193 @@
|
|||||||
// Beego (http://beego.me)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package httplib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetUrl(t *testing.T) {
|
func TestResponse(t *testing.T) {
|
||||||
resp, err := Get("http://beego.me").Debug(true).Response()
|
req := Get("http://httpbin.org/get")
|
||||||
|
resp, err := req.Response()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp.Body == nil {
|
t.Log(resp)
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(str) == 0 {
|
t.Log(b)
|
||||||
t.Fatal("has no info")
|
|
||||||
|
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) {
|
func TestSimplePost(t *testing.T) {
|
||||||
b := Post("http://beego.me/").Debug(true)
|
v := "smallfish"
|
||||||
b.Param("username", "astaxie")
|
req := Post("http://httpbin.org/post")
|
||||||
b.Param("password", "hello")
|
req.Param("username", v)
|
||||||
b.PostFile("uploadfile", "httplib_test.go")
|
|
||||||
str, err := b.String()
|
str, err := req.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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) {
|
func TestPostFile(t *testing.T) {
|
||||||
fmt.Println("TestSimpleGetString==========================================")
|
v := "smallfish"
|
||||||
html, err := Get("http://httpbin.org/headers").SetAgent("beegoooooo").String()
|
req := Post("http://httpbin.org/post")
|
||||||
|
req.Param("username", v)
|
||||||
|
req.PostFile("uploadfile", "httplib_test.go")
|
||||||
|
|
||||||
|
str, err := req.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println(html)
|
t.Log(str)
|
||||||
fmt.Println("TestSimpleGetString==========================================")
|
|
||||||
|
n := strings.Index(str, v)
|
||||||
|
if n == -1 {
|
||||||
|
t.Fatal(v + " not found in post")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSimpleGetStringWithDefaultCookie(t *testing.T) {
|
func TestSimplePut(t *testing.T) {
|
||||||
fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================")
|
str, err := Put("http://httpbin.org/put").String()
|
||||||
html, err := Get("http://httpbin.org/cookies/set?k1=v1").SetEnableCookie(true).String()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println(html)
|
t.Log(str)
|
||||||
html, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(html)
|
|
||||||
fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultSetting(t *testing.T) {
|
func TestSimpleDelete(t *testing.T) {
|
||||||
fmt.Println("TestDefaultSetting==========================================")
|
str, err := Delete("http://httpbin.org/delete").String()
|
||||||
var def BeegoHttpSettings
|
if err != nil {
|
||||||
def.EnableCookie = true
|
t.Fatal(err)
|
||||||
//def.ShowDebug = true
|
}
|
||||||
def.UserAgent = "UserAgent"
|
t.Log(str)
|
||||||
//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 TestWithCookie(t *testing.T) {
|
||||||
|
v := "smallfish"
|
||||||
|
str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println(html)
|
t.Log(str)
|
||||||
html, err = Get("http://httpbin.org/headers").String()
|
|
||||||
|
str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println(html)
|
t.Log(str)
|
||||||
fmt.Println("TestDefaultSetting==========================================")
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
95
log.go
95
log.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
@ -14,12 +22,14 @@ import (
|
|||||||
|
|
||||||
// Log levels to control the logging output.
|
// Log levels to control the logging output.
|
||||||
const (
|
const (
|
||||||
LevelTrace = iota
|
LevelEmergency = iota
|
||||||
LevelDebug
|
LevelAlert
|
||||||
LevelInfo
|
|
||||||
LevelWarning
|
|
||||||
LevelError
|
|
||||||
LevelCritical
|
LevelCritical
|
||||||
|
LevelError
|
||||||
|
LevelWarning
|
||||||
|
LevelNotice
|
||||||
|
LevelInformational
|
||||||
|
LevelDebug
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetLogLevel sets the global log level used by the simple
|
// SetLogLevel sets the global log level used by the simple
|
||||||
@ -45,29 +55,12 @@ func SetLogger(adaptername string, config string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace logs a message at trace level.
|
func Emergency(v ...interface{}) {
|
||||||
func Trace(v ...interface{}) {
|
BeeLogger.Emergency(generateFmtStr(len(v)), v...)
|
||||||
BeeLogger.Trace(generateFmtStr(len(v)), v...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs a message at debug level.
|
func Alert(v ...interface{}) {
|
||||||
func Debug(v ...interface{}) {
|
BeeLogger.Alert(generateFmtStr(len(v)), v...)
|
||||||
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...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Critical logs a message at critical level.
|
// Critical logs a message at critical level.
|
||||||
@ -75,6 +68,46 @@ func Critical(v ...interface{}) {
|
|||||||
BeeLogger.Critical(generateFmtStr(len(v)), v...)
|
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 {
|
func generateFmtStr(n int) string {
|
||||||
return strings.Repeat("%v ", n)
|
return strings.Repeat("%v ", n)
|
||||||
}
|
}
|
||||||
|
20
logs/conn.go
20
logs/conn.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -45,7 +53,7 @@ func (c *ConnWriter) Init(jsonconfig string) error {
|
|||||||
// write message in connection.
|
// write message in connection.
|
||||||
// if connection is down, try to re-connect.
|
// if connection is down, try to re-connect.
|
||||||
func (c *ConnWriter) WriteMsg(msg string, level int) error {
|
func (c *ConnWriter) WriteMsg(msg string, level int) error {
|
||||||
if level < c.Level {
|
if level > c.Level {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if c.neddedConnectOnMsg() {
|
if c.neddedConnectOnMsg() {
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -13,5 +21,5 @@ import (
|
|||||||
func TestConn(t *testing.T) {
|
func TestConn(t *testing.T) {
|
||||||
log := NewLogger(1000)
|
log := NewLogger(1000)
|
||||||
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
|
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
|
||||||
log.Info("info")
|
log.Informational("informational")
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -24,12 +32,14 @@ func NewBrush(color string) Brush {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var colors = []Brush{
|
var colors = []Brush{
|
||||||
NewBrush("1;36"), // Trace cyan
|
NewBrush("1;37"), // Emergency white
|
||||||
NewBrush("1;34"), // Debug blue
|
NewBrush("1;36"), // Alert cyan
|
||||||
NewBrush("1;32"), // Info green
|
NewBrush("1;35"), // Critical magenta
|
||||||
NewBrush("1;33"), // Warn yellow
|
|
||||||
NewBrush("1;31"), // Error red
|
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.
|
// ConsoleWriter implements LoggerInterface and writes messages to terminal.
|
||||||
@ -42,7 +52,7 @@ type ConsoleWriter struct {
|
|||||||
func NewConsole() LoggerInterface {
|
func NewConsole() LoggerInterface {
|
||||||
cw := new(ConsoleWriter)
|
cw := new(ConsoleWriter)
|
||||||
cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime)
|
cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime)
|
||||||
cw.Level = LevelTrace
|
cw.Level = LevelDebug
|
||||||
return cw
|
return cw
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +71,7 @@ func (c *ConsoleWriter) Init(jsonconfig string) error {
|
|||||||
|
|
||||||
// write message in console.
|
// write message in console.
|
||||||
func (c *ConsoleWriter) WriteMsg(msg string, level int) error {
|
func (c *ConsoleWriter) WriteMsg(msg string, level int) error {
|
||||||
if level < c.Level {
|
if level > c.Level {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if goos := runtime.GOOS; goos == "windows" {
|
if goos := runtime.GOOS; goos == "windows" {
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -10,22 +18,29 @@ import (
|
|||||||
"testing"
|
"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) {
|
func TestConsole(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log1 := NewLogger(10000)
|
||||||
log.EnableFuncCallDepth(true)
|
log1.EnableFuncCallDepth(true)
|
||||||
log.SetLogger("console", "")
|
log1.SetLogger("console", "")
|
||||||
log.Trace("trace")
|
testConsoleCalls(log1)
|
||||||
log.Info("info")
|
|
||||||
log.Warn("warning")
|
|
||||||
log.Debug("debug")
|
|
||||||
log.Critical("critical")
|
|
||||||
log2 := NewLogger(100)
|
log2 := NewLogger(100)
|
||||||
log2.SetLogger("console", `{"level":1}`)
|
log2.SetLogger("console", `{"level":3}`)
|
||||||
log.Trace("trace")
|
testConsoleCalls(log2)
|
||||||
log.Info("info")
|
|
||||||
log.Warn("warning")
|
|
||||||
log.Debug("debug")
|
|
||||||
log.Critical("critical")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConsole(b *testing.B) {
|
func BenchmarkConsole(b *testing.B) {
|
||||||
@ -33,6 +48,6 @@ func BenchmarkConsole(b *testing.B) {
|
|||||||
log.EnableFuncCallDepth(true)
|
log.EnableFuncCallDepth(true)
|
||||||
log.SetLogger("console", "")
|
log.SetLogger("console", "")
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
log.Trace("trace")
|
log.Debug("debug")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
logs/file.go
20
logs/file.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -138,7 +146,7 @@ func (w *FileLogWriter) docheck(size int) {
|
|||||||
|
|
||||||
// write logger message into file.
|
// write logger message into file.
|
||||||
func (w *FileLogWriter) WriteMsg(msg string, level int) error {
|
func (w *FileLogWriter) WriteMsg(msg string, level int) error {
|
||||||
if level < w.Level {
|
if level > w.Level {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] "
|
n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] "
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -10,6 +18,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -17,12 +26,14 @@ import (
|
|||||||
func TestFile(t *testing.T) {
|
func TestFile(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test.log"}`)
|
log.SetLogger("file", `{"filename":"test.log"}`)
|
||||||
log.Trace("test")
|
|
||||||
log.Info("info")
|
|
||||||
log.Debug("debug")
|
log.Debug("debug")
|
||||||
log.Warn("warning")
|
log.Informational("info")
|
||||||
|
log.Notice("notice")
|
||||||
|
log.Warning("warning")
|
||||||
log.Error("error")
|
log.Error("error")
|
||||||
|
log.Alert("alert")
|
||||||
log.Critical("critical")
|
log.Critical("critical")
|
||||||
|
log.Emergency("emergency")
|
||||||
time.Sleep(time.Second * 4)
|
time.Sleep(time.Second * 4)
|
||||||
f, err := os.Open("test.log")
|
f, err := os.Open("test.log")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -39,21 +50,24 @@ func TestFile(t *testing.T) {
|
|||||||
linenum++
|
linenum++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if linenum != 6 {
|
var expected = LevelDebug + 1
|
||||||
t.Fatal(linenum, "not line 6")
|
if linenum != expected {
|
||||||
|
t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines")
|
||||||
}
|
}
|
||||||
os.Remove("test.log")
|
os.Remove("test.log")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFile2(t *testing.T) {
|
func TestFile2(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test2.log","level":2}`)
|
log.SetLogger("file", fmt.Sprintf(`{"filename":"test2.log","level":%d}`, LevelError))
|
||||||
log.Trace("test")
|
|
||||||
log.Info("info")
|
|
||||||
log.Debug("debug")
|
log.Debug("debug")
|
||||||
log.Warn("warning")
|
log.Info("info")
|
||||||
|
log.Notice("notice")
|
||||||
|
log.Warning("warning")
|
||||||
log.Error("error")
|
log.Error("error")
|
||||||
|
log.Alert("alert")
|
||||||
log.Critical("critical")
|
log.Critical("critical")
|
||||||
|
log.Emergency("emergency")
|
||||||
time.Sleep(time.Second * 4)
|
time.Sleep(time.Second * 4)
|
||||||
f, err := os.Open("test2.log")
|
f, err := os.Open("test2.log")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -70,8 +84,9 @@ func TestFile2(t *testing.T) {
|
|||||||
linenum++
|
linenum++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if linenum != 4 {
|
var expected = LevelError + 1
|
||||||
t.Fatal(linenum, "not line 4")
|
if linenum != expected {
|
||||||
|
t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines")
|
||||||
}
|
}
|
||||||
os.Remove("test2.log")
|
os.Remove("test2.log")
|
||||||
}
|
}
|
||||||
@ -79,17 +94,19 @@ func TestFile2(t *testing.T) {
|
|||||||
func TestFileRotate(t *testing.T) {
|
func TestFileRotate(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
|
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
|
||||||
log.Trace("test")
|
|
||||||
log.Info("info")
|
|
||||||
log.Debug("debug")
|
log.Debug("debug")
|
||||||
log.Warn("warning")
|
log.Info("info")
|
||||||
|
log.Notice("notice")
|
||||||
|
log.Warning("warning")
|
||||||
log.Error("error")
|
log.Error("error")
|
||||||
|
log.Alert("alert")
|
||||||
log.Critical("critical")
|
log.Critical("critical")
|
||||||
|
log.Emergency("emergency")
|
||||||
time.Sleep(time.Second * 4)
|
time.Sleep(time.Second * 4)
|
||||||
rotatename := "test3.log" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1)
|
rotatename := "test3.log" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1)
|
||||||
b, err := exists(rotatename)
|
b, err := exists(rotatename)
|
||||||
if !b || err != nil {
|
if !b || err != nil {
|
||||||
t.Fatal("rotate not gen")
|
t.Fatal("rotate not generated")
|
||||||
}
|
}
|
||||||
os.Remove(rotatename)
|
os.Remove(rotatename)
|
||||||
os.Remove("test3.log")
|
os.Remove("test3.log")
|
||||||
@ -110,7 +127,7 @@ func BenchmarkFile(b *testing.B) {
|
|||||||
log := NewLogger(100000)
|
log := NewLogger(100000)
|
||||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
log.Trace("trace")
|
log.Debug("debug")
|
||||||
}
|
}
|
||||||
os.Remove("test4.log")
|
os.Remove("test4.log")
|
||||||
}
|
}
|
||||||
|
147
logs/log.go
147
logs/log.go
@ -1,9 +1,35 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,14 +39,25 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RFC5424 log message levels.
|
||||||
const (
|
const (
|
||||||
// log message levels
|
LevelEmergency = iota
|
||||||
LevelTrace = iota
|
LevelAlert
|
||||||
LevelDebug
|
|
||||||
LevelInfo
|
|
||||||
LevelWarn
|
|
||||||
LevelError
|
|
||||||
LevelCritical
|
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
|
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.
|
// if the buffering chan is full, logger adapters write to file or other way.
|
||||||
func NewLogger(channellen int64) *BeeLogger {
|
func NewLogger(channellen int64) *BeeLogger {
|
||||||
bl := new(BeeLogger)
|
bl := new(BeeLogger)
|
||||||
|
bl.level = LevelDebug
|
||||||
bl.loggerFuncCallDepth = 2
|
bl.loggerFuncCallDepth = 2
|
||||||
bl.msg = make(chan *logMsg, channellen)
|
bl.msg = make(chan *logMsg, channellen)
|
||||||
bl.outputs = make(map[string]LoggerInterface)
|
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 {
|
func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
|
||||||
if bl.level > loglevel {
|
if loglevel > bl.level {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
lm := new(logMsg)
|
lm := new(logMsg)
|
||||||
@ -130,8 +168,10 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// set log message level.
|
// Set log message level.
|
||||||
// if message level (such as LevelTrace) is less than logger level (such as LevelWarn), ignore message.
|
//
|
||||||
|
// 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) {
|
func (bl *BeeLogger) SetLevel(l int) {
|
||||||
bl.level = l
|
bl.level = l
|
||||||
}
|
}
|
||||||
@ -147,7 +187,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start logger chan reading.
|
// start logger chan reading.
|
||||||
// when chan is full, write logs.
|
// when chan is not empty, write logs.
|
||||||
func (bl *BeeLogger) startLogger() {
|
func (bl *BeeLogger) startLogger() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -159,40 +199,73 @@ func (bl *BeeLogger) startLogger() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// log trace level message.
|
// Log EMERGENCY level message.
|
||||||
func (bl *BeeLogger) Trace(format string, v ...interface{}) {
|
func (bl *BeeLogger) Emergency(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{}) {
|
|
||||||
msg := fmt.Sprintf("[D] "+format, v...)
|
msg := fmt.Sprintf("[D] "+format, v...)
|
||||||
bl.writerMsg(LevelDebug, msg)
|
bl.writerMsg(LevelEmergency, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// log info level message.
|
// Log ALERT level message.
|
||||||
func (bl *BeeLogger) Info(format string, v ...interface{}) {
|
func (bl *BeeLogger) Alert(format string, v ...interface{}) {
|
||||||
msg := fmt.Sprintf("[I] "+format, v...)
|
msg := fmt.Sprintf("[D] "+format, v...)
|
||||||
bl.writerMsg(LevelInfo, msg)
|
bl.writerMsg(LevelAlert, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// log warn level message.
|
// Log CRITICAL level message.
|
||||||
func (bl *BeeLogger) Warn(format string, v ...interface{}) {
|
func (bl *BeeLogger) Critical(format string, v ...interface{}) {
|
||||||
msg := fmt.Sprintf("[W] "+format, v...)
|
msg := fmt.Sprintf("[C] "+format, v...)
|
||||||
bl.writerMsg(LevelWarn, msg)
|
bl.writerMsg(LevelCritical, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// log error level message.
|
// Log ERROR level message.
|
||||||
func (bl *BeeLogger) Error(format string, v ...interface{}) {
|
func (bl *BeeLogger) Error(format string, v ...interface{}) {
|
||||||
msg := fmt.Sprintf("[E] "+format, v...)
|
msg := fmt.Sprintf("[E] "+format, v...)
|
||||||
bl.writerMsg(LevelError, msg)
|
bl.writerMsg(LevelError, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// log critical level message.
|
// Log WARNING level message.
|
||||||
func (bl *BeeLogger) Critical(format string, v ...interface{}) {
|
func (bl *BeeLogger) Warning(format string, v ...interface{}) {
|
||||||
msg := fmt.Sprintf("[C] "+format, v...)
|
msg := fmt.Sprintf("[W] "+format, v...)
|
||||||
bl.writerMsg(LevelCritical, msg)
|
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.
|
// flush all chan data.
|
||||||
|
40
logs/smtp.go
40
logs/smtp.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
@ -51,22 +59,30 @@ func (s *SmtpWriter) Init(jsonconfig string) error {
|
|||||||
return nil
|
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.
|
// write message in smtp writer.
|
||||||
// it will send an email with subject and only this message.
|
// it will send an email with subject and only this message.
|
||||||
func (s *SmtpWriter) WriteMsg(msg string, level int) error {
|
func (s *SmtpWriter) WriteMsg(msg string, level int) error {
|
||||||
if level < s.Level {
|
if level > s.Level {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hp := strings.Split(s.Host, ":")
|
hp := strings.Split(s.Host, ":")
|
||||||
|
|
||||||
// Set up authentication information.
|
// Set up authentication information.
|
||||||
auth := smtp.PlainAuth(
|
auth := s.GetSmtpAuth(hp[0])
|
||||||
"",
|
|
||||||
s.Username,
|
|
||||||
s.Password,
|
|
||||||
hp[0],
|
|
||||||
)
|
|
||||||
// Connect to the server, authenticate, set the sender and recipient,
|
// Connect to the server, authenticate, set the sender and recipient,
|
||||||
// and send the email all in one step.
|
// and send the email all in one step.
|
||||||
content_type := "Content-Type: text/plain" + "; charset=UTF-8"
|
content_type := "Content-Type: text/plain" + "; charset=UTF-8"
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package logs
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package middleware
|
||||||
|
|
||||||
@ -311,6 +319,7 @@ func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
isint = 500
|
isint = 500
|
||||||
}
|
}
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
w.WriteHeader(isint)
|
w.WriteHeader(isint)
|
||||||
h(w, r)
|
h(w, r)
|
||||||
return
|
return
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package middleware
|
||||||
|
|
||||||
|
@ -1,90 +1,71 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package middleware
|
||||||
|
|
||||||
//import (
|
import (
|
||||||
// "github.com/astaxie/beego/config"
|
"encoding/json"
|
||||||
// "os"
|
"io/ioutil"
|
||||||
// "path"
|
"os"
|
||||||
//)
|
)
|
||||||
|
|
||||||
//type Translation struct {
|
type Translation struct {
|
||||||
// filetype string
|
filepath string
|
||||||
// CurrentLocal string
|
CurrentLocal string
|
||||||
// Locales map[string]map[string]string
|
Locales map[string]map[string]string
|
||||||
//}
|
}
|
||||||
|
|
||||||
//func NewLocale(filetype string) *Translation {
|
func NewLocale(filepath string, defaultlocal string) *Translation {
|
||||||
// return &Translation{
|
i18n := make(map[string]map[string]string)
|
||||||
// filetype: filetype,
|
file, err := os.Open(filepath)
|
||||||
// CurrentLocal: "zh",
|
if err != nil {
|
||||||
// Locales: make(map[string]map[string]string),
|
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 {
|
func (t *Translation) SetLocale(local string) {
|
||||||
// dir, err := os.Open(dirPath)
|
t.CurrentLocal = local
|
||||||
// if err != nil {
|
}
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// defer dir.Close()
|
|
||||||
|
|
||||||
// names, err := dir.Readdirnames(-1)
|
func (t *Translation) Translate(key string, local string) string {
|
||||||
// if err != nil {
|
if local == "" {
|
||||||
// return err
|
local = t.CurrentLocal
|
||||||
// }
|
}
|
||||||
|
if ct, ok := t.Locales[key]; ok {
|
||||||
// for _, name := range names {
|
if v, o := ct[local]; o {
|
||||||
// fullPath := path.Join(dirPath, name)
|
return v
|
||||||
|
}
|
||||||
// fi, err := os.Stat(fullPath)
|
}
|
||||||
// if err != nil {
|
return key
|
||||||
// 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
|
|
||||||
//}
|
|
||||||
|
280
migration/migration.go
Normal file
280
migration/migration.go
Normal file
@ -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
|
||||||
|
}
|
18
mime.go
18
mime.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
19
namespace.go
19
namespace.go
@ -1,8 +1,17 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
|
@ -154,10 +154,5 @@ note: not recommend use this in product env.
|
|||||||
|
|
||||||
more details and examples in docs and test
|
more details and examples in docs and test
|
||||||
|
|
||||||
* [中文](http://beego.me/docs/Models_Overview?lang=zh)
|
[documents](http://beego.me/docs/mvc/model/overview.md)
|
||||||
* [English](http://beego.me/docs/Models_Overview?lang=en)
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
- some unrealized api
|
|
||||||
- examples
|
|
||||||
- docs
|
|
||||||
|
18
orm/cmd.go
18
orm/cmd.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
@ -144,6 +152,10 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
|
|||||||
column += " " + "NOT NULL"
|
column += " " + "NOT NULL"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if fi.initial.String() != "" {
|
||||||
|
// column += " DEFAULT " + fi.initial.String()
|
||||||
|
//}
|
||||||
|
|
||||||
if fi.unique {
|
if fi.unique {
|
||||||
column += " " + "UNIQUE"
|
column += " " + "UNIQUE"
|
||||||
}
|
}
|
||||||
|
18
orm/db.go
18
orm/db.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
@ -136,7 +144,7 @@ func detectTZ(al *alias) {
|
|||||||
if engine != "" {
|
if engine != "" {
|
||||||
al.Engine = engine
|
al.Engine = engine
|
||||||
} else {
|
} else {
|
||||||
engine = "INNODB"
|
al.Engine = "INNODB"
|
||||||
}
|
}
|
||||||
|
|
||||||
case DR_Sqlite:
|
case DR_Sqlite:
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -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 的数据库
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
|
@ -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 的值
|
|
@ -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,等
|
|
@ -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, ", ")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型
|
|
@ -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) 可以进行判断
|
|
@ -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
|
|
||||||
```
|
|
@ -1,17 +0,0 @@
|
|||||||
## 事务处理
|
|
||||||
|
|
||||||
orm 可以简单的进行事务操作
|
|
||||||
|
|
||||||
```go
|
|
||||||
o := NewOrm()
|
|
||||||
err := o.Begin()
|
|
||||||
// 事务处理过程
|
|
||||||
...
|
|
||||||
...
|
|
||||||
// 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内
|
|
||||||
if SomeError {
|
|
||||||
err = o.Rollback()
|
|
||||||
} else {
|
|
||||||
err = o.Commit()
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
@ -128,6 +136,9 @@ func getFieldType(val reflect.Value) (ft int, err error) {
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
ft = TypeCharField
|
ft = TypeCharField
|
||||||
default:
|
default:
|
||||||
|
if elm.Interface() == nil {
|
||||||
|
panic(fmt.Errorf("%s is nil pointer, may be miss setting tag", val))
|
||||||
|
}
|
||||||
switch elm.Interface().(type) {
|
switch elm.Interface().(type) {
|
||||||
case sql.NullInt64:
|
case sql.NullInt64:
|
||||||
ft = TypeBigIntegerField
|
ft = TypeBigIntegerField
|
||||||
|
54
orm/orm.go
54
orm/orm.go
@ -1,9 +1,53 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
18
orm/types.go
18
orm/types.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
18
orm/utils.go
18
orm/utils.go
@ -1,8 +1,16 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors slene
|
// 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
|
package orm
|
||||||
|
|
||||||
|
55
parser.go
55
parser.go
@ -1,8 +1,17 @@
|
|||||||
// Beego (http://beego.me/)
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
// @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
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// @license http://github.com/astaxie/beego/blob/master/LICENSE
|
// you may not use this file except in compliance with the License.
|
||||||
// @authors astaxie
|
// 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
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -61,11 +70,13 @@ func parserPkg(pkgRealpath, pkgpath string) error {
|
|||||||
for _, d := range fl.Decls {
|
for _, d := range fl.Decls {
|
||||||
switch specDecl := d.(type) {
|
switch specDecl := d.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
|
if specDecl.Recv != nil {
|
||||||
parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath)
|
parserComments(specDecl.Doc, specDecl.Name.String(), fmt.Sprint(specDecl.Recv.List[0].Type.(*ast.StarExpr).X), pkgpath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
genRouterCode()
|
genRouterCode()
|
||||||
savetoFile(pkgRealpath)
|
savetoFile(pkgRealpath)
|
||||||
return nil
|
return nil
|
||||||
@ -110,7 +121,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
}
|
}
|
||||||
|
|
||||||
func genRouterCode() {
|
func genRouterCode() {
|
||||||
os.Mkdir(path.Join(AppPath, "routers"), 0755)
|
os.Mkdir(path.Join(workPath, "routers"), 0755)
|
||||||
Info("generate router from comments")
|
Info("generate router from comments")
|
||||||
var globalinfo string
|
var globalinfo string
|
||||||
for k, cList := range genInfoList {
|
for k, cList := range genInfoList {
|
||||||
@ -144,7 +155,7 @@ func genRouterCode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if globalinfo != "" {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -154,18 +165,21 @@ func genRouterCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func compareFile(pkgRealpath string) bool {
|
func compareFile(pkgRealpath string) bool {
|
||||||
if utils.FileExists(path.Join(AppPath, lastupdateFilename)) {
|
if !utils.FileExists(path.Join(workPath, "routers", "commentsRouter.go")) {
|
||||||
content, err := ioutil.ReadFile(path.Join(AppPath, lastupdateFilename))
|
return true
|
||||||
|
}
|
||||||
|
if utils.FileExists(path.Join(workPath, lastupdateFilename)) {
|
||||||
|
content, err := ioutil.ReadFile(path.Join(workPath, lastupdateFilename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
json.Unmarshal(content, &pkgLastupdate)
|
json.Unmarshal(content, &pkgLastupdate)
|
||||||
ft, err := os.Lstat(pkgRealpath)
|
lastupdate, err := getpathTime(pkgRealpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if v, ok := pkgLastupdate[pkgRealpath]; ok {
|
if v, ok := pkgLastupdate[pkgRealpath]; ok {
|
||||||
if ft.ModTime().UnixNano() <= v {
|
if lastupdate <= v {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,14 +188,27 @@ func compareFile(pkgRealpath string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func savetoFile(pkgRealpath string) {
|
func savetoFile(pkgRealpath string) {
|
||||||
ft, err := os.Lstat(pkgRealpath)
|
lastupdate, err := getpathTime(pkgRealpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pkgLastupdate[pkgRealpath] = ft.ModTime().UnixNano()
|
pkgLastupdate[pkgRealpath] = lastupdate
|
||||||
d, err := json.Marshal(pkgLastupdate)
|
d, err := json.Marshal(pkgLastupdate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
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
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user