mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 18:40:55 +00:00
Merge branch 'develop' of github.com:dvwallin/beego into develop
This commit is contained in:
commit
edbad60782
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
beego.iml
|
||||||
|
26
README.md
26
README.md
@ -3,14 +3,36 @@
|
|||||||
[![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)
|
||||||
[![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego)
|
[![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego)
|
||||||
|
|
||||||
beego is an open-source, high-performance, modular, full-stack web framework.
|
beego is used for rapid development of RESTful APIs, web apps and backend services in Go.
|
||||||
|
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding.
|
||||||
|
|
||||||
More info [beego.me](http://beego.me)
|
More info [beego.me](http://beego.me)
|
||||||
|
|
||||||
## Installation
|
##Quick Start
|
||||||
|
######Download and install
|
||||||
|
|
||||||
go get github.com/astaxie/beego
|
go get github.com/astaxie/beego
|
||||||
|
|
||||||
|
######Create file `hello.go`
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/astaxie/beego"
|
||||||
|
|
||||||
|
func main(){
|
||||||
|
beego.Run()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
######Build and run
|
||||||
|
```bash
|
||||||
|
go build hello.go
|
||||||
|
./hello
|
||||||
|
```
|
||||||
|
######Congratulations!
|
||||||
|
You just built your first beego app.
|
||||||
|
Open your browser and visit `http://localhost:8000`.
|
||||||
|
Please see [Documentation](http://beego.me/docs) for more.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* RESTful support
|
* RESTful support
|
||||||
|
32
admin.go
32
admin.go
@ -101,11 +101,11 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
m["AppConfigPath"] = AppConfigPath
|
m["AppConfigPath"] = AppConfigPath
|
||||||
m["StaticDir"] = StaticDir
|
m["StaticDir"] = StaticDir
|
||||||
m["StaticExtensionsToGzip"] = StaticExtensionsToGzip
|
m["StaticExtensionsToGzip"] = StaticExtensionsToGzip
|
||||||
m["HttpAddr"] = HttpAddr
|
m["HTTPAddr"] = HTTPAddr
|
||||||
m["HttpPort"] = HttpPort
|
m["HTTPPort"] = HTTPPort
|
||||||
m["HttpTLS"] = EnableHttpTLS
|
m["HTTPTLS"] = EnableHTTPTLS
|
||||||
m["HttpCertFile"] = HttpCertFile
|
m["HTTPCertFile"] = HTTPCertFile
|
||||||
m["HttpKeyFile"] = HttpKeyFile
|
m["HTTPKeyFile"] = HTTPKeyFile
|
||||||
m["RecoverPanic"] = RecoverPanic
|
m["RecoverPanic"] = RecoverPanic
|
||||||
m["AutoRender"] = AutoRender
|
m["AutoRender"] = AutoRender
|
||||||
m["ViewsPath"] = ViewsPath
|
m["ViewsPath"] = ViewsPath
|
||||||
@ -114,14 +114,14 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
m["SessionProvider"] = SessionProvider
|
m["SessionProvider"] = SessionProvider
|
||||||
m["SessionName"] = SessionName
|
m["SessionName"] = SessionName
|
||||||
m["SessionGCMaxLifetime"] = SessionGCMaxLifetime
|
m["SessionGCMaxLifetime"] = SessionGCMaxLifetime
|
||||||
m["SessionSavePath"] = SessionSavePath
|
m["SessionProviderConfig"] = SessionProviderConfig
|
||||||
m["SessionCookieLifeTime"] = SessionCookieLifeTime
|
m["SessionCookieLifeTime"] = SessionCookieLifeTime
|
||||||
m["UseFcgi"] = UseFcgi
|
m["EnabelFcgi"] = EnabelFcgi
|
||||||
m["MaxMemory"] = MaxMemory
|
m["MaxMemory"] = MaxMemory
|
||||||
m["EnableGzip"] = EnableGzip
|
m["EnableGzip"] = EnableGzip
|
||||||
m["DirectoryIndex"] = DirectoryIndex
|
m["DirectoryIndex"] = DirectoryIndex
|
||||||
m["HttpServerTimeOut"] = HttpServerTimeOut
|
m["HTTPServerTimeOut"] = HTTPServerTimeOut
|
||||||
m["ErrorsShow"] = ErrorsShow
|
m["EnableErrorsShow"] = EnableErrorsShow
|
||||||
m["XSRFKEY"] = XSRFKEY
|
m["XSRFKEY"] = XSRFKEY
|
||||||
m["EnableXSRF"] = EnableXSRF
|
m["EnableXSRF"] = EnableXSRF
|
||||||
m["XSRFExpire"] = XSRFExpire
|
m["XSRFExpire"] = XSRFExpire
|
||||||
@ -130,8 +130,8 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
m["TemplateRight"] = TemplateRight
|
m["TemplateRight"] = TemplateRight
|
||||||
m["BeegoServerName"] = BeegoServerName
|
m["BeegoServerName"] = BeegoServerName
|
||||||
m["EnableAdmin"] = EnableAdmin
|
m["EnableAdmin"] = EnableAdmin
|
||||||
m["AdminHttpAddr"] = AdminHttpAddr
|
m["AdminHTTPAddr"] = AdminHTTPAddr
|
||||||
m["AdminHttpPort"] = AdminHttpPort
|
m["AdminHTTPPort"] = AdminHTTPPort
|
||||||
|
|
||||||
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
||||||
tmpl = template.Must(tmpl.Parse(configTpl))
|
tmpl = template.Must(tmpl.Parse(configTpl))
|
||||||
@ -314,14 +314,14 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
|
|||||||
data["Content"] = result.String()
|
data["Content"] = result.String()
|
||||||
|
|
||||||
if format == "json" && command == "gc summary" {
|
if format == "json" && command == "gc summary" {
|
||||||
dataJson, err := json.Marshal(data)
|
dataJSON, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
rw.Write(dataJson)
|
rw.Write(dataJSON)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,10 +451,10 @@ func (admin *adminApp) Run() {
|
|||||||
if len(toolbox.AdminTaskList) > 0 {
|
if len(toolbox.AdminTaskList) > 0 {
|
||||||
toolbox.StartTask()
|
toolbox.StartTask()
|
||||||
}
|
}
|
||||||
addr := AdminHttpAddr
|
addr := AdminHTTPAddr
|
||||||
|
|
||||||
if AdminHttpPort != 0 {
|
if AdminHTTPPort != 0 {
|
||||||
addr = fmt.Sprintf("%s:%d", AdminHttpAddr, AdminHttpPort)
|
addr = fmt.Sprintf("%s:%d", AdminHTTPAddr, AdminHTTPPort)
|
||||||
}
|
}
|
||||||
for p, f := range admin.routers {
|
for p, f := range admin.routers {
|
||||||
http.Handle(p, f)
|
http.Handle(p, f)
|
||||||
|
236
app.go
236
app.go
@ -20,15 +20,26 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/fcgi"
|
"net/http/fcgi"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/grace"
|
"github.com/astaxie/beego/grace"
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// BeeApp is an application instance
|
||||||
|
BeeApp *App
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// create beego application
|
||||||
|
BeeApp = NewApp()
|
||||||
|
}
|
||||||
|
|
||||||
// App defines beego application with a new PatternServeMux.
|
// App defines beego application with a new PatternServeMux.
|
||||||
type App struct {
|
type App struct {
|
||||||
Handlers *ControllerRegistor
|
Handlers *ControllerRegister
|
||||||
Server *http.Server
|
Server *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,10 +52,10 @@ func NewApp() *App {
|
|||||||
|
|
||||||
// Run beego application.
|
// Run beego application.
|
||||||
func (app *App) Run() {
|
func (app *App) Run() {
|
||||||
addr := HttpAddr
|
addr := HTTPAddr
|
||||||
|
|
||||||
if HttpPort != 0 {
|
if HTTPPort != 0 {
|
||||||
addr = fmt.Sprintf("%s:%d", HttpAddr, HttpPort)
|
addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -53,8 +64,8 @@ func (app *App) Run() {
|
|||||||
)
|
)
|
||||||
endRunning := make(chan bool, 1)
|
endRunning := make(chan bool, 1)
|
||||||
|
|
||||||
if UseFcgi {
|
if EnabelFcgi {
|
||||||
if UseStdIo {
|
if EnableStdIo {
|
||||||
err = fcgi.Serve(nil, app.Handlers) // standard I/O
|
err = fcgi.Serve(nil, app.Handlers) // standard I/O
|
||||||
if err == nil {
|
if err == nil {
|
||||||
BeeLogger.Info("Use FCGI via standard I/O")
|
BeeLogger.Info("Use FCGI via standard I/O")
|
||||||
@ -62,7 +73,7 @@ func (app *App) Run() {
|
|||||||
BeeLogger.Info("Cannot use FCGI via standard I/O", err)
|
BeeLogger.Info("Cannot use FCGI via standard I/O", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if HttpPort == 0 {
|
if HTTPPort == 0 {
|
||||||
// remove the Socket file before start
|
// remove the Socket file before start
|
||||||
if utils.FileExists(addr) {
|
if utils.FileExists(addr) {
|
||||||
os.Remove(addr)
|
os.Remove(addr)
|
||||||
@ -80,18 +91,18 @@ func (app *App) Run() {
|
|||||||
if Graceful {
|
if Graceful {
|
||||||
app.Server.Addr = addr
|
app.Server.Addr = addr
|
||||||
app.Server.Handler = app.Handlers
|
app.Server.Handler = app.Handlers
|
||||||
app.Server.ReadTimeout = time.Duration(HttpServerTimeOut) * time.Second
|
app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second
|
||||||
app.Server.WriteTimeout = time.Duration(HttpServerTimeOut) * time.Second
|
app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second
|
||||||
if EnableHttpTLS {
|
if EnableHTTPTLS {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(20 * time.Microsecond)
|
time.Sleep(20 * time.Microsecond)
|
||||||
if HttpsPort != 0 {
|
if HTTPSPort != 0 {
|
||||||
addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort)
|
addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort)
|
||||||
app.Server.Addr = addr
|
app.Server.Addr = addr
|
||||||
}
|
}
|
||||||
server := grace.NewServer(addr, app.Handlers)
|
server := grace.NewServer(addr, app.Handlers)
|
||||||
server.Server = app.Server
|
server.Server = app.Server
|
||||||
err := server.ListenAndServeTLS(HttpCertFile, HttpKeyFile)
|
err := server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
BeeLogger.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
|
BeeLogger.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
@ -99,11 +110,11 @@ func (app *App) Run() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
if EnableHttpListen {
|
if EnableHTTPListen {
|
||||||
go func() {
|
go func() {
|
||||||
server := grace.NewServer(addr, app.Handlers)
|
server := grace.NewServer(addr, app.Handlers)
|
||||||
server.Server = app.Server
|
server.Server = app.Server
|
||||||
if ListenTCP4 && HttpAddr == "" {
|
if ListenTCP4 && HTTPAddr == "" {
|
||||||
server.Network = "tcp4"
|
server.Network = "tcp4"
|
||||||
}
|
}
|
||||||
err := server.ListenAndServe()
|
err := server.ListenAndServe()
|
||||||
@ -117,17 +128,17 @@ func (app *App) Run() {
|
|||||||
} else {
|
} else {
|
||||||
app.Server.Addr = addr
|
app.Server.Addr = addr
|
||||||
app.Server.Handler = app.Handlers
|
app.Server.Handler = app.Handlers
|
||||||
app.Server.ReadTimeout = time.Duration(HttpServerTimeOut) * time.Second
|
app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second
|
||||||
app.Server.WriteTimeout = time.Duration(HttpServerTimeOut) * time.Second
|
app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second
|
||||||
|
|
||||||
if EnableHttpTLS {
|
if EnableHTTPTLS {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(20 * time.Microsecond)
|
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)
|
||||||
}
|
}
|
||||||
BeeLogger.Info("https server Running on %s", app.Server.Addr)
|
BeeLogger.Info("https server Running on %s", app.Server.Addr)
|
||||||
err := app.Server.ListenAndServeTLS(HttpCertFile, HttpKeyFile)
|
err := app.Server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
BeeLogger.Critical("ListenAndServeTLS: ", err)
|
BeeLogger.Critical("ListenAndServeTLS: ", err)
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
@ -136,11 +147,11 @@ func (app *App) Run() {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if EnableHttpListen {
|
if EnableHTTPListen {
|
||||||
go func() {
|
go func() {
|
||||||
app.Server.Addr = addr
|
app.Server.Addr = addr
|
||||||
BeeLogger.Info("http server Running on %s", app.Server.Addr)
|
BeeLogger.Info("http server Running on %s", app.Server.Addr)
|
||||||
if ListenTCP4 && HttpAddr == "" {
|
if ListenTCP4 && HTTPAddr == "" {
|
||||||
ln, err := net.Listen("tcp4", app.Server.Addr)
|
ln, err := net.Listen("tcp4", app.Server.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
BeeLogger.Critical("ListenAndServe: ", err)
|
BeeLogger.Critical("ListenAndServe: ", err)
|
||||||
@ -170,3 +181,182 @@ func (app *App) Run() {
|
|||||||
}
|
}
|
||||||
<-endRunning
|
<-endRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Router adds a patterned controller handler to BeeApp.
|
||||||
|
// it's an alias method of App.Router.
|
||||||
|
// usage:
|
||||||
|
// simple router
|
||||||
|
// beego.Router("/admin", &admin.UserController{})
|
||||||
|
// beego.Router("/admin/index", &admin.ArticleController{})
|
||||||
|
//
|
||||||
|
// regex router
|
||||||
|
//
|
||||||
|
// beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||||
|
//
|
||||||
|
// custom rules
|
||||||
|
// beego.Router("/api/list",&RestController{},"*:ListFood")
|
||||||
|
// beego.Router("/api/create",&RestController{},"post:CreateFood")
|
||||||
|
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
|
||||||
|
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
|
||||||
|
func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
|
||||||
|
BeeApp.Handlers.Add(rootpath, c, mappingMethods...)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include will generate router file in the router/xxx.go from the controller's comments
|
||||||
|
// usage:
|
||||||
|
// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
|
||||||
|
// type BankAccount struct{
|
||||||
|
// beego.Controller
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// register the function
|
||||||
|
// func (b *BankAccount)Mapping(){
|
||||||
|
// b.Mapping("ShowAccount" , b.ShowAccount)
|
||||||
|
// b.Mapping("ModifyAccount", b.ModifyAccount)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// //@router /account/:id [get]
|
||||||
|
// func (b *BankAccount) ShowAccount(){
|
||||||
|
// //logic
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// //@router /account/:id [post]
|
||||||
|
// func (b *BankAccount) ModifyAccount(){
|
||||||
|
// //logic
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// the comments @router url methodlist
|
||||||
|
// url support all the function Router's pattern
|
||||||
|
// methodlist [get post head put delete options *]
|
||||||
|
func Include(cList ...ControllerInterface) *App {
|
||||||
|
BeeApp.Handlers.Include(cList...)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTRouter adds a restful controller handler to BeeApp.
|
||||||
|
// its' controller implements beego.ControllerInterface and
|
||||||
|
// defines a param "pattern/:objectId" to visit each resource.
|
||||||
|
func RESTRouter(rootpath string, c ControllerInterface) *App {
|
||||||
|
Router(rootpath, c)
|
||||||
|
Router(path.Join(rootpath, ":objectId"), c)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoRouter adds defined controller handler to BeeApp.
|
||||||
|
// it's same to App.AutoRouter.
|
||||||
|
// if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
|
||||||
|
// visit the url /main/list to exec List function or /main/page to exec Page function.
|
||||||
|
func AutoRouter(c ControllerInterface) *App {
|
||||||
|
BeeApp.Handlers.AddAuto(c)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoPrefix adds controller handler to BeeApp with prefix.
|
||||||
|
// it's same to App.AutoRouterWithPrefix.
|
||||||
|
// if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
|
||||||
|
// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
|
||||||
|
func AutoPrefix(prefix string, c ControllerInterface) *App {
|
||||||
|
BeeApp.Handlers.AddAutoPrefix(prefix, c)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get used to register router for Get method
|
||||||
|
// usage:
|
||||||
|
// beego.Get("/", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Get(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Get(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post used to register router for Post method
|
||||||
|
// usage:
|
||||||
|
// beego.Post("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Post(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Post(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete used to register router for Delete method
|
||||||
|
// usage:
|
||||||
|
// beego.Delete("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Delete(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Delete(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put used to register router for Put method
|
||||||
|
// usage:
|
||||||
|
// beego.Put("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Put(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Put(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head used to register router for Head method
|
||||||
|
// usage:
|
||||||
|
// beego.Head("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Head(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Head(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options used to register router for Options method
|
||||||
|
// usage:
|
||||||
|
// beego.Options("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Options(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Options(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch used to register router for Patch method
|
||||||
|
// usage:
|
||||||
|
// beego.Patch("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Patch(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Patch(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any used to register router for all methods
|
||||||
|
// usage:
|
||||||
|
// beego.Any("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Any(rootpath string, f FilterFunc) *App {
|
||||||
|
BeeApp.Handlers.Any(rootpath, f)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler used to register a Handler router
|
||||||
|
// usage:
|
||||||
|
// beego.Handler("/api", func(ctx *context.Context){
|
||||||
|
// ctx.Output.Body("hello world")
|
||||||
|
// })
|
||||||
|
func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
|
||||||
|
BeeApp.Handlers.Handler(rootpath, h, options...)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertFilter adds a FilterFunc with pattern condition and action constant.
|
||||||
|
// The pos means action constant including
|
||||||
|
// beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
|
||||||
|
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
||||||
|
func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App {
|
||||||
|
BeeApp.Handlers.InsertFilter(pattern, pos, filter, params...)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
298
beego.go
298
beego.go
@ -12,243 +12,27 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// 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 (
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/astaxie/beego/session"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// beego web framework version.
|
// beego web framework version.
|
||||||
const VERSION = "1.5.0"
|
const VERSION = "1.5.0"
|
||||||
|
|
||||||
type hookfunc func() error //hook function to run
|
//hook function to run
|
||||||
var hooks []hookfunc //hook function slice to store the hookfunc
|
type hookfunc func() error
|
||||||
|
|
||||||
// Router adds a patterned controller handler to BeeApp.
|
var (
|
||||||
// it's an alias method of App.Router.
|
hooks = make([]hookfunc, 0) //hook function slice to store the hookfunc
|
||||||
// usage:
|
)
|
||||||
// simple router
|
|
||||||
// beego.Router("/admin", &admin.UserController{})
|
|
||||||
// beego.Router("/admin/index", &admin.ArticleController{})
|
|
||||||
//
|
|
||||||
// regex router
|
|
||||||
//
|
|
||||||
// beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
|
||||||
//
|
|
||||||
// custom rules
|
|
||||||
// beego.Router("/api/list",&RestController{},"*:ListFood")
|
|
||||||
// beego.Router("/api/create",&RestController{},"post:CreateFood")
|
|
||||||
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
|
|
||||||
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
|
|
||||||
func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
|
|
||||||
BeeApp.Handlers.Add(rootpath, c, mappingMethods...)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Router add list from
|
// AddAPPStartHook is used to register the hookfunc
|
||||||
// usage:
|
// The hookfuncs will run in beego.Run()
|
||||||
// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
|
|
||||||
// type BankAccount struct{
|
|
||||||
// beego.Controller
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// register the function
|
|
||||||
// func (b *BankAccount)Mapping(){
|
|
||||||
// b.Mapping("ShowAccount" , b.ShowAccount)
|
|
||||||
// b.Mapping("ModifyAccount", b.ModifyAccount)
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
// //@router /account/:id [get]
|
|
||||||
// func (b *BankAccount) ShowAccount(){
|
|
||||||
// //logic
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// //@router /account/:id [post]
|
|
||||||
// func (b *BankAccount) ModifyAccount(){
|
|
||||||
// //logic
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// the comments @router url methodlist
|
|
||||||
// url support all the function Router's pattern
|
|
||||||
// methodlist [get post head put delete options *]
|
|
||||||
func Include(cList ...ControllerInterface) *App {
|
|
||||||
BeeApp.Handlers.Include(cList...)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTRouter adds a restful controller handler to BeeApp.
|
|
||||||
// its' controller implements beego.ControllerInterface and
|
|
||||||
// defines a param "pattern/:objectId" to visit each resource.
|
|
||||||
func RESTRouter(rootpath string, c ControllerInterface) *App {
|
|
||||||
Router(rootpath, c)
|
|
||||||
Router(path.Join(rootpath, ":objectId"), c)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// AutoRouter adds defined controller handler to BeeApp.
|
|
||||||
// it's same to App.AutoRouter.
|
|
||||||
// if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
|
|
||||||
// visit the url /main/list to exec List function or /main/page to exec Page function.
|
|
||||||
func AutoRouter(c ControllerInterface) *App {
|
|
||||||
BeeApp.Handlers.AddAuto(c)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// AutoPrefix adds controller handler to BeeApp with prefix.
|
|
||||||
// it's same to App.AutoRouterWithPrefix.
|
|
||||||
// if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
|
|
||||||
// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
|
|
||||||
func AutoPrefix(prefix string, c ControllerInterface) *App {
|
|
||||||
BeeApp.Handlers.AddAutoPrefix(prefix, c)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Get method
|
|
||||||
// usage:
|
|
||||||
// beego.Get("/", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Get(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Get(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Post method
|
|
||||||
// usage:
|
|
||||||
// beego.Post("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Post(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Post(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Delete method
|
|
||||||
// usage:
|
|
||||||
// beego.Delete("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Delete(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Delete(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Put method
|
|
||||||
// usage:
|
|
||||||
// beego.Put("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Put(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Put(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Head method
|
|
||||||
// usage:
|
|
||||||
// beego.Head("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Head(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Head(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Options method
|
|
||||||
// usage:
|
|
||||||
// beego.Options("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Options(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Options(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for Patch method
|
|
||||||
// usage:
|
|
||||||
// beego.Patch("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Patch(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Patch(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for all method
|
|
||||||
// usage:
|
|
||||||
// beego.Any("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Any(rootpath string, f FilterFunc) *App {
|
|
||||||
BeeApp.Handlers.Any(rootpath, f)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// register router for own Handler
|
|
||||||
// usage:
|
|
||||||
// beego.Handler("/api", func(ctx *context.Context){
|
|
||||||
// ctx.Output.Body("hello world")
|
|
||||||
// })
|
|
||||||
func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
|
|
||||||
BeeApp.Handlers.Handler(rootpath, h, options...)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetViewsPath sets view directory path in beego application.
|
|
||||||
func SetViewsPath(path string) *App {
|
|
||||||
ViewsPath = path
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetStaticPath sets static directory path and proper url pattern in beego application.
|
|
||||||
// if beego.SetStaticPath("static","public"), visit /static/* to load static file in folder "public".
|
|
||||||
func SetStaticPath(url string, path string) *App {
|
|
||||||
if !strings.HasPrefix(url, "/") {
|
|
||||||
url = "/" + url
|
|
||||||
}
|
|
||||||
url = strings.TrimRight(url, "/")
|
|
||||||
StaticDir[url] = path
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// DelStaticPath removes the static folder setting in this url pattern in beego application.
|
|
||||||
func DelStaticPath(url string) *App {
|
|
||||||
if !strings.HasPrefix(url, "/") {
|
|
||||||
url = "/" + url
|
|
||||||
}
|
|
||||||
url = strings.TrimRight(url, "/")
|
|
||||||
delete(StaticDir, url)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertFilter adds a FilterFunc with pattern condition and action constant.
|
|
||||||
// The pos means action constant including
|
|
||||||
// beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
|
|
||||||
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
|
||||||
func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App {
|
|
||||||
BeeApp.Handlers.InsertFilter(pattern, pos, filter, params...)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// The hookfunc will run in beego.Run()
|
|
||||||
// such as sessionInit, middlerware start, buildtemplate, admin start
|
// such as sessionInit, middlerware start, buildtemplate, admin start
|
||||||
func AddAPPStartHook(hf hookfunc) {
|
func AddAPPStartHook(hf hookfunc) {
|
||||||
hooks = append(hooks, hf)
|
hooks = append(hooks, hf)
|
||||||
@ -259,25 +43,22 @@ func AddAPPStartHook(hf hookfunc) {
|
|||||||
// beego.Run(":8089")
|
// beego.Run(":8089")
|
||||||
// beego.Run("127.0.0.1:8089")
|
// beego.Run("127.0.0.1:8089")
|
||||||
func Run(params ...string) {
|
func Run(params ...string) {
|
||||||
|
initBeforeHTTPRun()
|
||||||
|
|
||||||
if len(params) > 0 && params[0] != "" {
|
if len(params) > 0 && params[0] != "" {
|
||||||
strs := strings.Split(params[0], ":")
|
strs := strings.Split(params[0], ":")
|
||||||
if len(strs) > 0 && strs[0] != "" {
|
if len(strs) > 0 && strs[0] != "" {
|
||||||
HttpAddr = strs[0]
|
HTTPAddr = strs[0]
|
||||||
}
|
}
|
||||||
if len(strs) > 1 && strs[1] != "" {
|
if len(strs) > 1 && strs[1] != "" {
|
||||||
HttpPort, _ = strconv.Atoi(strs[1])
|
HTTPPort, _ = strconv.Atoi(strs[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initBeforeHttpRun()
|
|
||||||
|
|
||||||
if EnableAdmin {
|
|
||||||
go beeAdminApp.Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
BeeApp.Run()
|
BeeApp.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initBeforeHttpRun() {
|
func initBeforeHTTPRun() {
|
||||||
// if AppConfigPath not In the conf/app.conf reParse config
|
// if AppConfigPath not In the conf/app.conf reParse config
|
||||||
if AppConfigPath != filepath.Join(AppPath, "conf", "app.conf") {
|
if AppConfigPath != filepath.Join(AppPath, "conf", "app.conf") {
|
||||||
err := ParseConfig()
|
err := ParseConfig()
|
||||||
@ -287,53 +68,22 @@ func initBeforeHttpRun() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//init mime
|
//init hooks
|
||||||
AddAPPStartHook(initMime)
|
AddAPPStartHook(registerMime)
|
||||||
|
AddAPPStartHook(registerDefaultErrorHandler)
|
||||||
|
AddAPPStartHook(registerSession)
|
||||||
|
AddAPPStartHook(registerDocs)
|
||||||
|
AddAPPStartHook(registerTemplate)
|
||||||
|
AddAPPStartHook(registerAdmin)
|
||||||
|
|
||||||
// do hooks function
|
|
||||||
for _, hk := range hooks {
|
for _, hk := range hooks {
|
||||||
err := hk()
|
if err := hk(); err != nil {
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if SessionOn {
|
|
||||||
var err error
|
|
||||||
sessionConfig := AppConfig.String("sessionConfig")
|
|
||||||
if sessionConfig == "" {
|
|
||||||
sessionConfig = `{"cookieName":"` + SessionName + `",` +
|
|
||||||
`"gclifetime":` + strconv.FormatInt(SessionGCMaxLifetime, 10) + `,` +
|
|
||||||
`"providerConfig":"` + filepath.ToSlash(SessionSavePath) + `",` +
|
|
||||||
`"secure":` + strconv.FormatBool(EnableHttpTLS) + `,` +
|
|
||||||
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
|
|
||||||
`"domain":"` + SessionDomain + `",` +
|
|
||||||
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
|
|
||||||
}
|
|
||||||
GlobalSessions, err = session.NewManager(SessionProvider,
|
|
||||||
sessionConfig)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
go GlobalSessions.GC()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := BuildTemplate(ViewsPath)
|
// TestBeegoInit is for test package init
|
||||||
if err != nil {
|
|
||||||
if RunMode == "dev" {
|
|
||||||
Warn(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerDefaultErrorHandler()
|
|
||||||
|
|
||||||
if EnableDocs {
|
|
||||||
Get("/docs", serverDocs)
|
|
||||||
Get("/docs/*", serverDocs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function is for test package init
|
|
||||||
func TestBeegoInit(apppath string) {
|
func TestBeegoInit(apppath string) {
|
||||||
AppPath = apppath
|
AppPath = apppath
|
||||||
os.Setenv("BEEGO_RUNMODE", "test")
|
os.Setenv("BEEGO_RUNMODE", "test")
|
||||||
@ -344,9 +94,5 @@ func TestBeegoInit(apppath string) {
|
|||||||
Info(err)
|
Info(err)
|
||||||
}
|
}
|
||||||
os.Chdir(AppPath)
|
os.Chdir(AppPath)
|
||||||
initBeforeHttpRun()
|
initBeforeHTTPRun()
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
hooks = make([]hookfunc, 0)
|
|
||||||
}
|
}
|
||||||
|
4
cache/README.md
vendored
4
cache/README.md
vendored
@ -43,7 +43,7 @@ interval means the gc time. The cache will check at each time interval, whether
|
|||||||
|
|
||||||
## Memcache adapter
|
## Memcache adapter
|
||||||
|
|
||||||
Memcache adapter use the vitess's [Memcache](http://code.google.com/p/vitess/go/memcache) client.
|
Memcache adapter use the [gomemcache](http://github.com/bradfitz/gomemcache) client.
|
||||||
|
|
||||||
Configure like this:
|
Configure like this:
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ Configure like this:
|
|||||||
|
|
||||||
## Redis adapter
|
## Redis adapter
|
||||||
|
|
||||||
Redis adapter use the [redigo](http://github.com/garyburd/redigo/redis) client.
|
Redis adapter use the [redigo](http://github.com/garyburd/redigo) client.
|
||||||
|
|
||||||
Configure like this:
|
Configure like this:
|
||||||
|
|
||||||
|
3
cache/cache.go
vendored
3
cache/cache.go
vendored
@ -12,6 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package cache provide a Cache interface and some implemetn engine
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// import(
|
// import(
|
||||||
@ -80,7 +81,7 @@ func Register(name string, adapter Cache) {
|
|||||||
adapters[name] = adapter
|
adapters[name] = adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new cache driver by adapter name and config string.
|
// NewCache 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) (adapter Cache, err error) {
|
func NewCache(adapterName, config string) (adapter Cache, err error) {
|
||||||
|
12
cache/conv.go
vendored
12
cache/conv.go
vendored
@ -19,7 +19,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// convert interface to string.
|
// GetString convert interface to string.
|
||||||
func GetString(v interface{}) string {
|
func GetString(v interface{}) string {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
@ -34,7 +34,7 @@ func GetString(v interface{}) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to int.
|
// GetInt convert interface to int.
|
||||||
func GetInt(v interface{}) int {
|
func GetInt(v interface{}) int {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case int:
|
case int:
|
||||||
@ -52,7 +52,7 @@ func GetInt(v interface{}) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to int64.
|
// GetInt64 convert interface to int64.
|
||||||
func GetInt64(v interface{}) int64 {
|
func GetInt64(v interface{}) int64 {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case int:
|
case int:
|
||||||
@ -71,7 +71,7 @@ func GetInt64(v interface{}) int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to float64.
|
// GetFloat64 convert interface to float64.
|
||||||
func GetFloat64(v interface{}) float64 {
|
func GetFloat64(v interface{}) float64 {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@ -85,7 +85,7 @@ func GetFloat64(v interface{}) float64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to bool.
|
// GetBool convert interface to bool.
|
||||||
func GetBool(v interface{}) bool {
|
func GetBool(v interface{}) bool {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
@ -99,7 +99,7 @@ func GetBool(v interface{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert interface to byte slice.
|
// getByteArray convert interface to byte slice.
|
||||||
func getByteArray(v interface{}) []byte {
|
func getByteArray(v interface{}) []byte {
|
||||||
switch result := v.(type) {
|
switch result := v.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
|
14
cache/conv_test.go
vendored
14
cache/conv_test.go
vendored
@ -27,7 +27,7 @@ func TestGetString(t *testing.T) {
|
|||||||
if "test2" != GetString(t2) {
|
if "test2" != GetString(t2) {
|
||||||
t.Error("get string from byte array error")
|
t.Error("get string from byte array error")
|
||||||
}
|
}
|
||||||
var t3 int = 1
|
var t3 = 1
|
||||||
if "1" != GetString(t3) {
|
if "1" != GetString(t3) {
|
||||||
t.Error("get string from int error")
|
t.Error("get string from int error")
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ func TestGetString(t *testing.T) {
|
|||||||
if "1" != GetString(t4) {
|
if "1" != GetString(t4) {
|
||||||
t.Error("get string from int64 error")
|
t.Error("get string from int64 error")
|
||||||
}
|
}
|
||||||
var t5 float64 = 1.1
|
var t5 = 1.1
|
||||||
if "1.1" != GetString(t5) {
|
if "1.1" != GetString(t5) {
|
||||||
t.Error("get string from float64 error")
|
t.Error("get string from float64 error")
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ func TestGetString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInt(t *testing.T) {
|
func TestGetInt(t *testing.T) {
|
||||||
var t1 int = 1
|
var t1 = 1
|
||||||
if 1 != GetInt(t1) {
|
if 1 != GetInt(t1) {
|
||||||
t.Error("get int from int error")
|
t.Error("get int from int error")
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func TestGetInt(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetInt64(t *testing.T) {
|
func TestGetInt64(t *testing.T) {
|
||||||
var i int64 = 1
|
var i int64 = 1
|
||||||
var t1 int = 1
|
var t1 = 1
|
||||||
if i != GetInt64(t1) {
|
if i != GetInt64(t1) {
|
||||||
t.Error("get int64 from int error")
|
t.Error("get int64 from int error")
|
||||||
}
|
}
|
||||||
@ -91,12 +91,12 @@ func TestGetInt64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFloat64(t *testing.T) {
|
func TestGetFloat64(t *testing.T) {
|
||||||
var f float64 = 1.11
|
var f = 1.11
|
||||||
var t1 float32 = 1.11
|
var t1 float32 = 1.11
|
||||||
if f != GetFloat64(t1) {
|
if f != GetFloat64(t1) {
|
||||||
t.Error("get float64 from float32 error")
|
t.Error("get float64 from float32 error")
|
||||||
}
|
}
|
||||||
var t2 float64 = 1.11
|
var t2 = 1.11
|
||||||
if f != GetFloat64(t2) {
|
if f != GetFloat64(t2) {
|
||||||
t.Error("get float64 from float64 error")
|
t.Error("get float64 from float64 error")
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ func TestGetFloat64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var f2 float64 = 1
|
var f2 float64 = 1
|
||||||
var t4 int = 1
|
var t4 = 1
|
||||||
if f2 != GetFloat64(t4) {
|
if f2 != GetFloat64(t4) {
|
||||||
t.Error("get float64 from int error")
|
t.Error("get float64 from int error")
|
||||||
}
|
}
|
||||||
|
45
cache/file.go
vendored
45
cache/file.go
vendored
@ -41,11 +41,12 @@ type FileCacheItem struct {
|
|||||||
Expired int64
|
Expired int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileCache Config
|
||||||
var (
|
var (
|
||||||
FileCachePath string = "cache" // cache directory
|
FileCachePath = "cache" // cache directory
|
||||||
FileCacheFileSuffix string = ".bin" // cache file suffix
|
FileCacheFileSuffix = ".bin" // cache file suffix
|
||||||
FileCacheDirectoryLevel int = 2 // cache file deep level if auto generated cache files.
|
FileCacheDirectoryLevel = 2 // cache file deep level if auto generated cache files.
|
||||||
FileCacheEmbedExpiry int64 = 0 // cache expire time, default is no expire forever.
|
FileCacheEmbedExpiry int64 // cache expire time, default is no expire forever.
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileCache is cache adapter for file storage.
|
// FileCache is cache adapter for file storage.
|
||||||
@ -56,14 +57,14 @@ type FileCache struct {
|
|||||||
EmbedExpiry int
|
EmbedExpiry int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new file cache with no config.
|
// NewFileCache Create new file cache with no config.
|
||||||
// the level and expiry need set in method StartAndGC as config string.
|
// the level and expiry need set in method StartAndGC as config string.
|
||||||
func NewFileCache() *FileCache {
|
func NewFileCache() *FileCache {
|
||||||
// return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix}
|
// return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix}
|
||||||
return &FileCache{}
|
return &FileCache{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start and begin gc for file cache.
|
// StartAndGC will 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 (fc *FileCache) StartAndGC(config string) error {
|
func (fc *FileCache) StartAndGC(config string) error {
|
||||||
|
|
||||||
@ -120,12 +121,12 @@ func (fc *FileCache) getCacheFileName(key string) string {
|
|||||||
// 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 (fc *FileCache) Get(key string) interface{} {
|
func (fc *FileCache) Get(key string) interface{} {
|
||||||
fileData, err := File_get_contents(fc.getCacheFileName(key))
|
fileData, err := FileGetContents(fc.getCacheFileName(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
var to FileCacheItem
|
var to FileCacheItem
|
||||||
Gob_decode(fileData, &to)
|
GobDecode(fileData, &to)
|
||||||
if to.Expired < time.Now().Unix() {
|
if to.Expired < time.Now().Unix() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -155,11 +156,11 @@ func (fc *FileCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
item.Expired = time.Now().Unix() + timeout
|
item.Expired = time.Now().Unix() + timeout
|
||||||
}
|
}
|
||||||
item.Lastaccess = time.Now().Unix()
|
item.Lastaccess = time.Now().Unix()
|
||||||
data, err := Gob_encode(item)
|
data, err := GobEncode(item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return File_put_contents(fc.getCacheFileName(key), data)
|
return FilePutContents(fc.getCacheFileName(key), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete file cache value.
|
// Delete file cache value.
|
||||||
@ -171,7 +172,7 @@ func (fc *FileCache) Delete(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase cached int value.
|
// Incr will increase cached int value.
|
||||||
// fc value is saving forever unless Delete.
|
// fc value is saving forever unless Delete.
|
||||||
func (fc *FileCache) Incr(key string) error {
|
func (fc *FileCache) Incr(key string) error {
|
||||||
data := fc.Get(key)
|
data := fc.Get(key)
|
||||||
@ -185,7 +186,7 @@ func (fc *FileCache) Incr(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrease cached int value.
|
// Decr will decrease cached int value.
|
||||||
func (fc *FileCache) Decr(key string) error {
|
func (fc *FileCache) Decr(key string) error {
|
||||||
data := fc.Get(key)
|
data := fc.Get(key)
|
||||||
var decr int
|
var decr int
|
||||||
@ -198,13 +199,13 @@ func (fc *FileCache) Decr(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check value is exist.
|
// IsExist check value is exist.
|
||||||
func (fc *FileCache) IsExist(key string) bool {
|
func (fc *FileCache) IsExist(key string) bool {
|
||||||
ret, _ := exists(fc.getCacheFileName(key))
|
ret, _ := exists(fc.getCacheFileName(key))
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean cached files.
|
// ClearAll will clean cached files.
|
||||||
// not implemented.
|
// not implemented.
|
||||||
func (fc *FileCache) ClearAll() error {
|
func (fc *FileCache) ClearAll() error {
|
||||||
return nil
|
return nil
|
||||||
@ -222,9 +223,9 @@ func exists(path string) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get bytes to file.
|
// FileGetContents Get bytes to file.
|
||||||
// if non-exist, create this file.
|
// if non-exist, create this file.
|
||||||
func File_get_contents(filename string) (data []byte, e error) {
|
func FileGetContents(filename string) (data []byte, e error) {
|
||||||
f, e := 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 e != nil {
|
if e != nil {
|
||||||
return
|
return
|
||||||
@ -242,9 +243,9 @@ func File_get_contents(filename string) (data []byte, e error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put bytes to file.
|
// FilePutContents Put bytes to file.
|
||||||
// if non-exist, create this file.
|
// if non-exist, create this file.
|
||||||
func File_put_contents(filename string, content []byte) error {
|
func FilePutContents(filename string, content []byte) error {
|
||||||
fp, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
fp, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -254,8 +255,8 @@ func File_put_contents(filename string, content []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gob encodes file cache item.
|
// GobEncode Gob encodes file cache item.
|
||||||
func Gob_encode(data interface{}) ([]byte, error) {
|
func GobEncode(data interface{}) ([]byte, error) {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
enc := gob.NewEncoder(buf)
|
enc := gob.NewEncoder(buf)
|
||||||
err := enc.Encode(data)
|
err := enc.Encode(data)
|
||||||
@ -265,8 +266,8 @@ func Gob_encode(data interface{}) ([]byte, error) {
|
|||||||
return buf.Bytes(), err
|
return buf.Bytes(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gob decodes file cache item.
|
// GobDecode Gob decodes file cache item.
|
||||||
func Gob_decode(data []byte, to *FileCacheItem) error {
|
func GobDecode(data []byte, to *FileCacheItem) error {
|
||||||
buf := bytes.NewBuffer(data)
|
buf := bytes.NewBuffer(data)
|
||||||
dec := gob.NewDecoder(buf)
|
dec := gob.NewDecoder(buf)
|
||||||
return dec.Decode(&to)
|
return dec.Decode(&to)
|
||||||
|
53
cache/memcache/memcache.go
vendored
53
cache/memcache/memcache.go
vendored
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// package memcahe for cache provider
|
// Package memcache for cache provider
|
||||||
//
|
//
|
||||||
// depend on github.com/bradfitz/gomemcache/memcache
|
// depend on github.com/bradfitz/gomemcache/memcache
|
||||||
//
|
//
|
||||||
@ -39,19 +39,19 @@ import (
|
|||||||
"github.com/astaxie/beego/cache"
|
"github.com/astaxie/beego/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Memcache adapter.
|
// Cache Memcache adapter.
|
||||||
type MemcacheCache struct {
|
type Cache struct {
|
||||||
conn *memcache.Client
|
conn *memcache.Client
|
||||||
conninfo []string
|
conninfo []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new memcache adapter.
|
// NewMemCache create new memcache adapter.
|
||||||
func NewMemCache() *MemcacheCache {
|
func NewMemCache() *Cache {
|
||||||
return &MemcacheCache{}
|
return &Cache{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get value from memcache.
|
// Get get value from memcache.
|
||||||
func (rc *MemcacheCache) Get(key string) interface{} {
|
func (rc *Cache) Get(key string) interface{} {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -63,8 +63,8 @@ func (rc *MemcacheCache) Get(key string) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get value from memcache.
|
// GetMulti get value from memcache.
|
||||||
func (rc *MemcacheCache) GetMulti(keys []string) []interface{} {
|
func (rc *Cache) GetMulti(keys []string) []interface{} {
|
||||||
size := len(keys)
|
size := len(keys)
|
||||||
var rv []interface{}
|
var rv []interface{}
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
@ -81,16 +81,15 @@ func (rc *MemcacheCache) GetMulti(keys []string) []interface{} {
|
|||||||
rv = append(rv, string(v.Value))
|
rv = append(rv, string(v.Value))
|
||||||
}
|
}
|
||||||
return rv
|
return rv
|
||||||
} else {
|
}
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
rv = append(rv, err)
|
rv = append(rv, err)
|
||||||
}
|
}
|
||||||
return rv
|
return rv
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// put value to memcache. only support string.
|
// Put put value to memcache. only support string.
|
||||||
func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
|
func (rc *Cache) Put(key string, val interface{}, timeout int64) error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -104,8 +103,8 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
return rc.conn.Set(&item)
|
return rc.conn.Set(&item)
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete value in memcache.
|
// Delete delete value in memcache.
|
||||||
func (rc *MemcacheCache) Delete(key string) error {
|
func (rc *Cache) Delete(key string) error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -114,8 +113,8 @@ func (rc *MemcacheCache) Delete(key string) error {
|
|||||||
return rc.conn.Delete(key)
|
return rc.conn.Delete(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase counter.
|
// Incr increase counter.
|
||||||
func (rc *MemcacheCache) Incr(key string) error {
|
func (rc *Cache) Incr(key string) error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -125,8 +124,8 @@ func (rc *MemcacheCache) Incr(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease counter.
|
// Decr decrease counter.
|
||||||
func (rc *MemcacheCache) Decr(key string) error {
|
func (rc *Cache) Decr(key string) error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -136,8 +135,8 @@ func (rc *MemcacheCache) Decr(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check value exists in memcache.
|
// IsExist check value exists in memcache.
|
||||||
func (rc *MemcacheCache) IsExist(key string) bool {
|
func (rc *Cache) IsExist(key string) bool {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return false
|
return false
|
||||||
@ -150,8 +149,8 @@ func (rc *MemcacheCache) IsExist(key string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear all cached in memcache.
|
// ClearAll clear all cached in memcache.
|
||||||
func (rc *MemcacheCache) ClearAll() error {
|
func (rc *Cache) ClearAll() error {
|
||||||
if rc.conn == nil {
|
if rc.conn == nil {
|
||||||
if err := rc.connectInit(); err != nil {
|
if err := rc.connectInit(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -160,10 +159,10 @@ func (rc *MemcacheCache) ClearAll() error {
|
|||||||
return rc.conn.FlushAll()
|
return rc.conn.FlushAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
// start memcache adapter.
|
// StartAndGC start memcache adapter.
|
||||||
// config string is like {"conn":"connection info"}.
|
// config string is like {"conn":"connection info"}.
|
||||||
// if connecting error, return.
|
// if connecting error, return.
|
||||||
func (rc *MemcacheCache) StartAndGC(config string) error {
|
func (rc *Cache) StartAndGC(config string) error {
|
||||||
var cf map[string]string
|
var cf map[string]string
|
||||||
json.Unmarshal([]byte(config), &cf)
|
json.Unmarshal([]byte(config), &cf)
|
||||||
if _, ok := cf["conn"]; !ok {
|
if _, ok := cf["conn"]; !ok {
|
||||||
@ -179,7 +178,7 @@ func (rc *MemcacheCache) StartAndGC(config string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect to memcache and keep the connection.
|
// connect to memcache and keep the connection.
|
||||||
func (rc *MemcacheCache) connectInit() error {
|
func (rc *Cache) connectInit() error {
|
||||||
rc.conn = memcache.New(rc.conninfo...)
|
rc.conn = memcache.New(rc.conninfo...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
2
cache/memcache/memcache_test.go
vendored
2
cache/memcache/memcache_test.go
vendored
@ -23,7 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRedisCache(t *testing.T) {
|
func TestMemcacheCache(t *testing.T) {
|
||||||
bm, err := cache.NewCache("memcache", `{"conn": "127.0.0.1:11211"}`)
|
bm, err := cache.NewCache("memcache", `{"conn": "127.0.0.1:11211"}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("init err")
|
t.Error("init err")
|
||||||
|
26
cache/memory.go
vendored
26
cache/memory.go
vendored
@ -23,18 +23,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// clock time of recycling the expired cache items in memory.
|
// DefaultEvery means the clock time of recycling the expired cache items in memory.
|
||||||
DefaultEvery int = 60 // 1 minute
|
DefaultEvery = 60 // 1 minute
|
||||||
)
|
)
|
||||||
|
|
||||||
// Memory cache item.
|
// MemoryItem store enery cache item.
|
||||||
type MemoryItem struct {
|
type MemoryItem struct {
|
||||||
val interface{}
|
val interface{}
|
||||||
Lastaccess time.Time
|
Lastaccess time.Time
|
||||||
expired int64
|
expired int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory cache adapter.
|
// MemoryCache is Memory cache adapter.
|
||||||
// it contains a RW locker for safe map storage.
|
// it contains a RW locker for safe map storage.
|
||||||
type MemoryCache struct {
|
type MemoryCache struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
@ -87,7 +87,7 @@ func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete cache in memory.
|
// Delete cache in memory.
|
||||||
func (bc *MemoryCache) Delete(name string) error {
|
func (bc *MemoryCache) Delete(name string) error {
|
||||||
bc.lock.Lock()
|
bc.lock.Lock()
|
||||||
defer bc.lock.Unlock()
|
defer bc.lock.Unlock()
|
||||||
@ -101,7 +101,7 @@ func (bc *MemoryCache) Delete(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase cache counter in memory.
|
// Incr increase cache counter in memory.
|
||||||
// it supports int,int64,int32,uint,uint64,uint32.
|
// it supports int,int64,int32,uint,uint64,uint32.
|
||||||
func (bc *MemoryCache) Incr(key string) error {
|
func (bc *MemoryCache) Incr(key string) error {
|
||||||
bc.lock.RLock()
|
bc.lock.RLock()
|
||||||
@ -129,7 +129,7 @@ func (bc *MemoryCache) Incr(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrease counter in memory.
|
// Decr decrease counter in memory.
|
||||||
func (bc *MemoryCache) Decr(key string) error {
|
func (bc *MemoryCache) Decr(key string) error {
|
||||||
bc.lock.RLock()
|
bc.lock.RLock()
|
||||||
defer bc.lock.RUnlock()
|
defer bc.lock.RUnlock()
|
||||||
@ -168,7 +168,7 @@ func (bc *MemoryCache) Decr(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// check cache exist in memory.
|
// IsExist check cache exist in memory.
|
||||||
func (bc *MemoryCache) IsExist(name string) bool {
|
func (bc *MemoryCache) IsExist(name string) bool {
|
||||||
bc.lock.RLock()
|
bc.lock.RLock()
|
||||||
defer bc.lock.RUnlock()
|
defer bc.lock.RUnlock()
|
||||||
@ -176,7 +176,7 @@ func (bc *MemoryCache) IsExist(name string) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete all cache in memory.
|
// ClearAll will delete all cache in memory.
|
||||||
func (bc *MemoryCache) ClearAll() error {
|
func (bc *MemoryCache) ClearAll() error {
|
||||||
bc.lock.Lock()
|
bc.lock.Lock()
|
||||||
defer bc.lock.Unlock()
|
defer bc.lock.Unlock()
|
||||||
@ -184,7 +184,7 @@ func (bc *MemoryCache) ClearAll() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// start memory cache. it will check expiration in every clock time.
|
// StartAndGC start memory cache. it will check expiration in every clock time.
|
||||||
func (bc *MemoryCache) StartAndGC(config string) error {
|
func (bc *MemoryCache) StartAndGC(config string) error {
|
||||||
var cf map[string]int
|
var cf map[string]int
|
||||||
json.Unmarshal([]byte(config), &cf)
|
json.Unmarshal([]byte(config), &cf)
|
||||||
@ -213,13 +213,13 @@ func (bc *MemoryCache) vaccuum() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for name := range bc.items {
|
for name := range bc.items {
|
||||||
bc.item_expired(name)
|
bc.itemExpired(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// item_expired returns true if an item is expired.
|
// itemExpired returns true if an item is expired.
|
||||||
func (bc *MemoryCache) item_expired(name string) bool {
|
func (bc *MemoryCache) itemExpired(name string) bool {
|
||||||
bc.lock.Lock()
|
bc.lock.Lock()
|
||||||
defer bc.lock.Unlock()
|
defer bc.lock.Unlock()
|
||||||
itm, ok := bc.items[name]
|
itm, ok := bc.items[name]
|
||||||
|
52
cache/redis/redis.go
vendored
52
cache/redis/redis.go
vendored
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// package redis for cache provider
|
// Package redis for cache provider
|
||||||
//
|
//
|
||||||
// depend on github.com/garyburd/redigo/redis
|
// depend on github.com/garyburd/redigo/redis
|
||||||
//
|
//
|
||||||
@ -41,12 +41,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// the collection name of redis for cache adapter.
|
// DefaultKey the collection name of redis for cache adapter.
|
||||||
DefaultKey string = "beecacheRedis"
|
DefaultKey = "beecacheRedis"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Redis cache adapter.
|
// Cache is Redis cache adapter.
|
||||||
type RedisCache struct {
|
type Cache struct {
|
||||||
p *redis.Pool // redis connection pool
|
p *redis.Pool // redis connection pool
|
||||||
conninfo string
|
conninfo string
|
||||||
dbNum int
|
dbNum int
|
||||||
@ -54,13 +54,13 @@ type RedisCache struct {
|
|||||||
password string
|
password string
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new redis cache with default collection name.
|
// NewRedisCache create new redis cache with default collection name.
|
||||||
func NewRedisCache() *RedisCache {
|
func NewRedisCache() *Cache {
|
||||||
return &RedisCache{key: DefaultKey}
|
return &Cache{key: DefaultKey}
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually do the redis cmds
|
// actually do the redis cmds
|
||||||
func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interface{}, err error) {
|
func (rc *Cache) do(commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||||
c := rc.p.Get()
|
c := rc.p.Get()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ 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 *Cache) Get(key string) interface{} {
|
||||||
if v, err := rc.do("GET", key); err == nil {
|
if v, err := rc.do("GET", key); err == nil {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ func (rc *RedisCache) Get(key string) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetMulti get cache from redis.
|
// GetMulti get cache from redis.
|
||||||
func (rc *RedisCache) GetMulti(keys []string) []interface{} {
|
func (rc *Cache) GetMulti(keys []string) []interface{} {
|
||||||
size := len(keys)
|
size := len(keys)
|
||||||
var rv []interface{}
|
var rv []interface{}
|
||||||
c := rc.p.Get()
|
c := rc.p.Get()
|
||||||
@ -108,8 +108,8 @@ ERROR:
|
|||||||
return rv
|
return rv
|
||||||
}
|
}
|
||||||
|
|
||||||
// put cache to redis.
|
// Put put cache to redis.
|
||||||
func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
|
func (rc *Cache) Put(key string, val interface{}, timeout int64) error {
|
||||||
var err error
|
var err error
|
||||||
if _, err = rc.do("SETEX", key, timeout, val); err != nil {
|
if _, err = rc.do("SETEX", key, timeout, val); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -121,8 +121,8 @@ func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete cache in redis.
|
// Delete delete cache in redis.
|
||||||
func (rc *RedisCache) Delete(key string) error {
|
func (rc *Cache) Delete(key string) error {
|
||||||
var err error
|
var err error
|
||||||
if _, err = rc.do("DEL", key); err != nil {
|
if _, err = rc.do("DEL", key); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -131,8 +131,8 @@ func (rc *RedisCache) Delete(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check cache's existence in redis.
|
// IsExist check cache's existence in redis.
|
||||||
func (rc *RedisCache) IsExist(key string) bool {
|
func (rc *Cache) IsExist(key string) bool {
|
||||||
v, err := redis.Bool(rc.do("EXISTS", key))
|
v, err := redis.Bool(rc.do("EXISTS", key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
@ -145,20 +145,20 @@ func (rc *RedisCache) IsExist(key string) bool {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase counter in redis.
|
// Incr increase counter in redis.
|
||||||
func (rc *RedisCache) Incr(key string) error {
|
func (rc *Cache) Incr(key string) error {
|
||||||
_, err := redis.Bool(rc.do("INCRBY", key, 1))
|
_, err := redis.Bool(rc.do("INCRBY", key, 1))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrease counter in redis.
|
// Decr decrease counter in redis.
|
||||||
func (rc *RedisCache) Decr(key string) error {
|
func (rc *Cache) Decr(key string) error {
|
||||||
_, err := redis.Bool(rc.do("INCRBY", key, -1))
|
_, err := redis.Bool(rc.do("INCRBY", key, -1))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean all cache in redis. delete this redis collection.
|
// ClearAll clean all cache in redis. delete this redis collection.
|
||||||
func (rc *RedisCache) ClearAll() error {
|
func (rc *Cache) ClearAll() error {
|
||||||
cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key))
|
cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -172,11 +172,11 @@ func (rc *RedisCache) ClearAll() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// start redis cache adapter.
|
// StartAndGC start redis cache adapter.
|
||||||
// config is like {"key":"collection key","conn":"connection info","dbNum":"0"}
|
// config is like {"key":"collection key","conn":"connection info","dbNum":"0"}
|
||||||
// the cache item in redis are stored forever,
|
// the cache item in redis are stored forever,
|
||||||
// so no gc operation.
|
// so no gc operation.
|
||||||
func (rc *RedisCache) StartAndGC(config string) error {
|
func (rc *Cache) StartAndGC(config string) error {
|
||||||
var cf map[string]string
|
var cf map[string]string
|
||||||
json.Unmarshal([]byte(config), &cf)
|
json.Unmarshal([]byte(config), &cf)
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ func (rc *RedisCache) StartAndGC(config string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect to redis.
|
// connect to redis.
|
||||||
func (rc *RedisCache) connectInit() {
|
func (rc *Cache) connectInit() {
|
||||||
dialFunc := func() (c redis.Conn, err error) {
|
dialFunc := func() (c redis.Conn, err error) {
|
||||||
c, err = redis.Dial("tcp", rc.conninfo)
|
c, err = redis.Dial("tcp", rc.conninfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
231
config.go
231
config.go
@ -29,60 +29,115 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BeeApp *App // beego application
|
// AccessLogs represent whether output the access logs, default is false
|
||||||
AppName string
|
AccessLogs bool
|
||||||
AppPath string
|
// AdminHTTPAddr is address for admin
|
||||||
workPath string
|
AdminHTTPAddr string
|
||||||
AppConfigPath string
|
// AdminHTTPPort is listens port for admin
|
||||||
StaticDir map[string]string
|
AdminHTTPPort int
|
||||||
TemplateCache map[string]*template.Template // template caching map
|
// AppConfig is the instance of Config, store the config information from file
|
||||||
StaticExtensionsToGzip []string // files with should be compressed with gzip (.js,.css,etc)
|
|
||||||
EnableHttpListen bool
|
|
||||||
HttpAddr string
|
|
||||||
HttpPort int
|
|
||||||
ListenTCP4 bool
|
|
||||||
EnableHttpTLS bool
|
|
||||||
HttpsPort int
|
|
||||||
HttpCertFile string
|
|
||||||
HttpKeyFile string
|
|
||||||
RecoverPanic bool // flag of auto recover panic
|
|
||||||
AutoRender bool // flag of render template automatically
|
|
||||||
ViewsPath string
|
|
||||||
AppConfig *beegoAppConfig
|
AppConfig *beegoAppConfig
|
||||||
RunMode string // run mode, "dev" or "prod"
|
// AppName represent Application name, always the project folder name
|
||||||
GlobalSessions *session.Manager // global session mananger
|
AppName string
|
||||||
SessionOn bool // flag of starting session auto. default is false.
|
// AppPath is the path to the application
|
||||||
SessionProvider string // default session provider, memory, mysql , redis ,etc.
|
AppPath string
|
||||||
SessionName string // the cookie name when saving session id into cookie.
|
// AppConfigPath is the path to the config files
|
||||||
SessionGCMaxLifetime int64 // session gc time for auto cleaning expired session.
|
AppConfigPath string
|
||||||
SessionSavePath string // if use mysql/redis/file provider, define save path to connection info.
|
// AppConfigProvider is the provider for the config, default is ini
|
||||||
SessionCookieLifeTime int // the life time of session id in cookie.
|
AppConfigProvider string
|
||||||
SessionAutoSetCookie bool // auto setcookie
|
// AutoRender is a flag of render template automatically. It's always turn off in API application
|
||||||
SessionDomain string // the cookie domain default is empty
|
// default is true
|
||||||
UseFcgi bool
|
AutoRender bool
|
||||||
UseStdIo bool
|
// BeegoServerName exported in response header.
|
||||||
|
BeegoServerName string
|
||||||
|
// CopyRequestBody is just useful for raw request body in context. default is false
|
||||||
|
CopyRequestBody bool
|
||||||
|
// DirectoryIndex wheather display directory index. default is false.
|
||||||
|
DirectoryIndex bool
|
||||||
|
// EnableAdmin means turn on admin module to log every request info.
|
||||||
|
EnableAdmin bool
|
||||||
|
// EnableDocs enable generate docs & server docs API Swagger
|
||||||
|
EnableDocs bool
|
||||||
|
// EnableErrorsShow wheather show errors in page. if true, show error and trace info in page rendered with error template.
|
||||||
|
EnableErrorsShow bool
|
||||||
|
// EnabelFcgi turn on the fcgi Listen, default is false
|
||||||
|
EnabelFcgi bool
|
||||||
|
// EnableGzip means gzip the response
|
||||||
|
EnableGzip bool
|
||||||
|
// EnableHTTPListen represent whether turn on the HTTP, default is true
|
||||||
|
EnableHTTPListen bool
|
||||||
|
// EnableHTTPTLS represent whether turn on the HTTPS, default is true
|
||||||
|
EnableHTTPTLS bool
|
||||||
|
// EnableStdIo works with EnabelFcgi Use FCGI via standard I/O
|
||||||
|
EnableStdIo bool
|
||||||
|
// EnableXSRF whether turn on xsrf. default is false
|
||||||
|
EnableXSRF bool
|
||||||
|
// FlashName is the name of the flash variable found in response header and cookie
|
||||||
|
FlashName string
|
||||||
|
// FlashSeperator used to seperate flash key:value, default is BEEGOFLASH
|
||||||
|
FlashSeperator string
|
||||||
|
// GlobalSessions is the instance for the session manager
|
||||||
|
GlobalSessions *session.Manager
|
||||||
|
// Graceful means use graceful module to start the server
|
||||||
|
Graceful bool
|
||||||
|
// workPath is always the same as AppPath, but sometime when it started with other
|
||||||
|
// program, like supervisor
|
||||||
|
workPath string
|
||||||
|
// ListenTCP4 represent only Listen in TCP4, default is false
|
||||||
|
ListenTCP4 bool
|
||||||
|
// MaxMemory The whole request body is parsed and up to a total of maxMemory
|
||||||
|
// bytes of its file parts are stored in memory, with the remainder stored on disk in temporary files
|
||||||
MaxMemory int64
|
MaxMemory int64
|
||||||
EnableGzip bool // flag of enable gzip
|
// HTTPAddr is the TCP network address addr for HTTP
|
||||||
DirectoryIndex bool // flag of display directory index. default is false.
|
HTTPAddr string
|
||||||
HttpServerTimeOut int64
|
// HTTPPort is listens port for HTTP
|
||||||
ErrorsShow bool // flag of show errors in page. if true, show error and trace info in page rendered with error template.
|
HTTPPort int
|
||||||
XSRFKEY string // xsrf hash salt string.
|
// HTTPSPort is listens port for HTTPS
|
||||||
EnableXSRF bool // flag of enable xsrf.
|
HTTPSPort int
|
||||||
XSRFExpire int // the expiry of xsrf value.
|
// HTTPCertFile is the path to certificate file
|
||||||
CopyRequestBody bool // flag of copy raw request body in context.
|
HTTPCertFile string
|
||||||
|
// HTTPKeyFile is the path to private key file
|
||||||
|
HTTPKeyFile string
|
||||||
|
// HTTPServerTimeOut HTTP server timeout. default is 0, no timeout
|
||||||
|
HTTPServerTimeOut int64
|
||||||
|
// RecoverPanic is a flag for auto recover panic, default is true
|
||||||
|
RecoverPanic bool
|
||||||
|
// RouterCaseSensitive means whether router case sensitive, default is true
|
||||||
|
RouterCaseSensitive bool
|
||||||
|
// RunMode represent the staging, "dev" or "prod"
|
||||||
|
RunMode string
|
||||||
|
// SessionOn means whether turn on the session auto when application started. default is false.
|
||||||
|
SessionOn bool
|
||||||
|
// SessionProvider means session provider, e.q memory, mysql, redis,etc.
|
||||||
|
SessionProvider string
|
||||||
|
// SessionName is the cookie name when saving session id into cookie.
|
||||||
|
SessionName string
|
||||||
|
// SessionGCMaxLifetime for auto cleaning expired session.
|
||||||
|
SessionGCMaxLifetime int64
|
||||||
|
// SessionProviderConfig is for the provider config, define save path or connection info.
|
||||||
|
SessionProviderConfig string
|
||||||
|
// SessionCookieLifeTime means the life time of session id in cookie.
|
||||||
|
SessionCookieLifeTime int
|
||||||
|
// SessionAutoSetCookie auto setcookie
|
||||||
|
SessionAutoSetCookie bool
|
||||||
|
// SessionDomain means the cookie domain default is empty
|
||||||
|
SessionDomain string
|
||||||
|
// StaticDir store the static path, key is path, value is the folder
|
||||||
|
StaticDir map[string]string
|
||||||
|
// StaticExtensionsToGzip stores the extensions which need to gzip(.js,.css,etc)
|
||||||
|
StaticExtensionsToGzip []string
|
||||||
|
// TemplateCache store the caching template
|
||||||
|
TemplateCache map[string]*template.Template
|
||||||
|
// TemplateLeft left delimiter
|
||||||
TemplateLeft string
|
TemplateLeft string
|
||||||
|
// TemplateRight right delimiter
|
||||||
TemplateRight string
|
TemplateRight string
|
||||||
BeegoServerName string // beego server name exported in response header.
|
// ViewsPath means the template folder
|
||||||
EnableAdmin bool // flag of enable admin module to log every request info.
|
ViewsPath string
|
||||||
AdminHttpAddr string // http server configurations for admin module.
|
// XSRFKEY xsrf hash salt string.
|
||||||
AdminHttpPort int
|
XSRFKEY string
|
||||||
FlashName string // name of the flash variable found in response header and cookie
|
// XSRFExpire is the expiry of xsrf value.
|
||||||
FlashSeperator string // used to seperate flash key:value
|
XSRFExpire int
|
||||||
AppConfigProvider string // config provider
|
|
||||||
EnableDocs bool // enable generate docs & server docs API Swagger
|
|
||||||
RouterCaseSensitive bool // router case sensitive default is true
|
|
||||||
AccessLogs bool // print access logs, default is false
|
|
||||||
Graceful bool // use graceful start the server
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type beegoAppConfig struct {
|
type beegoAppConfig struct {
|
||||||
@ -215,9 +270,6 @@ func (b *beegoAppConfig) SaveConfigFile(filename string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// create beego application
|
|
||||||
BeeApp = NewApp()
|
|
||||||
|
|
||||||
workPath, _ = os.Getwd()
|
workPath, _ = os.Getwd()
|
||||||
workPath, _ = filepath.Abs(workPath)
|
workPath, _ = filepath.Abs(workPath)
|
||||||
// initialize default configurations
|
// initialize default configurations
|
||||||
@ -243,12 +295,12 @@ func init() {
|
|||||||
TemplateCache = make(map[string]*template.Template)
|
TemplateCache = make(map[string]*template.Template)
|
||||||
|
|
||||||
// set this to 0.0.0.0 to make this app available to externally
|
// set this to 0.0.0.0 to make this app available to externally
|
||||||
EnableHttpListen = true //default enable http Listen
|
EnableHTTPListen = true //default enable http Listen
|
||||||
|
|
||||||
HttpAddr = ""
|
HTTPAddr = ""
|
||||||
HttpPort = 8080
|
HTTPPort = 8080
|
||||||
|
|
||||||
HttpsPort = 10443
|
HTTPSPort = 10443
|
||||||
|
|
||||||
AppName = "beego"
|
AppName = "beego"
|
||||||
|
|
||||||
@ -264,20 +316,15 @@ func init() {
|
|||||||
SessionProvider = "memory"
|
SessionProvider = "memory"
|
||||||
SessionName = "beegosessionID"
|
SessionName = "beegosessionID"
|
||||||
SessionGCMaxLifetime = 3600
|
SessionGCMaxLifetime = 3600
|
||||||
SessionSavePath = ""
|
SessionProviderConfig = ""
|
||||||
SessionCookieLifeTime = 0 //set cookie default is the brower life
|
SessionCookieLifeTime = 0 //set cookie default is the brower life
|
||||||
SessionAutoSetCookie = true
|
SessionAutoSetCookie = true
|
||||||
|
|
||||||
UseFcgi = false
|
|
||||||
UseStdIo = false
|
|
||||||
|
|
||||||
MaxMemory = 1 << 26 //64MB
|
MaxMemory = 1 << 26 //64MB
|
||||||
|
|
||||||
EnableGzip = false
|
HTTPServerTimeOut = 0
|
||||||
|
|
||||||
HttpServerTimeOut = 0
|
EnableErrorsShow = true
|
||||||
|
|
||||||
ErrorsShow = true
|
|
||||||
|
|
||||||
XSRFKEY = "beegoxsrf"
|
XSRFKEY = "beegoxsrf"
|
||||||
XSRFExpire = 0
|
XSRFExpire = 0
|
||||||
@ -288,8 +335,8 @@ func init() {
|
|||||||
BeegoServerName = "beegoServer:" + VERSION
|
BeegoServerName = "beegoServer:" + VERSION
|
||||||
|
|
||||||
EnableAdmin = false
|
EnableAdmin = false
|
||||||
AdminHttpAddr = "127.0.0.1"
|
AdminHTTPAddr = "127.0.0.1"
|
||||||
AdminHttpPort = 8088
|
AdminHTTPPort = 8088
|
||||||
|
|
||||||
FlashName = "BEEGO_FLASH"
|
FlashName = "BEEGO_FLASH"
|
||||||
FlashSeperator = "BEEGOFLASH"
|
FlashSeperator = "BEEGOFLASH"
|
||||||
@ -330,18 +377,18 @@ func ParseConfig() (err error) {
|
|||||||
RunMode = runmode
|
RunMode = runmode
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpAddr = AppConfig.String("HttpAddr")
|
HTTPAddr = AppConfig.String("HTTPAddr")
|
||||||
|
|
||||||
if v, err := AppConfig.Int("HttpPort"); err == nil {
|
if v, err := AppConfig.Int("HTTPPort"); err == nil {
|
||||||
HttpPort = v
|
HTTPPort = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := AppConfig.Bool("ListenTCP4"); err == nil {
|
if v, err := AppConfig.Bool("ListenTCP4"); err == nil {
|
||||||
ListenTCP4 = v
|
ListenTCP4 = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := AppConfig.Bool("EnableHttpListen"); err == nil {
|
if v, err := AppConfig.Bool("EnableHTTPListen"); err == nil {
|
||||||
EnableHttpListen = v
|
EnableHTTPListen = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxmemory, err := AppConfig.Int64("MaxMemory"); err == nil {
|
if maxmemory, err := AppConfig.Int64("MaxMemory"); err == nil {
|
||||||
@ -376,8 +423,8 @@ func ParseConfig() (err error) {
|
|||||||
SessionName = sessName
|
SessionName = sessName
|
||||||
}
|
}
|
||||||
|
|
||||||
if sesssavepath := AppConfig.String("SessionSavePath"); sesssavepath != "" {
|
if sessProvConfig := AppConfig.String("SessionProviderConfig"); sessProvConfig != "" {
|
||||||
SessionSavePath = sesssavepath
|
SessionProviderConfig = sessProvConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessMaxLifeTime, err := AppConfig.Int64("SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 {
|
if sessMaxLifeTime, err := AppConfig.Int64("SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 {
|
||||||
@ -388,8 +435,8 @@ func ParseConfig() (err error) {
|
|||||||
SessionCookieLifeTime = sesscookielifetime
|
SessionCookieLifeTime = sesscookielifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
if usefcgi, err := AppConfig.Bool("UseFcgi"); err == nil {
|
if enabelFcgi, err := AppConfig.Bool("EnabelFcgi"); err == nil {
|
||||||
UseFcgi = usefcgi
|
EnabelFcgi = enabelFcgi
|
||||||
}
|
}
|
||||||
|
|
||||||
if enablegzip, err := AppConfig.Bool("EnableGzip"); err == nil {
|
if enablegzip, err := AppConfig.Bool("EnableGzip"); err == nil {
|
||||||
@ -400,12 +447,12 @@ func ParseConfig() (err error) {
|
|||||||
DirectoryIndex = directoryindex
|
DirectoryIndex = directoryindex
|
||||||
}
|
}
|
||||||
|
|
||||||
if timeout, err := AppConfig.Int64("HttpServerTimeOut"); err == nil {
|
if timeout, err := AppConfig.Int64("HTTPServerTimeOut"); err == nil {
|
||||||
HttpServerTimeOut = timeout
|
HTTPServerTimeOut = timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
if errorsshow, err := AppConfig.Bool("ErrorsShow"); err == nil {
|
if errorsshow, err := AppConfig.Bool("EnableErrorsShow"); err == nil {
|
||||||
ErrorsShow = errorsshow
|
EnableErrorsShow = errorsshow
|
||||||
}
|
}
|
||||||
|
|
||||||
if copyrequestbody, err := AppConfig.Bool("CopyRequestBody"); err == nil {
|
if copyrequestbody, err := AppConfig.Bool("CopyRequestBody"); err == nil {
|
||||||
@ -432,20 +479,20 @@ func ParseConfig() (err error) {
|
|||||||
TemplateRight = tplright
|
TemplateRight = tplright
|
||||||
}
|
}
|
||||||
|
|
||||||
if httptls, err := AppConfig.Bool("EnableHttpTLS"); err == nil {
|
if httptls, err := AppConfig.Bool("EnableHTTPTLS"); err == nil {
|
||||||
EnableHttpTLS = httptls
|
EnableHTTPTLS = httptls
|
||||||
}
|
}
|
||||||
|
|
||||||
if httpsport, err := AppConfig.Int("HttpsPort"); err == nil {
|
if httpsport, err := AppConfig.Int("HTTPSPort"); err == nil {
|
||||||
HttpsPort = httpsport
|
HTTPSPort = httpsport
|
||||||
}
|
}
|
||||||
|
|
||||||
if certfile := AppConfig.String("HttpCertFile"); certfile != "" {
|
if certfile := AppConfig.String("HTTPCertFile"); certfile != "" {
|
||||||
HttpCertFile = certfile
|
HTTPCertFile = certfile
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyfile := AppConfig.String("HttpKeyFile"); keyfile != "" {
|
if keyfile := AppConfig.String("HTTPKeyFile"); keyfile != "" {
|
||||||
HttpKeyFile = keyfile
|
HTTPKeyFile = keyfile
|
||||||
}
|
}
|
||||||
|
|
||||||
if serverName := AppConfig.String("BeegoServerName"); serverName != "" {
|
if serverName := AppConfig.String("BeegoServerName"); serverName != "" {
|
||||||
@ -495,12 +542,12 @@ func ParseConfig() (err error) {
|
|||||||
EnableAdmin = enableadmin
|
EnableAdmin = enableadmin
|
||||||
}
|
}
|
||||||
|
|
||||||
if adminhttpaddr := AppConfig.String("AdminHttpAddr"); adminhttpaddr != "" {
|
if adminhttpaddr := AppConfig.String("AdminHTTPAddr"); adminhttpaddr != "" {
|
||||||
AdminHttpAddr = adminhttpaddr
|
AdminHTTPAddr = adminhttpaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
if adminhttpport, err := AppConfig.Int("AdminHttpPort"); err == nil {
|
if adminhttpport, err := AppConfig.Int("AdminHTTPPort"); err == nil {
|
||||||
AdminHttpPort = adminhttpport
|
AdminHTTPPort = adminhttpport
|
||||||
}
|
}
|
||||||
|
|
||||||
if enabledocs, err := AppConfig.Bool("EnableDocs"); err == nil {
|
if enabledocs, err := AppConfig.Bool("EnableDocs"); err == nil {
|
||||||
|
@ -88,12 +88,12 @@ func Register(name string, adapter Config) {
|
|||||||
|
|
||||||
// adapterName is ini/json/xml/yaml.
|
// adapterName is ini/json/xml/yaml.
|
||||||
// filename is the config file path.
|
// filename is the config file path.
|
||||||
func NewConfig(adapterName, fileaname string) (ConfigContainer, error) {
|
func NewConfig(adapterName, filename string) (ConfigContainer, error) {
|
||||||
adapter, ok := adapters[adapterName]
|
adapter, ok := adapters[adapterName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
|
return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
|
||||||
}
|
}
|
||||||
return adapter.Parse(fileaname)
|
return adapter.Parse(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// adapterName is ini/json/xml/yaml.
|
// adapterName is ini/json/xml/yaml.
|
||||||
|
@ -353,7 +353,7 @@ func (input *BeegoInput) Bind(dest interface{}, key string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (input *BeegoInput) bind(key string, typ reflect.Type) reflect.Value {
|
func (input *BeegoInput) bind(key string, typ reflect.Type) reflect.Value {
|
||||||
rv := reflect.Zero(reflect.TypeOf(0))
|
rv := reflect.Zero(typ)
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
val := input.Query(key)
|
val := input.Query(key)
|
||||||
@ -398,7 +398,7 @@ func (input *BeegoInput) bind(key string, typ reflect.Type) reflect.Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (input *BeegoInput) bindValue(val string, typ reflect.Type) reflect.Value {
|
func (input *BeegoInput) bindValue(val string, typ reflect.Type) reflect.Value {
|
||||||
rv := reflect.Zero(reflect.TypeOf(0))
|
rv := reflect.Zero(typ)
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
rv = input.bindInt(val, typ)
|
rv = input.bindInt(val, typ)
|
||||||
|
115
controller.go
115
controller.go
@ -34,18 +34,19 @@ import (
|
|||||||
|
|
||||||
//commonly used mime-types
|
//commonly used mime-types
|
||||||
const (
|
const (
|
||||||
applicationJson = "application/json"
|
applicationJSON = "application/json"
|
||||||
applicationXml = "application/xml"
|
applicationXML = "application/xml"
|
||||||
textXml = "text/xml"
|
textXML = "text/xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// custom error when user stop request handler manually.
|
// ErrAbort custom error when user stop request handler manually.
|
||||||
USERSTOPRUN = errors.New("User stop run")
|
ErrAbort = errors.New("User stop run")
|
||||||
GlobalControllerRouter map[string][]ControllerComments = make(map[string][]ControllerComments) //pkgpath+controller:comments
|
// GlobalControllerRouter store comments with controller. pkgpath+controller:comments
|
||||||
|
GlobalControllerRouter = make(map[string][]ControllerComments)
|
||||||
)
|
)
|
||||||
|
|
||||||
// store the comment for the controller method
|
// ControllerComments store the comment for the controller method
|
||||||
type ControllerComments struct {
|
type ControllerComments struct {
|
||||||
Method string
|
Method string
|
||||||
Router string
|
Router string
|
||||||
@ -64,7 +65,7 @@ type Controller struct {
|
|||||||
Layout string
|
Layout string
|
||||||
LayoutSections map[string]string // the key is the section name and the value is the template name
|
LayoutSections map[string]string // the key is the section name and the value is the template name
|
||||||
TplExt string
|
TplExt string
|
||||||
_xsrf_token string
|
_xsrfToken string
|
||||||
gotofunc string
|
gotofunc string
|
||||||
CruSession session.SessionStore
|
CruSession session.SessionStore
|
||||||
XSRFExpire int
|
XSRFExpire int
|
||||||
@ -87,8 +88,8 @@ type ControllerInterface interface {
|
|||||||
Options()
|
Options()
|
||||||
Finish()
|
Finish()
|
||||||
Render() error
|
Render() error
|
||||||
XsrfToken() string
|
XSRFToken() string
|
||||||
CheckXsrfCookie() bool
|
CheckXSRFCookie() bool
|
||||||
HandlerFunc(fn string) bool
|
HandlerFunc(fn string) bool
|
||||||
URLMapping()
|
URLMapping()
|
||||||
}
|
}
|
||||||
@ -153,20 +154,20 @@ func (c *Controller) Options() {
|
|||||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||||
}
|
}
|
||||||
|
|
||||||
// call function fn
|
// HandlerFunc call function with the name
|
||||||
func (c *Controller) HandlerFunc(fnname string) bool {
|
func (c *Controller) HandlerFunc(fnname string) bool {
|
||||||
if v, ok := c.methodMapping[fnname]; ok {
|
if v, ok := c.methodMapping[fnname]; ok {
|
||||||
v()
|
v()
|
||||||
return true
|
return true
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// URLMapping register the internal Controller router.
|
// URLMapping register the internal Controller router.
|
||||||
func (c *Controller) URLMapping() {
|
func (c *Controller) URLMapping() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mapping the method to function
|
||||||
func (c *Controller) Mapping(method string, fn func()) {
|
func (c *Controller) Mapping(method string, fn func()) {
|
||||||
c.methodMapping[method] = fn
|
c.methodMapping[method] = fn
|
||||||
}
|
}
|
||||||
@ -177,13 +178,11 @@ func (c *Controller) Render() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
rb, err := c.RenderBytes()
|
rb, err := c.RenderBytes()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
}
|
||||||
c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
|
c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
c.Ctx.Output.Body(rb)
|
c.Ctx.Output.Body(rb)
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +199,19 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
|||||||
if c.TplNames == "" {
|
if c.TplNames == "" {
|
||||||
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
|
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
|
||||||
}
|
}
|
||||||
|
|
||||||
if RunMode == "dev" {
|
if RunMode == "dev" {
|
||||||
BuildTemplate(ViewsPath)
|
buildFiles := make([]string, 1)
|
||||||
|
buildFiles = append(buildFiles, c.TplNames)
|
||||||
|
if c.LayoutSections != nil {
|
||||||
|
for _, sectionTpl := range c.LayoutSections {
|
||||||
|
if sectionTpl == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buildFiles = append(buildFiles, sectionTpl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BuildTemplate(ViewsPath, buildFiles...)
|
||||||
}
|
}
|
||||||
newbytes := bytes.NewBufferString("")
|
newbytes := bytes.NewBufferString("")
|
||||||
if _, ok := BeeTemplates[c.TplNames]; !ok {
|
if _, ok := BeeTemplates[c.TplNames]; !ok {
|
||||||
@ -241,12 +251,13 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
icontent, _ := ioutil.ReadAll(ibytes)
|
icontent, _ := ioutil.ReadAll(ibytes)
|
||||||
return icontent, nil
|
return icontent, nil
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if c.TplNames == "" {
|
if c.TplNames == "" {
|
||||||
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
|
c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
|
||||||
}
|
}
|
||||||
if RunMode == "dev" {
|
if RunMode == "dev" {
|
||||||
BuildTemplate(ViewsPath)
|
BuildTemplate(ViewsPath, c.TplNames)
|
||||||
}
|
}
|
||||||
ibytes := bytes.NewBufferString("")
|
ibytes := bytes.NewBufferString("")
|
||||||
if _, ok := BeeTemplates[c.TplNames]; !ok {
|
if _, ok := BeeTemplates[c.TplNames]; !ok {
|
||||||
@ -260,14 +271,13 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
|||||||
icontent, _ := ioutil.ReadAll(ibytes)
|
icontent, _ := ioutil.ReadAll(ibytes)
|
||||||
return icontent, nil
|
return icontent, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect sends the redirection response to url with status code.
|
// Redirect sends the redirection response to url with status code.
|
||||||
func (c *Controller) Redirect(url string, code int) {
|
func (c *Controller) Redirect(url string, code int) {
|
||||||
c.Ctx.Redirect(code, url)
|
c.Ctx.Redirect(code, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aborts stops controller handler and show the error data if code is defined in ErrorMap or code string.
|
// Abort stops controller handler and show the error data if code is defined in ErrorMap or code string.
|
||||||
func (c *Controller) Abort(code string) {
|
func (c *Controller) Abort(code string) {
|
||||||
status, err := strconv.Atoi(code)
|
status, err := strconv.Atoi(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -285,29 +295,28 @@ func (c *Controller) CustomAbort(status int, body string) {
|
|||||||
}
|
}
|
||||||
// last panic user string
|
// last panic user string
|
||||||
c.Ctx.ResponseWriter.Write([]byte(body))
|
c.Ctx.ResponseWriter.Write([]byte(body))
|
||||||
panic(USERSTOPRUN)
|
panic(ErrAbort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(ErrAbort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UrlFor does another controller handler in this request function.
|
// URLFor does another controller handler in this request function.
|
||||||
// it goes to this controller method if endpoint is not clear.
|
// it goes to this controller method if endpoint is not clear.
|
||||||
func (c *Controller) UrlFor(endpoint string, values ...interface{}) string {
|
func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
|
||||||
if len(endpoint) <= 0 {
|
if len(endpoint) <= 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if endpoint[0] == '.' {
|
if endpoint[0] == '.' {
|
||||||
return UrlFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...)
|
return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...)
|
||||||
} else {
|
|
||||||
return UrlFor(endpoint, values...)
|
|
||||||
}
|
}
|
||||||
|
return URLFor(endpoint, values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeJson sends a json response with encoding charset.
|
// ServeJSON sends a json response with encoding charset.
|
||||||
func (c *Controller) ServeJson(encoding ...bool) {
|
func (c *Controller) ServeJSON(encoding ...bool) {
|
||||||
var hasIndent bool
|
var hasIndent bool
|
||||||
var hasencoding bool
|
var hasencoding bool
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
@ -321,8 +330,8 @@ func (c *Controller) ServeJson(encoding ...bool) {
|
|||||||
c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding)
|
c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeJsonp sends a jsonp response.
|
// ServeJSONP sends a jsonp response.
|
||||||
func (c *Controller) ServeJsonp() {
|
func (c *Controller) ServeJSONP() {
|
||||||
var hasIndent bool
|
var hasIndent bool
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
hasIndent = false
|
hasIndent = false
|
||||||
@ -332,8 +341,8 @@ func (c *Controller) ServeJsonp() {
|
|||||||
c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent)
|
c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeXml sends xml response.
|
// ServeXML sends xml response.
|
||||||
func (c *Controller) ServeXml() {
|
func (c *Controller) ServeXML() {
|
||||||
var hasIndent bool
|
var hasIndent bool
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
hasIndent = false
|
hasIndent = false
|
||||||
@ -347,12 +356,12 @@ func (c *Controller) ServeXml() {
|
|||||||
func (c *Controller) ServeFormatted() {
|
func (c *Controller) ServeFormatted() {
|
||||||
accept := c.Ctx.Input.Header("Accept")
|
accept := c.Ctx.Input.Header("Accept")
|
||||||
switch accept {
|
switch accept {
|
||||||
case applicationJson:
|
case applicationJSON:
|
||||||
c.ServeJson()
|
c.ServeJSON()
|
||||||
case applicationXml, textXml:
|
case applicationXML, textXML:
|
||||||
c.ServeXml()
|
c.ServeXML()
|
||||||
default:
|
default:
|
||||||
c.ServeJson()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,9 +387,8 @@ func (c *Controller) GetString(key string, def ...string) string {
|
|||||||
|
|
||||||
if v := c.Ctx.Input.Query(key); v != "" {
|
if v := c.Ctx.Input.Query(key); v != "" {
|
||||||
return v
|
return v
|
||||||
} else {
|
|
||||||
return defv
|
|
||||||
}
|
}
|
||||||
|
return defv
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStrings returns the input string slice by key string or the default value while it's present and input is blank
|
// GetStrings returns the input string slice by key string or the default value while it's present and input is blank
|
||||||
@ -399,9 +407,8 @@ func (c *Controller) GetStrings(key string, def ...[]string) []string {
|
|||||||
vs := f[key]
|
vs := f[key]
|
||||||
if len(vs) > 0 {
|
if len(vs) > 0 {
|
||||||
return vs
|
return vs
|
||||||
} else {
|
|
||||||
return defv
|
|
||||||
}
|
}
|
||||||
|
return defv
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt returns input as an int or the default value while it's present and input is blank
|
// GetInt returns input as an int or the default value while it's present and input is blank
|
||||||
@ -575,7 +582,7 @@ func (c *Controller) GetSession(name interface{}) interface{} {
|
|||||||
return c.CruSession.Get(name)
|
return c.CruSession.Get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSession removes value from session.
|
// DelSession removes value from session.
|
||||||
func (c *Controller) DelSession(name interface{}) {
|
func (c *Controller) DelSession(name interface{}) {
|
||||||
if c.CruSession == nil {
|
if c.CruSession == nil {
|
||||||
c.StartSession()
|
c.StartSession()
|
||||||
@ -614,34 +621,34 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter
|
|||||||
c.Ctx.SetSecureCookie(Secret, name, value, others...)
|
c.Ctx.SetSecureCookie(Secret, name, value, others...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XsrfToken creates a xsrf token string and returns.
|
// XSRFToken creates a CSRF token string and returns.
|
||||||
func (c *Controller) XsrfToken() string {
|
func (c *Controller) XSRFToken() string {
|
||||||
if c._xsrf_token == "" {
|
if c._xsrfToken == "" {
|
||||||
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)
|
||||||
}
|
}
|
||||||
c._xsrf_token = c.Ctx.XsrfToken(XSRFKEY, expire)
|
c._xsrfToken = c.Ctx.XsrfToken(XSRFKEY, expire)
|
||||||
}
|
}
|
||||||
return c._xsrf_token
|
return c._xsrfToken
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckXsrfCookie checks xsrf token in this request is valid or not.
|
// CheckXSRFCookie checks xsrf token in this request is valid or not.
|
||||||
// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
|
// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
|
||||||
// or in form field value named as "_xsrf".
|
// or in form field value named as "_xsrf".
|
||||||
func (c *Controller) CheckXsrfCookie() bool {
|
func (c *Controller) CheckXSRFCookie() bool {
|
||||||
if !c.EnableXSRF {
|
if !c.EnableXSRF {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return c.Ctx.CheckXsrfCookie()
|
return c.Ctx.CheckXsrfCookie()
|
||||||
}
|
}
|
||||||
|
|
||||||
// XsrfFormHtml writes an input field contains xsrf token value.
|
// XSRFFormHTML writes an input field contains xsrf token value.
|
||||||
func (c *Controller) XsrfFormHtml() string {
|
func (c *Controller) XSRFFormHTML() string {
|
||||||
return "<input type=\"hidden\" name=\"_xsrf\" value=\"" +
|
return "<input type=\"hidden\" name=\"_xsrf\" value=\"" +
|
||||||
c._xsrf_token + "\"/>"
|
c._xsrfToken + "\"/>"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetControllerAndAction gets the executing controller name and action name.
|
// GetControllerAndAction gets the executing controller name and action name.
|
||||||
|
17
doc.go
Normal file
17
doc.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Package beego provide a MVC framework
|
||||||
|
beego: an open-source, high-performance, modular, full-stack web framework
|
||||||
|
|
||||||
|
It is used for rapid development of RESTful APIs, web apps and backend services in Go.
|
||||||
|
beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding.
|
||||||
|
|
||||||
|
package main
|
||||||
|
import "github.com/astaxie/beego"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
beego.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
more infomation: http://beego.me
|
||||||
|
*/
|
||||||
|
package beego
|
9
docs.go
9
docs.go
@ -20,20 +20,21 @@ import (
|
|||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var GlobalDocApi map[string]interface{}
|
// GlobalDocAPI store the swagger api documents
|
||||||
|
var GlobalDocAPI map[string]interface{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if EnableDocs {
|
if EnableDocs {
|
||||||
GlobalDocApi = make(map[string]interface{})
|
GlobalDocAPI = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverDocs(ctx *context.Context) {
|
func serverDocs(ctx *context.Context) {
|
||||||
var obj interface{}
|
var obj interface{}
|
||||||
if splat := ctx.Input.Param(":splat"); splat == "" {
|
if splat := ctx.Input.Param(":splat"); splat == "" {
|
||||||
obj = GlobalDocApi["Root"]
|
obj = GlobalDocAPI["Root"]
|
||||||
} else {
|
} else {
|
||||||
if v, ok := GlobalDocApi[splat]; ok {
|
if v, ok := GlobalDocAPI[splat]; ok {
|
||||||
obj = v
|
obj = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
error.go
48
error.go
@ -358,52 +358,11 @@ func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
|||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// register default error http handlers, 404,401,403,500 and 503.
|
|
||||||
func registerDefaultErrorHandler() {
|
|
||||||
if _, ok := ErrorMaps["401"]; !ok {
|
|
||||||
Errorhandler("401", unauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["402"]; !ok {
|
|
||||||
Errorhandler("402", paymentRequired)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["403"]; !ok {
|
|
||||||
Errorhandler("403", forbidden)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["404"]; !ok {
|
|
||||||
Errorhandler("404", notFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["405"]; !ok {
|
|
||||||
Errorhandler("405", methodNotAllowed)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["500"]; !ok {
|
|
||||||
Errorhandler("500", internalServerError)
|
|
||||||
}
|
|
||||||
if _, ok := ErrorMaps["501"]; !ok {
|
|
||||||
Errorhandler("501", notImplemented)
|
|
||||||
}
|
|
||||||
if _, ok := ErrorMaps["502"]; !ok {
|
|
||||||
Errorhandler("502", badGateway)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["503"]; !ok {
|
|
||||||
Errorhandler("503", serviceUnavailable)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := ErrorMaps["504"]; !ok {
|
|
||||||
Errorhandler("504", gatewayTimeout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrorHandler registers http.HandlerFunc to each http err code string.
|
// ErrorHandler registers http.HandlerFunc to each http err code string.
|
||||||
// usage:
|
// usage:
|
||||||
// beego.ErrorHandler("404",NotFound)
|
// beego.ErrorHandler("404",NotFound)
|
||||||
// beego.ErrorHandler("500",InternalServerError)
|
// beego.ErrorHandler("500",InternalServerError)
|
||||||
func Errorhandler(code string, h http.HandlerFunc) *App {
|
func ErrorHandler(code string, h http.HandlerFunc) *App {
|
||||||
errinfo := &errorInfo{}
|
errinfo := &errorInfo{}
|
||||||
errinfo.errorType = errorTypeHandler
|
errinfo.errorType = errorTypeHandler
|
||||||
errinfo.handler = h
|
errinfo.handler = h
|
||||||
@ -414,7 +373,7 @@ func Errorhandler(code string, h http.HandlerFunc) *App {
|
|||||||
|
|
||||||
// ErrorController registers ControllerInterface to each http err code string.
|
// ErrorController registers ControllerInterface to each http err code string.
|
||||||
// usage:
|
// usage:
|
||||||
// beego.ErrorHandler(&controllers.ErrorController{})
|
// beego.ErrorController(&controllers.ErrorController{})
|
||||||
func ErrorController(c ControllerInterface) *App {
|
func ErrorController(c ControllerInterface) *App {
|
||||||
reflectVal := reflect.ValueOf(c)
|
reflectVal := reflect.ValueOf(c)
|
||||||
rt := reflectVal.Type()
|
rt := reflectVal.Type()
|
||||||
@ -453,7 +412,6 @@ func exception(errcode string, ctx *context.Context) {
|
|||||||
|
|
||||||
func executeError(err *errorInfo, ctx *context.Context, code int) {
|
func executeError(err *errorInfo, ctx *context.Context, code int) {
|
||||||
if err.errorType == errorTypeHandler {
|
if err.errorType == errorTypeHandler {
|
||||||
ctx.ResponseWriter.WriteHeader(code)
|
|
||||||
err.handler(ctx.ResponseWriter, ctx.Request)
|
err.handler(ctx.ResponseWriter, ctx.Request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -473,7 +431,7 @@ func executeError(err *errorInfo, ctx *context.Context, code int) {
|
|||||||
|
|
||||||
execController.URLMapping()
|
execController.URLMapping()
|
||||||
|
|
||||||
in := make([]reflect.Value, 0)
|
var in []reflect.Value
|
||||||
method := vc.MethodByName(err.method)
|
method := vc.MethodByName(err.method)
|
||||||
method.Call(in)
|
method.Call(in)
|
||||||
|
|
||||||
|
@ -54,14 +54,13 @@ func (c *connection) readPump() {
|
|||||||
}()
|
}()
|
||||||
c.ws.SetReadLimit(maxMessageSize)
|
c.ws.SetReadLimit(maxMessageSize)
|
||||||
c.ws.SetReadDeadline(time.Now().Add(readWait))
|
c.ws.SetReadDeadline(time.Now().Add(readWait))
|
||||||
|
c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(readWait)); return nil })
|
||||||
for {
|
for {
|
||||||
op, r, err := c.ws.NextReader()
|
op, r, err := c.ws.NextReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch op {
|
switch op {
|
||||||
case websocket.PongMessage:
|
|
||||||
c.ws.SetReadDeadline(time.Now().Add(readWait))
|
|
||||||
case websocket.TextMessage:
|
case websocket.TextMessage:
|
||||||
message, err := ioutil.ReadAll(r)
|
message, err := ioutil.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -39,7 +39,6 @@ func (f *FilterRouter) ValidRouter(url string) (bool, map[string]string) {
|
|||||||
}
|
}
|
||||||
if isok, ok := isok.(bool); ok {
|
if isok, ok := isok.(bool); ok {
|
||||||
return isok, params
|
return isok, params
|
||||||
} else {
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -30,7 +30,7 @@ func (t *TestFlashController) TestWriteFlash() {
|
|||||||
flash.Notice("TestFlashString")
|
flash.Notice("TestFlashString")
|
||||||
flash.Store(&t.Controller)
|
flash.Store(&t.Controller)
|
||||||
// we choose to serve json because we don't want to load a template html file
|
// we choose to serve json because we don't want to load a template html file
|
||||||
t.ServeJson(true)
|
t.ServeJSON(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFlashHeader(t *testing.T) {
|
func TestFlashHeader(t *testing.T) {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
// mux := http.NewServeMux()
|
// mux := http.NewServeMux()
|
||||||
// mux.HandleFunc("/hello", handler)
|
// mux.HandleFunc("/hello", handler)
|
||||||
//
|
//
|
||||||
// err := grace.ListenAndServe("localhost:8080", mux1)
|
// err := grace.ListenAndServe("localhost:8080", mux)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// log.Println(err)
|
// log.Println(err)
|
||||||
// }
|
// }
|
||||||
|
106
hooks.go
Normal file
106
hooks.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package beego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mime"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
func registerMime() error {
|
||||||
|
for k, v := range mimemaps {
|
||||||
|
mime.AddExtensionType(k, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// register default error http handlers, 404,401,403,500 and 503.
|
||||||
|
func registerDefaultErrorHandler() error {
|
||||||
|
if _, ok := ErrorMaps["401"]; !ok {
|
||||||
|
ErrorHandler("401", unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["402"]; !ok {
|
||||||
|
ErrorHandler("402", paymentRequired)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["403"]; !ok {
|
||||||
|
ErrorHandler("403", forbidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["404"]; !ok {
|
||||||
|
ErrorHandler("404", notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["405"]; !ok {
|
||||||
|
ErrorHandler("405", methodNotAllowed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["500"]; !ok {
|
||||||
|
ErrorHandler("500", internalServerError)
|
||||||
|
}
|
||||||
|
if _, ok := ErrorMaps["501"]; !ok {
|
||||||
|
ErrorHandler("501", notImplemented)
|
||||||
|
}
|
||||||
|
if _, ok := ErrorMaps["502"]; !ok {
|
||||||
|
ErrorHandler("502", badGateway)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["503"]; !ok {
|
||||||
|
ErrorHandler("503", serviceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["504"]; !ok {
|
||||||
|
ErrorHandler("504", gatewayTimeout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerSession() error {
|
||||||
|
if SessionOn {
|
||||||
|
var err error
|
||||||
|
sessionConfig := AppConfig.String("sessionConfig")
|
||||||
|
if sessionConfig == "" {
|
||||||
|
sessionConfig = `{"cookieName":"` + SessionName + `",` +
|
||||||
|
`"gclifetime":` + strconv.FormatInt(SessionGCMaxLifetime, 10) + `,` +
|
||||||
|
`"providerConfig":"` + filepath.ToSlash(SessionProviderConfig) + `",` +
|
||||||
|
`"secure":` + strconv.FormatBool(EnableHTTPTLS) + `,` +
|
||||||
|
`"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` +
|
||||||
|
`"domain":"` + SessionDomain + `",` +
|
||||||
|
`"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}`
|
||||||
|
}
|
||||||
|
GlobalSessions, err = session.NewManager(SessionProvider, sessionConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go GlobalSessions.GC()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerTemplate() error {
|
||||||
|
if AutoRender {
|
||||||
|
err := BuildTemplate(ViewsPath)
|
||||||
|
if err != nil && RunMode == "dev" {
|
||||||
|
Warn(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerDocs() error {
|
||||||
|
if EnableDocs {
|
||||||
|
Get("/docs", serverDocs)
|
||||||
|
Get("/docs/*", serverDocs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerAdmin() error {
|
||||||
|
if EnableAdmin {
|
||||||
|
go beeAdminApp.Run()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -74,12 +74,6 @@ func SetDefaultSetting(setting BeegoHttpSettings) {
|
|||||||
settingMutex.Lock()
|
settingMutex.Lock()
|
||||||
defer settingMutex.Unlock()
|
defer settingMutex.Unlock()
|
||||||
defaultSetting = setting
|
defaultSetting = setting
|
||||||
if defaultSetting.ConnectTimeout == 0 {
|
|
||||||
defaultSetting.ConnectTimeout = 60 * time.Second
|
|
||||||
}
|
|
||||||
if defaultSetting.ReadWriteTimeout == 0 {
|
|
||||||
defaultSetting.ReadWriteTimeout = 60 * time.Second
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return *BeegoHttpRequest with specific method
|
// return *BeegoHttpRequest with specific method
|
||||||
@ -100,7 +94,7 @@ func NewBeegoRequest(rawurl, method string) *BeegoHttpRequest {
|
|||||||
return &BeegoHttpRequest{
|
return &BeegoHttpRequest{
|
||||||
url: rawurl,
|
url: rawurl,
|
||||||
req: &req,
|
req: &req,
|
||||||
params: map[string]string{},
|
params: map[string][]string{},
|
||||||
files: map[string]string{},
|
files: map[string]string{},
|
||||||
setting: defaultSetting,
|
setting: defaultSetting,
|
||||||
resp: &resp,
|
resp: &resp,
|
||||||
@ -150,7 +144,7 @@ type BeegoHttpSettings struct {
|
|||||||
type BeegoHttpRequest struct {
|
type BeegoHttpRequest struct {
|
||||||
url string
|
url string
|
||||||
req *http.Request
|
req *http.Request
|
||||||
params map[string]string
|
params map[string][]string
|
||||||
files map[string]string
|
files map[string]string
|
||||||
setting BeegoHttpSettings
|
setting BeegoHttpSettings
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
@ -273,7 +267,11 @@ func (b *BeegoHttpRequest) SetProxy(proxy func(*http.Request) (*url.URL, error))
|
|||||||
// Param adds query param in to request.
|
// Param adds query param in to request.
|
||||||
// params build query string as ?key1=value1&key2=value2...
|
// params build query string as ?key1=value1&key2=value2...
|
||||||
func (b *BeegoHttpRequest) Param(key, value string) *BeegoHttpRequest {
|
func (b *BeegoHttpRequest) Param(key, value string) *BeegoHttpRequest {
|
||||||
b.params[key] = value
|
if param, ok := b.params[key]; ok {
|
||||||
|
b.params[key] = append(param, value)
|
||||||
|
} else {
|
||||||
|
b.params[key] = []string{value}
|
||||||
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +346,9 @@ func (b *BeegoHttpRequest) buildUrl(paramBody string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, v := range b.params {
|
for k, v := range b.params {
|
||||||
bodyWriter.WriteField(k, v)
|
for _, vv := range v {
|
||||||
|
bodyWriter.WriteField(k, vv)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bodyWriter.Close()
|
bodyWriter.Close()
|
||||||
pw.Close()
|
pw.Close()
|
||||||
@ -383,11 +383,13 @@ func (b *BeegoHttpRequest) SendOut() (*http.Response, error) {
|
|||||||
if len(b.params) > 0 {
|
if len(b.params) > 0 {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
for k, v := range b.params {
|
for k, v := range b.params {
|
||||||
|
for _, vv := range v {
|
||||||
buf.WriteString(url.QueryEscape(k))
|
buf.WriteString(url.QueryEscape(k))
|
||||||
buf.WriteByte('=')
|
buf.WriteByte('=')
|
||||||
buf.WriteString(url.QueryEscape(v))
|
buf.WriteString(url.QueryEscape(vv))
|
||||||
buf.WriteByte('&')
|
buf.WriteByte('&')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
paramBody = buf.String()
|
paramBody = buf.String()
|
||||||
paramBody = paramBody[0 : len(paramBody)-1]
|
paramBody = paramBody[0 : len(paramBody)-1]
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestResponse(t *testing.T) {
|
func TestResponse(t *testing.T) {
|
||||||
@ -153,6 +154,7 @@ func TestWithSetting(t *testing.T) {
|
|||||||
setting.EnableCookie = true
|
setting.EnableCookie = true
|
||||||
setting.UserAgent = v
|
setting.UserAgent = v
|
||||||
setting.Transport = nil
|
setting.Transport = nil
|
||||||
|
setting.ReadWriteTimeout = 5 * time.Second
|
||||||
SetDefaultSetting(setting)
|
SetDefaultSetting(setting)
|
||||||
|
|
||||||
str, err := Get("http://httpbin.org/get").String()
|
str, err := Get("http://httpbin.org/get").String()
|
||||||
|
15
log.go
15
log.go
@ -32,18 +32,18 @@ const (
|
|||||||
LevelDebug
|
LevelDebug
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetLogLevel sets the global log level used by the simple
|
// SetLevel sets the global log level used by the simple logger.
|
||||||
// logger.
|
|
||||||
func SetLevel(l int) {
|
func SetLevel(l int) {
|
||||||
BeeLogger.SetLevel(l)
|
BeeLogger.SetLevel(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLogFuncCall set the CallDepth, default is 3
|
||||||
func SetLogFuncCall(b bool) {
|
func SetLogFuncCall(b bool) {
|
||||||
BeeLogger.EnableFuncCallDepth(b)
|
BeeLogger.EnableFuncCallDepth(b)
|
||||||
BeeLogger.SetLogFuncCallDepth(3)
|
BeeLogger.SetLogFuncCallDepth(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// logger references the used application logger.
|
// BeeLogger references the used application logger.
|
||||||
var BeeLogger *logs.BeeLogger
|
var BeeLogger *logs.BeeLogger
|
||||||
|
|
||||||
// SetLogger sets a new logger.
|
// SetLogger sets a new logger.
|
||||||
@ -55,10 +55,12 @@ func SetLogger(adaptername string, config string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emergency logs a message at emergency level.
|
||||||
func Emergency(v ...interface{}) {
|
func Emergency(v ...interface{}) {
|
||||||
BeeLogger.Emergency(generateFmtStr(len(v)), v...)
|
BeeLogger.Emergency(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alert logs a message at alert level.
|
||||||
func Alert(v ...interface{}) {
|
func Alert(v ...interface{}) {
|
||||||
BeeLogger.Alert(generateFmtStr(len(v)), v...)
|
BeeLogger.Alert(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
@ -78,21 +80,22 @@ func Warning(v ...interface{}) {
|
|||||||
BeeLogger.Warning(generateFmtStr(len(v)), v...)
|
BeeLogger.Warning(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compatibility alias for Warning()
|
// Warn compatibility alias for Warning()
|
||||||
func Warn(v ...interface{}) {
|
func Warn(v ...interface{}) {
|
||||||
BeeLogger.Warn(generateFmtStr(len(v)), v...)
|
BeeLogger.Warn(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice logs a message at notice level.
|
||||||
func Notice(v ...interface{}) {
|
func Notice(v ...interface{}) {
|
||||||
BeeLogger.Notice(generateFmtStr(len(v)), v...)
|
BeeLogger.Notice(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info logs a message at info level.
|
// Informational logs a message at info level.
|
||||||
func Informational(v ...interface{}) {
|
func Informational(v ...interface{}) {
|
||||||
BeeLogger.Informational(generateFmtStr(len(v)), v...)
|
BeeLogger.Informational(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compatibility alias for Warning()
|
// Info compatibility alias for Warning()
|
||||||
func Info(v ...interface{}) {
|
func Info(v ...interface{}) {
|
||||||
BeeLogger.Info(generateFmtStr(len(v)), v...)
|
BeeLogger.Info(generateFmtStr(len(v)), v...)
|
||||||
}
|
}
|
||||||
|
@ -205,15 +205,20 @@ func (w *FileLogWriter) lines() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DoRotate means it need to write file in new file.
|
// DoRotate means it need to write file in new file.
|
||||||
// new file name like xx.log.2013-01-01.2
|
// new file name like xx.2013-01-01.2.log
|
||||||
func (w *FileLogWriter) DoRotate() error {
|
func (w *FileLogWriter) DoRotate() error {
|
||||||
_, err := os.Lstat(w.Filename)
|
_, err := os.Lstat(w.Filename)
|
||||||
if err == nil { // file exists
|
if err == nil { // file exists
|
||||||
// Find the next available number
|
// Find the next available number
|
||||||
num := 1
|
num := 1
|
||||||
fname := ""
|
fname := ""
|
||||||
|
suffix := filepath.Ext(w.Filename)
|
||||||
|
filenameOnly := strings.TrimSuffix(w.Filename, suffix)
|
||||||
|
if suffix == "" {
|
||||||
|
suffix = ".log"
|
||||||
|
}
|
||||||
for ; err == nil && num <= 999; num++ {
|
for ; err == nil && num <= 999; num++ {
|
||||||
fname = w.Filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num)
|
fname = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix)
|
||||||
_, err = os.Lstat(fname)
|
_, err = os.Lstat(fname)
|
||||||
}
|
}
|
||||||
// return error if the last file checked still existed
|
// return error if the last file checked still existed
|
||||||
|
@ -103,7 +103,7 @@ func TestFileRotate(t *testing.T) {
|
|||||||
log.Critical("critical")
|
log.Critical("critical")
|
||||||
log.Emergency("emergency")
|
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" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log"
|
||||||
b, err := exists(rotatename)
|
b, err := exists(rotatename)
|
||||||
if !b || err != nil {
|
if !b || err != nil {
|
||||||
t.Fatal("rotate not generated")
|
t.Fatal("rotate not generated")
|
||||||
|
@ -31,9 +31,9 @@ const (
|
|||||||
|
|
||||||
// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
|
// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
|
||||||
type SmtpWriter struct {
|
type SmtpWriter struct {
|
||||||
Username string `json:"Username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Host string `json:"Host"`
|
Host string `json:"host"`
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
FromAddress string `json:"fromAddress"`
|
FromAddress string `json:"fromAddress"`
|
||||||
RecipientAddresses []string `json:"sendTos"`
|
RecipientAddresses []string `json:"sendTos"`
|
||||||
|
@ -28,8 +28,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gmfim map[string]*memFileInfo = make(map[string]*memFileInfo)
|
var (
|
||||||
var lock sync.RWMutex
|
gmfim = make(map[string]*memFileInfo)
|
||||||
|
lock sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
// OpenMemZipFile returns MemFile object with a compressed static file.
|
// OpenMemZipFile returns MemFile object with a compressed static file.
|
||||||
// it's used for serve static file if gzip enable.
|
// it's used for serve static file if gzip enable.
|
||||||
|
13
mime.go
13
mime.go
@ -14,11 +14,7 @@
|
|||||||
|
|
||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
var mimemaps = map[string]string{
|
||||||
"mime"
|
|
||||||
)
|
|
||||||
|
|
||||||
var mimemaps map[string]string = map[string]string{
|
|
||||||
".3dm": "x-world/x-3dmf",
|
".3dm": "x-world/x-3dmf",
|
||||||
".3dmf": "x-world/x-3dmf",
|
".3dmf": "x-world/x-3dmf",
|
||||||
".7z": "application/x-7z-compressed",
|
".7z": "application/x-7z-compressed",
|
||||||
@ -558,10 +554,3 @@ var mimemaps map[string]string = map[string]string{
|
|||||||
".oex": "application/x-opera-extension",
|
".oex": "application/x-opera-extension",
|
||||||
".mustache": "text/html",
|
".mustache": "text/html",
|
||||||
}
|
}
|
||||||
|
|
||||||
func initMime() error {
|
|
||||||
for k, v := range mimemaps {
|
|
||||||
mime.AddExtensionType(k, v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
107
namespace.go
107
namespace.go
@ -23,16 +23,17 @@ import (
|
|||||||
|
|
||||||
type namespaceCond func(*beecontext.Context) bool
|
type namespaceCond func(*beecontext.Context) bool
|
||||||
|
|
||||||
type innnerNamespace func(*Namespace)
|
// LinkNamespace used as link action
|
||||||
|
type LinkNamespace func(*Namespace)
|
||||||
|
|
||||||
// Namespace is store all the info
|
// Namespace is store all the info
|
||||||
type Namespace struct {
|
type Namespace struct {
|
||||||
prefix string
|
prefix string
|
||||||
handlers *ControllerRegistor
|
handlers *ControllerRegister
|
||||||
}
|
}
|
||||||
|
|
||||||
// get new Namespace
|
// NewNamespace get new Namespace
|
||||||
func NewNamespace(prefix string, params ...innnerNamespace) *Namespace {
|
func NewNamespace(prefix string, params ...LinkNamespace) *Namespace {
|
||||||
ns := &Namespace{
|
ns := &Namespace{
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
handlers: NewControllerRegister(),
|
handlers: NewControllerRegister(),
|
||||||
@ -43,7 +44,7 @@ func NewNamespace(prefix string, params ...innnerNamespace) *Namespace {
|
|||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
// set condtion function
|
// Cond set condtion function
|
||||||
// if cond return true can run this namespace, else can't
|
// if cond return true can run this namespace, else can't
|
||||||
// usage:
|
// usage:
|
||||||
// ns.Cond(func (ctx *context.Context) bool{
|
// ns.Cond(func (ctx *context.Context) bool{
|
||||||
@ -72,7 +73,7 @@ func (n *Namespace) Cond(cond namespaceCond) *Namespace {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// add filter in the Namespace
|
// Filter add filter in the Namespace
|
||||||
// action has before & after
|
// action has before & after
|
||||||
// FilterFunc
|
// FilterFunc
|
||||||
// usage:
|
// usage:
|
||||||
@ -95,98 +96,98 @@ func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Rourer
|
// Router same as beego.Rourer
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Router
|
// refer: https://godoc.org/github.com/astaxie/beego#Router
|
||||||
func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace {
|
func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace {
|
||||||
n.handlers.Add(rootpath, c, mappingMethods...)
|
n.handlers.Add(rootpath, c, mappingMethods...)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.AutoRouter
|
// AutoRouter same as beego.AutoRouter
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#AutoRouter
|
// refer: https://godoc.org/github.com/astaxie/beego#AutoRouter
|
||||||
func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace {
|
func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace {
|
||||||
n.handlers.AddAuto(c)
|
n.handlers.AddAuto(c)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.AutoPrefix
|
// AutoPrefix same as beego.AutoPrefix
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#AutoPrefix
|
// refer: https://godoc.org/github.com/astaxie/beego#AutoPrefix
|
||||||
func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace {
|
func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace {
|
||||||
n.handlers.AddAutoPrefix(prefix, c)
|
n.handlers.AddAutoPrefix(prefix, c)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Get
|
// Get same as beego.Get
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Get
|
// refer: https://godoc.org/github.com/astaxie/beego#Get
|
||||||
func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Get(rootpath, f)
|
n.handlers.Get(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Post
|
// Post same as beego.Post
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Post
|
// refer: https://godoc.org/github.com/astaxie/beego#Post
|
||||||
func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Post(rootpath, f)
|
n.handlers.Post(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Delete
|
// Delete same as beego.Delete
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Delete
|
// refer: https://godoc.org/github.com/astaxie/beego#Delete
|
||||||
func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Delete(rootpath, f)
|
n.handlers.Delete(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Put
|
// Put same as beego.Put
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Put
|
// refer: https://godoc.org/github.com/astaxie/beego#Put
|
||||||
func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Put(rootpath, f)
|
n.handlers.Put(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Head
|
// Head same as beego.Head
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Head
|
// refer: https://godoc.org/github.com/astaxie/beego#Head
|
||||||
func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Head(rootpath, f)
|
n.handlers.Head(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Options
|
// Options same as beego.Options
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Options
|
// refer: https://godoc.org/github.com/astaxie/beego#Options
|
||||||
func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Options(rootpath, f)
|
n.handlers.Options(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Patch
|
// Patch same as beego.Patch
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Patch
|
// refer: https://godoc.org/github.com/astaxie/beego#Patch
|
||||||
func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Patch(rootpath, f)
|
n.handlers.Patch(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Any
|
// Any same as beego.Any
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Any
|
// refer: https://godoc.org/github.com/astaxie/beego#Any
|
||||||
func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace {
|
func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace {
|
||||||
n.handlers.Any(rootpath, f)
|
n.handlers.Any(rootpath, f)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as beego.Handler
|
// Handler same as beego.Handler
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Handler
|
// refer: https://godoc.org/github.com/astaxie/beego#Handler
|
||||||
func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace {
|
func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace {
|
||||||
n.handlers.Handler(rootpath, h)
|
n.handlers.Handler(rootpath, h)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// add include class
|
// Include add include class
|
||||||
// refer: https://godoc.org/github.com/astaxie/beego#Include
|
// refer: https://godoc.org/github.com/astaxie/beego#Include
|
||||||
func (n *Namespace) Include(cList ...ControllerInterface) *Namespace {
|
func (n *Namespace) Include(cList ...ControllerInterface) *Namespace {
|
||||||
n.handlers.Include(cList...)
|
n.handlers.Include(cList...)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// nest Namespace
|
// Namespace add nest Namespace
|
||||||
// usage:
|
// usage:
|
||||||
//ns := beego.NewNamespace(“/v1”).
|
//ns := beego.NewNamespace(“/v1”).
|
||||||
//Namespace(
|
//Namespace(
|
||||||
@ -230,7 +231,7 @@ func (n *Namespace) Namespace(ns ...*Namespace) *Namespace {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// register Namespace into beego.Handler
|
// AddNamespace register Namespace into beego.Handler
|
||||||
// support multi Namespace
|
// support multi Namespace
|
||||||
func AddNamespace(nl ...*Namespace) {
|
func AddNamespace(nl ...*Namespace) {
|
||||||
for _, n := range nl {
|
for _, n := range nl {
|
||||||
@ -275,113 +276,113 @@ func addPrefix(t *Tree, prefix string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Condition
|
// NSCond is Namespace Condition
|
||||||
func NSCond(cond namespaceCond) innnerNamespace {
|
func NSCond(cond namespaceCond) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Cond(cond)
|
ns.Cond(cond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace BeforeRouter filter
|
// NSBefore Namespace BeforeRouter filter
|
||||||
func NSBefore(filiterList ...FilterFunc) innnerNamespace {
|
func NSBefore(filiterList ...FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Filter("before", filiterList...)
|
ns.Filter("before", filiterList...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace FinishRouter filter
|
// NSAfter add Namespace FinishRouter filter
|
||||||
func NSAfter(filiterList ...FilterFunc) innnerNamespace {
|
func NSAfter(filiterList ...FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Filter("after", filiterList...)
|
ns.Filter("after", filiterList...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Include ControllerInterface
|
// NSInclude Namespace Include ControllerInterface
|
||||||
func NSInclude(cList ...ControllerInterface) innnerNamespace {
|
func NSInclude(cList ...ControllerInterface) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Include(cList...)
|
ns.Include(cList...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Router
|
// NSRouter call Namespace Router
|
||||||
func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) innnerNamespace {
|
func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Router(rootpath, c, mappingMethods...)
|
ns.Router(rootpath, c, mappingMethods...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Get
|
// NSGet call Namespace Get
|
||||||
func NSGet(rootpath string, f FilterFunc) innnerNamespace {
|
func NSGet(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Get(rootpath, f)
|
ns.Get(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Post
|
// NSPost call Namespace Post
|
||||||
func NSPost(rootpath string, f FilterFunc) innnerNamespace {
|
func NSPost(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Post(rootpath, f)
|
ns.Post(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Head
|
// NSHead call Namespace Head
|
||||||
func NSHead(rootpath string, f FilterFunc) innnerNamespace {
|
func NSHead(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Head(rootpath, f)
|
ns.Head(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Put
|
// NSPut call Namespace Put
|
||||||
func NSPut(rootpath string, f FilterFunc) innnerNamespace {
|
func NSPut(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Put(rootpath, f)
|
ns.Put(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Delete
|
// NSDelete call Namespace Delete
|
||||||
func NSDelete(rootpath string, f FilterFunc) innnerNamespace {
|
func NSDelete(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Delete(rootpath, f)
|
ns.Delete(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Any
|
// NSAny call Namespace Any
|
||||||
func NSAny(rootpath string, f FilterFunc) innnerNamespace {
|
func NSAny(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Any(rootpath, f)
|
ns.Any(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Options
|
// NSOptions call Namespace Options
|
||||||
func NSOptions(rootpath string, f FilterFunc) innnerNamespace {
|
func NSOptions(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Options(rootpath, f)
|
ns.Options(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace Patch
|
// NSPatch call Namespace Patch
|
||||||
func NSPatch(rootpath string, f FilterFunc) innnerNamespace {
|
func NSPatch(rootpath string, f FilterFunc) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.Patch(rootpath, f)
|
ns.Patch(rootpath, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Namespace AutoRouter
|
// NSAutoRouter call Namespace AutoRouter
|
||||||
func NSAutoRouter(c ControllerInterface) innnerNamespace {
|
func NSAutoRouter(c ControllerInterface) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.AutoRouter(c)
|
ns.AutoRouter(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace AutoPrefix
|
// NSAutoPrefix call Namespace AutoPrefix
|
||||||
func NSAutoPrefix(prefix string, c ControllerInterface) innnerNamespace {
|
func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
ns.AutoPrefix(prefix, c)
|
ns.AutoPrefix(prefix, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace add sub Namespace
|
// NSNamespace add sub Namespace
|
||||||
func NSNamespace(prefix string, params ...innnerNamespace) innnerNamespace {
|
func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace {
|
||||||
return func(ns *Namespace) {
|
return func(ns *Namespace) {
|
||||||
n := NewNamespace(prefix, params...)
|
n := NewNamespace(prefix, params...)
|
||||||
ns.Namespace(n)
|
ns.Namespace(n)
|
||||||
|
10
orm/db.go
10
orm/db.go
@ -802,6 +802,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
|
|||||||
tables.parseRelated(qs.related, qs.relDepth)
|
tables.parseRelated(qs.related, qs.relDepth)
|
||||||
|
|
||||||
where, args := tables.getCondSql(cond, false, tz)
|
where, args := tables.getCondSql(cond, false, tz)
|
||||||
|
groupBy := tables.getGroupSql(qs.groups)
|
||||||
orderBy := tables.getOrderSql(qs.orders)
|
orderBy := tables.getOrderSql(qs.orders)
|
||||||
limit := tables.getLimitSql(mi, offset, rlimit)
|
limit := tables.getLimitSql(mi, offset, rlimit)
|
||||||
join := tables.getJoinSql()
|
join := tables.getJoinSql()
|
||||||
@ -814,7 +815,11 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s", sels, Q, mi.table, Q, join, where, orderBy, limit)
|
sqlSelect := "SELECT"
|
||||||
|
if qs.distinct {
|
||||||
|
sqlSelect += " DISTINCT"
|
||||||
|
}
|
||||||
|
query := fmt.Sprintf("%s %s FROM %s%s%s T0 %s%s%s%s%s", sqlSelect, sels, Q, mi.table, Q, join, where, groupBy, orderBy, limit)
|
||||||
|
|
||||||
d.ins.ReplaceMarks(&query)
|
d.ins.ReplaceMarks(&query)
|
||||||
|
|
||||||
@ -1444,13 +1449,14 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
|
|||||||
}
|
}
|
||||||
|
|
||||||
where, args := tables.getCondSql(cond, false, tz)
|
where, args := tables.getCondSql(cond, false, tz)
|
||||||
|
groupBy := tables.getGroupSql(qs.groups)
|
||||||
orderBy := tables.getOrderSql(qs.orders)
|
orderBy := tables.getOrderSql(qs.orders)
|
||||||
limit := tables.getLimitSql(mi, qs.offset, qs.limit)
|
limit := tables.getLimitSql(mi, qs.offset, qs.limit)
|
||||||
join := tables.getJoinSql()
|
join := tables.getJoinSql()
|
||||||
|
|
||||||
sels := strings.Join(cols, ", ")
|
sels := strings.Join(cols, ", ")
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s", sels, Q, mi.table, Q, join, where, orderBy, limit)
|
query := fmt.Sprintf("SELECT %s FROM %s%s%s T0 %s%s%s%s%s", sels, Q, mi.table, Q, join, where, groupBy,orderBy, limit)
|
||||||
|
|
||||||
d.ins.ReplaceMarks(&query)
|
d.ins.ReplaceMarks(&query)
|
||||||
|
|
||||||
|
@ -390,6 +390,30 @@ func (t *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate group sql.
|
||||||
|
func (t *dbTables) getGroupSql(groups []string) (groupSql string) {
|
||||||
|
if len(groups) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Q := t.base.TableQuote()
|
||||||
|
|
||||||
|
groupSqls := make([]string, 0, len(groups))
|
||||||
|
for _, group := range groups {
|
||||||
|
exprs := strings.Split(group, ExprSep)
|
||||||
|
|
||||||
|
index, _, fi, suc := t.parseExprs(t.mi, exprs)
|
||||||
|
if suc == false {
|
||||||
|
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
|
||||||
|
}
|
||||||
|
|
||||||
|
groupSqls = append(groupSqls, fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q))
|
||||||
|
}
|
||||||
|
|
||||||
|
groupSql = fmt.Sprintf("GROUP BY %s ", strings.Join(groupSqls, ", "))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// generate order sql.
|
// generate order sql.
|
||||||
func (t *dbTables) getOrderSql(orders []string) (orderSql string) {
|
func (t *dbTables) getOrderSql(orders []string) (orderSql string) {
|
||||||
if len(orders) == 0 {
|
if len(orders) == 0 {
|
||||||
|
@ -60,7 +60,9 @@ type querySet struct {
|
|||||||
relDepth int
|
relDepth int
|
||||||
limit int64
|
limit int64
|
||||||
offset int64
|
offset int64
|
||||||
|
groups []string
|
||||||
orders []string
|
orders []string
|
||||||
|
distinct bool
|
||||||
orm *orm
|
orm *orm
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +107,12 @@ func (o querySet) Offset(offset interface{}) QuerySeter {
|
|||||||
return &o
|
return &o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add GROUP expression
|
||||||
|
func (o querySet) GroupBy(exprs ...string) QuerySeter {
|
||||||
|
o.groups = exprs
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
// add ORDER expression.
|
// add ORDER expression.
|
||||||
// "column" means ASC, "-column" means DESC.
|
// "column" means ASC, "-column" means DESC.
|
||||||
func (o querySet) OrderBy(exprs ...string) QuerySeter {
|
func (o querySet) OrderBy(exprs ...string) QuerySeter {
|
||||||
@ -112,6 +120,12 @@ func (o querySet) OrderBy(exprs ...string) QuerySeter {
|
|||||||
return &o
|
return &o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add DISTINCT to SELECT
|
||||||
|
func (o querySet) Distinct() QuerySeter {
|
||||||
|
o.distinct = true
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
// set relation model to query together.
|
// set relation model to query together.
|
||||||
// it will query relation models and assign to parent model.
|
// it will query relation models and assign to parent model.
|
||||||
func (o querySet) RelatedSel(params ...interface{}) QuerySeter {
|
func (o querySet) RelatedSel(params ...interface{}) QuerySeter {
|
||||||
|
@ -66,7 +66,9 @@ type QuerySeter interface {
|
|||||||
SetCond(*Condition) QuerySeter
|
SetCond(*Condition) QuerySeter
|
||||||
Limit(interface{}, ...interface{}) QuerySeter
|
Limit(interface{}, ...interface{}) QuerySeter
|
||||||
Offset(interface{}) QuerySeter
|
Offset(interface{}) QuerySeter
|
||||||
|
GroupBy(...string) QuerySeter
|
||||||
OrderBy(...string) QuerySeter
|
OrderBy(...string) QuerySeter
|
||||||
|
Distinct() QuerySeter
|
||||||
RelatedSel(...interface{}) QuerySeter
|
RelatedSel(...interface{}) QuerySeter
|
||||||
Count() (int64, error)
|
Count() (int64, error)
|
||||||
Exist() bool
|
Exist() bool
|
||||||
|
14
parser.go
14
parser.go
@ -42,13 +42,13 @@ func init() {
|
|||||||
`
|
`
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lastupdateFilename string = "lastupdate.tmp"
|
lastupdateFilename = "lastupdate.tmp"
|
||||||
commentFilename string
|
commentFilename string
|
||||||
pkgLastupdate map[string]int64
|
pkgLastupdate map[string]int64
|
||||||
genInfoList map[string][]ControllerComments
|
genInfoList map[string][]ControllerComments
|
||||||
)
|
)
|
||||||
|
|
||||||
const COMMENTFL = "commentsRouter_"
|
const coomentPrefix = "commentsRouter_"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
pkgLastupdate = make(map[string]int64)
|
pkgLastupdate = make(map[string]int64)
|
||||||
@ -56,7 +56,7 @@ func init() {
|
|||||||
|
|
||||||
func parserPkg(pkgRealpath, pkgpath string) error {
|
func parserPkg(pkgRealpath, pkgpath string) error {
|
||||||
rep := strings.NewReplacer("/", "_", ".", "_")
|
rep := strings.NewReplacer("/", "_", ".", "_")
|
||||||
commentFilename = COMMENTFL + rep.Replace(pkgpath) + ".go"
|
commentFilename = coomentPrefix + rep.Replace(pkgpath) + ".go"
|
||||||
if !compareFile(pkgRealpath) {
|
if !compareFile(pkgRealpath) {
|
||||||
Info(pkgRealpath + " has not changed, not reloading")
|
Info(pkgRealpath + " has not changed, not reloading")
|
||||||
return nil
|
return nil
|
||||||
@ -132,9 +132,11 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
|
|||||||
func genRouterCode() {
|
func genRouterCode() {
|
||||||
os.Mkdir(path.Join(workPath, "routers"), 0755)
|
os.Mkdir(path.Join(workPath, "routers"), 0755)
|
||||||
Info("generate router from comments")
|
Info("generate router from comments")
|
||||||
var globalinfo string
|
var (
|
||||||
sortKey := make([]string, 0)
|
globalinfo string
|
||||||
for k, _ := range genInfoList {
|
sortKey []string
|
||||||
|
)
|
||||||
|
for k := range genInfoList {
|
||||||
sortKey = append(sortKey, k)
|
sortKey = append(sortKey, k)
|
||||||
}
|
}
|
||||||
sort.Strings(sortKey)
|
sort.Strings(sortKey)
|
||||||
|
@ -83,41 +83,41 @@ func APIBaiscAuth(appid, appkey string) beego.FilterFunc {
|
|||||||
func APIAuthWithFunc(f AppIdToAppSecret, timeout int) beego.FilterFunc {
|
func APIAuthWithFunc(f AppIdToAppSecret, timeout int) beego.FilterFunc {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
if ctx.Input.Query("appid") == "" {
|
if ctx.Input.Query("appid") == "" {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("miss query param: appid")
|
ctx.WriteString("miss query param: appid")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
appsecret := f(ctx.Input.Query("appid"))
|
appsecret := f(ctx.Input.Query("appid"))
|
||||||
if appsecret == "" {
|
if appsecret == "" {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("not exist this appid")
|
ctx.WriteString("not exist this appid")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ctx.Input.Query("signature") == "" {
|
if ctx.Input.Query("signature") == "" {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("miss query param: signature")
|
ctx.WriteString("miss query param: signature")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ctx.Input.Query("timestamp") == "" {
|
if ctx.Input.Query("timestamp") == "" {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("miss query param: timestamp")
|
ctx.WriteString("miss query param: timestamp")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
u, err := time.Parse("2006-01-02 15:04:05", ctx.Input.Query("timestamp"))
|
u, err := time.Parse("2006-01-02 15:04:05", ctx.Input.Query("timestamp"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("timestamp format is error, should 2006-01-02 15:04:05")
|
ctx.WriteString("timestamp format is error, should 2006-01-02 15:04:05")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
if t.Sub(u).Seconds() > float64(timeout) {
|
if t.Sub(u).Seconds() > float64(timeout) {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("timeout! the request time is long ago, please try again")
|
ctx.WriteString("timeout! the request time is long ago, please try again")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ctx.Input.Query("signature") !=
|
if ctx.Input.Query("signature") !=
|
||||||
Signature(appsecret, ctx.Input.Method(), ctx.Request.Form, ctx.Input.Uri()) {
|
Signature(appsecret, ctx.Input.Method(), ctx.Request.Form, ctx.Input.Uri()) {
|
||||||
ctx.Output.SetStatus(403)
|
ctx.ResponseWriter.WriteHeader(403)
|
||||||
ctx.WriteString("auth failed")
|
ctx.WriteString("auth failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
package cors
|
package cors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -216,8 +215,6 @@ func Allow(opts *Options) beego.FilterFunc {
|
|||||||
for key, value := range headers {
|
for key, value := range headers {
|
||||||
ctx.Output.Header(key, value)
|
ctx.Output.Header(key, value)
|
||||||
}
|
}
|
||||||
ctx.Output.SetStatus(http.StatusOK)
|
|
||||||
ctx.WriteString("")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
headers = opts.Header(origin)
|
headers = opts.Header(origin)
|
||||||
|
135
plugins/jwt/jwt.go
Normal file
135
plugins/jwt/jwt.go
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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 jwt provides JWT (Json Web Token) authentication
|
||||||
|
//
|
||||||
|
// Usage
|
||||||
|
// In file main.go
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "github.com/astaxie/beego"
|
||||||
|
// "github.com/astaxie/beego/plugins/jwt"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func main() {
|
||||||
|
// // JWT for Url matching /v1/*
|
||||||
|
// // PrivateKeyPath: The path for the private RSA key used by JWT
|
||||||
|
// // PublicKeyPath: The path for the public RSA key used by JWT
|
||||||
|
// // The list of Urls should be excluded from the JWT Auth
|
||||||
|
// beego.InsertFilter("/v1/*", beego.BeforeRouter, jwt.AuthRequest(&jwt.Options{
|
||||||
|
// PrivateKeyPath: "conf/beeblog.rsa",
|
||||||
|
// PublicKeyPath: "conf/beeblog.rsa.pub",
|
||||||
|
// WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
|
||||||
|
// }))
|
||||||
|
// beego.Run()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// In file routers/router.go
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "github.com/astaxie/beego"
|
||||||
|
// "github.com/astaxie/beego/plugins/jwt"
|
||||||
|
// )
|
||||||
|
// func init() {
|
||||||
|
// ns := beego.NSNamespace("/jwt",
|
||||||
|
// beego.NSInclude(
|
||||||
|
// &jwt.JwtController{},
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// beego.AddNamespace(ns)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
|
"github.com/astaxie/beego/logs"
|
||||||
|
goJwt "github.com/dgrijalva/jwt-go"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options for the JWT Auth
|
||||||
|
type Options struct {
|
||||||
|
PrivateKeyPath string
|
||||||
|
PublicKeyPath string
|
||||||
|
WhiteList []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var RSAKeys struct {
|
||||||
|
PrivateKey []byte
|
||||||
|
PublicKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthRequest(o *Options) beego.FilterFunc {
|
||||||
|
RSAKeys.PrivateKey, _ = ioutil.ReadFile(o.PrivateKeyPath)
|
||||||
|
RSAKeys.PublicKey, _ = ioutil.ReadFile(o.PublicKeyPath)
|
||||||
|
|
||||||
|
return func(ctx *context.Context) {
|
||||||
|
// :TODO the url patterns should be considered here.
|
||||||
|
// Shouldn't only use the string equal
|
||||||
|
for _, method := range o.WhiteList {
|
||||||
|
if method == ctx.Request.URL.Path {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedToken, err := goJwt.ParseFromRequest(ctx.Request, func(t *goJwt.Token) (interface{}, error) {
|
||||||
|
return RSAKeys.PublicKey, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err == nil && parsedToken.Valid {
|
||||||
|
ctx.Output.SetStatus(http.StatusOK)
|
||||||
|
} else {
|
||||||
|
ctx.Output.SetStatus(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// oprations for Jwt
|
||||||
|
type JwtController struct {
|
||||||
|
beego.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *JwtController) URLMapping() {
|
||||||
|
this.Mapping("IssueToken", this.IssueToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Title IssueToken
|
||||||
|
// @Description Issue a Json Web Token
|
||||||
|
// @Success 200 string
|
||||||
|
// @Failure 403 no privilege to access
|
||||||
|
// @Failure 500 server inner error
|
||||||
|
// @router /issue-token [get]
|
||||||
|
func (this *JwtController) IssueToken() {
|
||||||
|
this.Data["json"] = CreateToken()
|
||||||
|
this.ServeJson()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateToken() map[string]string {
|
||||||
|
log := logs.NewLogger(10000)
|
||||||
|
log.SetLogger("console", "")
|
||||||
|
|
||||||
|
token := goJwt.New(goJwt.GetSigningMethod("RS256")) // Create a Token that will be signed with RSA 256.
|
||||||
|
token.Claims["ID"] = "This is my super fake ID"
|
||||||
|
token.Claims["exp"] = time.Now().Unix() + 36000
|
||||||
|
// The claims object allows you to store information in the actual token.
|
||||||
|
tokenString, _ := token.SignedString(RSAKeys.PrivateKey)
|
||||||
|
// tokenString Contains the actual token you should share with your client.
|
||||||
|
return map[string]string{"token": tokenString}
|
||||||
|
}
|
88
plugins/jwt/jwt_test.go
Normal file
88
plugins/jwt/jwt_test.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/astaxie/beego"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testRequest(method, path string) (*httptest.ResponseRecorder, *http.Request) {
|
||||||
|
request, _ := http.NewRequest(method, path, nil)
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
|
||||||
|
return recorder, request
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IssueTokenAction(t *testing.T) {
|
||||||
|
url := "/v1/jwt/issue-token"
|
||||||
|
|
||||||
|
mux := beego.NewControllerRegister()
|
||||||
|
|
||||||
|
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
|
||||||
|
PrivateKeyPath: "test/jwt.rsa",
|
||||||
|
PublicKeyPath: "test/jwt.rsa.pub",
|
||||||
|
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
|
||||||
|
}))
|
||||||
|
|
||||||
|
mux.Add("/v1/jwt/issue-token", &JwtController{}, "get:IssueToken")
|
||||||
|
|
||||||
|
rw, r := testRequest("GET", url)
|
||||||
|
mux.ServeHTTP(rw, r)
|
||||||
|
|
||||||
|
if rw.Code != http.StatusOK {
|
||||||
|
t.Errorf("Shoud return 200")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc *JwtController) Foo() {
|
||||||
|
tc.Ctx.Output.Body([]byte("ok"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_AuthRequestWithAuthorizationHeader(t *testing.T) {
|
||||||
|
|
||||||
|
url := "/foo"
|
||||||
|
|
||||||
|
mux := beego.NewControllerRegister()
|
||||||
|
|
||||||
|
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
|
||||||
|
PrivateKeyPath: "test/jwt.rsa",
|
||||||
|
PublicKeyPath: "test/jwt.rsa.pub",
|
||||||
|
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
|
||||||
|
}))
|
||||||
|
|
||||||
|
mux.Add("/foo", &JwtController{}, "get:Foo")
|
||||||
|
newToken := CreateToken()
|
||||||
|
|
||||||
|
rw, r := testRequest("GET", url)
|
||||||
|
r.Header.Add("Authorization", "Bearer "+newToken["token"])
|
||||||
|
mux.ServeHTTP(rw, r)
|
||||||
|
|
||||||
|
if rw.Code != http.StatusOK {
|
||||||
|
t.Errorf("Shoud return 200")
|
||||||
|
}
|
||||||
|
if rw.Body.String() != "ok" {
|
||||||
|
t.Errorf("Should output ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_AuthRequestWithoutAuthorizationHeader(t *testing.T) {
|
||||||
|
url := "/foo"
|
||||||
|
|
||||||
|
mux := beego.NewControllerRegister()
|
||||||
|
|
||||||
|
mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{
|
||||||
|
PrivateKeyPath: "test/jwt.rsa",
|
||||||
|
PublicKeyPath: "test/jwt.rsa.pub",
|
||||||
|
WhiteList: []string{"/v1/jwt/issue-token", "/docs"},
|
||||||
|
}))
|
||||||
|
|
||||||
|
mux.Add("/foo", &JwtController{}, "get:Foo")
|
||||||
|
|
||||||
|
rw, r := testRequest("GET", url)
|
||||||
|
mux.ServeHTTP(rw, r)
|
||||||
|
|
||||||
|
if rw.Code != http.StatusUnauthorized {
|
||||||
|
t.Errorf("Shoud return 401")
|
||||||
|
}
|
||||||
|
}
|
15
plugins/jwt/test/jwt.rsa
Normal file
15
plugins/jwt/test/jwt.rsa
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICWwIBAAKBgQCdu+23Y/0J/FTQKnIPnxupoOo9/OYCv90DPXN/KLLRAMjYzgcC
|
||||||
|
DsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDhbaGWuTdQUX9zmiLoQ4I7X6h0
|
||||||
|
dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/tB3PVRG9j6B1Ibz5CnQIDAQAB
|
||||||
|
AoGAFGg+/i4ai9MwqeoD7c95Bb5C8BgrLgnir0uhCL+cOvwuABbPw01jRoLuEi58
|
||||||
|
Mp5vzaXLXByFSA+ts03/qMbvZkDGac5g5kLli5TjHIONMxVBrdfGQ1+OApnaPayN
|
||||||
|
N+HYjZKs6xao6J5iFqfA0FqzDR9kQhUoeosdQoo1GlxDckECQQDO/0LJrFiLzYWe
|
||||||
|
qS/DxfAnFu2BlClKZjxRJ3vIkRRaON6HPl8BeJW901bFKG5+WSfO+OwQ9egWaf3X
|
||||||
|
fFm/oEHRAkEAwxMor4fOkBZbL4KPW7sen169vwnXuYusqj0t3dIeiIVrCigkOMT4
|
||||||
|
OvX/63u4CTdXh1D5u/4Z/1HTYH92VCP7DQJAJPxbNKnE0IYSf/z++d4eQP3JxkNw
|
||||||
|
9Ug7Msz5QycZGd3bdRLh6uNe7iIa+PN2esD3afX0SDuIEqkxoBUp/CFoYQJAUmi3
|
||||||
|
mV+/7bLkFrALK+9iwmTdt+TKk4HkEY8C32CysW3biFDo7GqZix79XFfJqWsNuQaG
|
||||||
|
WdrA1NGWgH+YV3dTyQJAIWEZGAuUXRkQB20LfjGzpsKgQFbqjTisMS0qe3JjnDwu
|
||||||
|
0JR8sYXapgeEEEisH+OtkZKIfyeFOwoUyNC83bcvgw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
6
plugins/jwt/test/jwt.rsa.pub
Normal file
6
plugins/jwt/test/jwt.rsa.pub
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdu+23Y/0J/FTQKnIPnxupoOo9
|
||||||
|
/OYCv90DPXN/KLLRAMjYzgcCDsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDh
|
||||||
|
baGWuTdQUX9zmiLoQ4I7X6h0dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/t
|
||||||
|
B3PVRG9j6B1Ibz5CnQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
160
router.go
160
router.go
@ -34,8 +34,8 @@ import (
|
|||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// default filter execution points
|
// default filter execution points
|
||||||
|
const (
|
||||||
BeforeStatic = iota
|
BeforeStatic = iota
|
||||||
BeforeRouter
|
BeforeRouter
|
||||||
BeforeExec
|
BeforeExec
|
||||||
@ -50,7 +50,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// supported http methods.
|
// HTTPMETHOD list the supported http methods.
|
||||||
HTTPMETHOD = map[string]string{
|
HTTPMETHOD = map[string]string{
|
||||||
"GET": "GET",
|
"GET": "GET",
|
||||||
"POST": "POST",
|
"POST": "POST",
|
||||||
@ -71,10 +71,12 @@ var (
|
|||||||
"SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml",
|
"SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml",
|
||||||
"GetControllerAndAction"}
|
"GetControllerAndAction"}
|
||||||
|
|
||||||
url_placeholder = "{{placeholder}}"
|
urlPlaceholder = "{{placeholder}}"
|
||||||
DefaultLogFilter FilterHandler = &logFilter{}
|
// DefaultAccessLogFilter will skip the accesslog if return true
|
||||||
|
DefaultAccessLogFilter FilterHandler = &logFilter{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FilterHandler is an interface for
|
||||||
type FilterHandler interface {
|
type FilterHandler interface {
|
||||||
Filter(*beecontext.Context) bool
|
Filter(*beecontext.Context) bool
|
||||||
}
|
}
|
||||||
@ -96,7 +98,7 @@ func (l *logFilter) Filter(ctx *beecontext.Context) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// To append a slice's value into "exceptMethod", for controller's methods shouldn't reflect to AutoRouter
|
// ExceptMethodAppend to append a slice's value into "exceptMethod", for controller's methods shouldn't reflect to AutoRouter
|
||||||
func ExceptMethodAppend(action string) {
|
func ExceptMethodAppend(action string) {
|
||||||
exceptMethod = append(exceptMethod, action)
|
exceptMethod = append(exceptMethod, action)
|
||||||
}
|
}
|
||||||
@ -110,22 +112,22 @@ type controllerInfo struct {
|
|||||||
routerType int
|
routerType int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerRegistor containers registered router rules, controller handlers and filters.
|
// ControllerRegister containers registered router rules, controller handlers and filters.
|
||||||
type ControllerRegistor struct {
|
type ControllerRegister struct {
|
||||||
routers map[string]*Tree
|
routers map[string]*Tree
|
||||||
enableFilter bool
|
enableFilter bool
|
||||||
filters map[int][]*FilterRouter
|
filters map[int][]*FilterRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewControllerRegister returns a new ControllerRegistor.
|
// NewControllerRegister returns a new ControllerRegister.
|
||||||
func NewControllerRegister() *ControllerRegistor {
|
func NewControllerRegister() *ControllerRegister {
|
||||||
return &ControllerRegistor{
|
return &ControllerRegister{
|
||||||
routers: make(map[string]*Tree),
|
routers: make(map[string]*Tree),
|
||||||
filters: make(map[int][]*FilterRouter),
|
filters: make(map[int][]*FilterRouter),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add controller handler and pattern rules to ControllerRegistor.
|
// Add controller handler and pattern rules to ControllerRegister.
|
||||||
// usage:
|
// usage:
|
||||||
// default methods is the same name as method
|
// default methods is the same name as method
|
||||||
// Add("/user",&UserController{})
|
// Add("/user",&UserController{})
|
||||||
@ -135,7 +137,7 @@ func NewControllerRegister() *ControllerRegistor {
|
|||||||
// Add("/api/delete",&RestController{},"delete:DeleteFood")
|
// Add("/api/delete",&RestController{},"delete:DeleteFood")
|
||||||
// Add("/api",&RestController{},"get,post:ApiFunc")
|
// Add("/api",&RestController{},"get,post:ApiFunc")
|
||||||
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
|
||||||
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
|
||||||
reflectVal := reflect.ValueOf(c)
|
reflectVal := reflect.ValueOf(c)
|
||||||
t := reflect.Indirect(reflectVal).Type()
|
t := reflect.Indirect(reflectVal).Type()
|
||||||
methods := make(map[string]string)
|
methods := make(map[string]string)
|
||||||
@ -183,7 +185,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegistor) addToRouter(method, pattern string, r *controllerInfo) {
|
func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerInfo) {
|
||||||
if !RouterCaseSensitive {
|
if !RouterCaseSensitive {
|
||||||
pattern = strings.ToLower(pattern)
|
pattern = strings.ToLower(pattern)
|
||||||
}
|
}
|
||||||
@ -196,9 +198,9 @@ func (p *ControllerRegistor) addToRouter(method, pattern string, r *controllerIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only when the Runmode is dev will generate router file in the router/auto.go from the controller
|
// Include only when the Runmode is dev will generate router file in the router/auto.go from the controller
|
||||||
// Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
|
// Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
|
||||||
func (p *ControllerRegistor) Include(cList ...ControllerInterface) {
|
func (p *ControllerRegister) Include(cList ...ControllerInterface) {
|
||||||
if RunMode == "dev" {
|
if RunMode == "dev" {
|
||||||
skip := make(map[string]bool, 10)
|
skip := make(map[string]bool, 10)
|
||||||
for _, c := range cList {
|
for _, c := range cList {
|
||||||
@ -238,84 +240,84 @@ func (p *ControllerRegistor) Include(cList ...ControllerInterface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add get method
|
// Get add get method
|
||||||
// usage:
|
// usage:
|
||||||
// Get("/", func(ctx *context.Context){
|
// Get("/", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Get(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Get(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("get", pattern, f)
|
p.AddMethod("get", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add post method
|
// Post add post method
|
||||||
// usage:
|
// usage:
|
||||||
// Post("/api", func(ctx *context.Context){
|
// Post("/api", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Post(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Post(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("post", pattern, f)
|
p.AddMethod("post", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add put method
|
// Put add put method
|
||||||
// usage:
|
// usage:
|
||||||
// Put("/api/:id", func(ctx *context.Context){
|
// Put("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Put(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Put(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("put", pattern, f)
|
p.AddMethod("put", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add delete method
|
// Delete add delete method
|
||||||
// usage:
|
// usage:
|
||||||
// Delete("/api/:id", func(ctx *context.Context){
|
// Delete("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Delete(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Delete(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("delete", pattern, f)
|
p.AddMethod("delete", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add head method
|
// Head add head method
|
||||||
// usage:
|
// usage:
|
||||||
// Head("/api/:id", func(ctx *context.Context){
|
// Head("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Head(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Head(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("head", pattern, f)
|
p.AddMethod("head", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add patch method
|
// Patch add patch method
|
||||||
// usage:
|
// usage:
|
||||||
// Patch("/api/:id", func(ctx *context.Context){
|
// Patch("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Patch(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Patch(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("patch", pattern, f)
|
p.AddMethod("patch", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add options method
|
// Options add options method
|
||||||
// usage:
|
// usage:
|
||||||
// Options("/api/:id", func(ctx *context.Context){
|
// Options("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Options(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Options(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("options", pattern, f)
|
p.AddMethod("options", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add all method
|
// Any add all method
|
||||||
// usage:
|
// usage:
|
||||||
// Any("/api/:id", func(ctx *context.Context){
|
// Any("/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) Any(pattern string, f FilterFunc) {
|
func (p *ControllerRegister) Any(pattern string, f FilterFunc) {
|
||||||
p.AddMethod("*", pattern, f)
|
p.AddMethod("*", pattern, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add http method router
|
// AddMethod add http method router
|
||||||
// usage:
|
// usage:
|
||||||
// AddMethod("get","/api/:id", func(ctx *context.Context){
|
// AddMethod("get","/api/:id", func(ctx *context.Context){
|
||||||
// ctx.Output.Body("hello world")
|
// ctx.Output.Body("hello world")
|
||||||
// })
|
// })
|
||||||
func (p *ControllerRegistor) AddMethod(method, pattern string, f FilterFunc) {
|
func (p *ControllerRegister) AddMethod(method, pattern string, f FilterFunc) {
|
||||||
if _, ok := HTTPMETHOD[strings.ToUpper(method)]; method != "*" && !ok {
|
if _, ok := HTTPMETHOD[strings.ToUpper(method)]; method != "*" && !ok {
|
||||||
panic("not support http method: " + method)
|
panic("not support http method: " + method)
|
||||||
}
|
}
|
||||||
@ -343,8 +345,8 @@ func (p *ControllerRegistor) AddMethod(method, pattern string, f FilterFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add user defined Handler
|
// Handler add user defined Handler
|
||||||
func (p *ControllerRegistor) Handler(pattern string, h http.Handler, options ...interface{}) {
|
func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ...interface{}) {
|
||||||
route := &controllerInfo{}
|
route := &controllerInfo{}
|
||||||
route.pattern = pattern
|
route.pattern = pattern
|
||||||
route.routerType = routerTypeHandler
|
route.routerType = routerTypeHandler
|
||||||
@ -359,21 +361,21 @@ func (p *ControllerRegistor) Handler(pattern string, h http.Handler, options ...
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add auto router to ControllerRegistor.
|
// AddAuto router to ControllerRegister.
|
||||||
// example beego.AddAuto(&MainContorlller{}),
|
// example beego.AddAuto(&MainContorlller{}),
|
||||||
// MainController has method List and Page.
|
// MainController has method List and Page.
|
||||||
// visit the url /main/list to execute List function
|
// visit the url /main/list to execute List function
|
||||||
// /main/page to execute Page function.
|
// /main/page to execute Page function.
|
||||||
func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
|
func (p *ControllerRegister) AddAuto(c ControllerInterface) {
|
||||||
p.AddAutoPrefix("/", c)
|
p.AddAutoPrefix("/", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add auto router to ControllerRegistor with prefix.
|
// AddAutoPrefix Add auto router to ControllerRegister with prefix.
|
||||||
// example beego.AddAutoPrefix("/admin",&MainContorlller{}),
|
// example beego.AddAutoPrefix("/admin",&MainContorlller{}),
|
||||||
// MainController has method List and Page.
|
// MainController has method List and Page.
|
||||||
// visit the url /admin/main/list to execute List function
|
// visit the url /admin/main/list to execute List function
|
||||||
// /admin/main/page to execute Page function.
|
// /admin/main/page to execute Page function.
|
||||||
func (p *ControllerRegistor) AddAutoPrefix(prefix string, c ControllerInterface) {
|
func (p *ControllerRegister) AddAutoPrefix(prefix string, c ControllerInterface) {
|
||||||
reflectVal := reflect.ValueOf(c)
|
reflectVal := reflect.ValueOf(c)
|
||||||
rt := reflectVal.Type()
|
rt := reflectVal.Type()
|
||||||
ct := reflect.Indirect(reflectVal).Type()
|
ct := reflect.Indirect(reflectVal).Type()
|
||||||
@ -399,9 +401,9 @@ func (p *ControllerRegistor) AddAutoPrefix(prefix string, c ControllerInterface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a FilterFunc with pattern rule and action constant.
|
// InsertFilter Add a FilterFunc with pattern rule and action constant.
|
||||||
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
||||||
func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error {
|
func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error {
|
||||||
|
|
||||||
mr := new(FilterRouter)
|
mr := new(FilterRouter)
|
||||||
mr.tree = NewTree()
|
mr.tree = NewTree()
|
||||||
@ -420,15 +422,15 @@ func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter Filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add Filter into
|
// add Filter into
|
||||||
func (p *ControllerRegistor) insertFilterRouter(pos int, mr *FilterRouter) error {
|
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) error {
|
||||||
p.filters[pos] = append(p.filters[pos], mr)
|
p.filters[pos] = append(p.filters[pos], mr)
|
||||||
p.enableFilter = true
|
p.enableFilter = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UrlFor does another controller handler in this request function.
|
// URLFor does another controller handler in this request function.
|
||||||
// it can access any controller method.
|
// it can access any controller method.
|
||||||
func (p *ControllerRegistor) UrlFor(endpoint string, values ...interface{}) string {
|
func (p *ControllerRegister) URLFor(endpoint string, values ...interface{}) string {
|
||||||
paths := strings.Split(endpoint, ".")
|
paths := strings.Split(endpoint, ".")
|
||||||
if len(paths) <= 1 {
|
if len(paths) <= 1 {
|
||||||
Warn("urlfor endpoint must like path.controller.method")
|
Warn("urlfor endpoint must like path.controller.method")
|
||||||
@ -460,7 +462,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...interface{}) stri
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName string, params map[string]string, httpMethod string) (bool, string) {
|
func (p *ControllerRegister) geturl(t *Tree, url, controllName, methodName string, params map[string]string, httpMethod string) (bool, string) {
|
||||||
for k, subtree := range t.fixrouters {
|
for k, subtree := range t.fixrouters {
|
||||||
u := path.Join(url, k)
|
u := path.Join(url, k)
|
||||||
ok, u := p.geturl(subtree, u, controllName, methodName, params, httpMethod)
|
ok, u := p.geturl(subtree, u, controllName, methodName, params, httpMethod)
|
||||||
@ -469,7 +471,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t.wildcard != nil {
|
if t.wildcard != nil {
|
||||||
u := path.Join(url, url_placeholder)
|
u := path.Join(url, urlPlaceholder)
|
||||||
ok, u := p.geturl(t.wildcard, u, controllName, methodName, params, httpMethod)
|
ok, u := p.geturl(t.wildcard, u, controllName, methodName, params, httpMethod)
|
||||||
if ok {
|
if ok {
|
||||||
return ok, u
|
return ok, u
|
||||||
@ -499,22 +501,21 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
if find {
|
if find {
|
||||||
if l.regexps == nil {
|
if l.regexps == nil {
|
||||||
if len(l.wildcards) == 0 {
|
if len(l.wildcards) == 0 {
|
||||||
return true, strings.Replace(url, "/"+url_placeholder, "", 1) + tourl(params)
|
return true, strings.Replace(url, "/"+urlPlaceholder, "", 1) + tourl(params)
|
||||||
}
|
}
|
||||||
if len(l.wildcards) == 1 {
|
if len(l.wildcards) == 1 {
|
||||||
if v, ok := params[l.wildcards[0]]; ok {
|
if v, ok := params[l.wildcards[0]]; ok {
|
||||||
delete(params, l.wildcards[0])
|
delete(params, l.wildcards[0])
|
||||||
return true, strings.Replace(url, url_placeholder, v, 1) + tourl(params)
|
return true, strings.Replace(url, urlPlaceholder, v, 1) + tourl(params)
|
||||||
} else {
|
|
||||||
return false, ""
|
|
||||||
}
|
}
|
||||||
|
return false, ""
|
||||||
}
|
}
|
||||||
if len(l.wildcards) == 3 && l.wildcards[0] == "." {
|
if len(l.wildcards) == 3 && l.wildcards[0] == "." {
|
||||||
if p, ok := params[":path"]; ok {
|
if p, ok := params[":path"]; ok {
|
||||||
if e, isok := params[":ext"]; isok {
|
if e, isok := params[":ext"]; isok {
|
||||||
delete(params, ":path")
|
delete(params, ":path")
|
||||||
delete(params, ":ext")
|
delete(params, ":ext")
|
||||||
return true, strings.Replace(url, url_placeholder, p+"."+e, -1) + tourl(params)
|
return true, strings.Replace(url, urlPlaceholder, p+"."+e, -1) + tourl(params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,18 +527,17 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
}
|
}
|
||||||
if u, ok := params[v]; ok {
|
if u, ok := params[v]; ok {
|
||||||
delete(params, v)
|
delete(params, v)
|
||||||
url = strings.Replace(url, url_placeholder, u, 1)
|
url = strings.Replace(url, urlPlaceholder, u, 1)
|
||||||
} else {
|
} else {
|
||||||
if canskip {
|
if canskip {
|
||||||
canskip = false
|
canskip = false
|
||||||
continue
|
continue
|
||||||
} else {
|
}
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true, url + tourl(params)
|
return true, url + tourl(params)
|
||||||
} else {
|
}
|
||||||
var i int
|
var i int
|
||||||
var startreg bool
|
var startreg bool
|
||||||
regurl := ""
|
regurl := ""
|
||||||
@ -561,7 +561,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
if l.regexps.MatchString(regurl) {
|
if l.regexps.MatchString(regurl) {
|
||||||
ps := strings.Split(regurl, "/")
|
ps := strings.Split(regurl, "/")
|
||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
url = strings.Replace(url, url_placeholder, p, 1)
|
url = strings.Replace(url, urlPlaceholder, p, 1)
|
||||||
}
|
}
|
||||||
return true, url + tourl(params)
|
return true, url + tourl(params)
|
||||||
}
|
}
|
||||||
@ -569,13 +569,12 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement http.Handler interface.
|
// Implement http.Handler interface.
|
||||||
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
starttime := time.Now()
|
starttime := time.Now()
|
||||||
var runrouter reflect.Type
|
var runrouter reflect.Type
|
||||||
var findrouter bool
|
var findrouter bool
|
||||||
@ -607,7 +606,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
urlPath = r.URL.Path
|
urlPath = r.URL.Path
|
||||||
}
|
}
|
||||||
// defined filter function
|
// defined filter function
|
||||||
do_filter := func(pos int) (started bool) {
|
doFilter := func(pos int) (started bool) {
|
||||||
if p.enableFilter {
|
if p.enableFilter {
|
||||||
if l, ok := p.filters[pos]; ok {
|
if l, ok := p.filters[pos]; ok {
|
||||||
for _, filterR := range l {
|
for _, filterR := range l {
|
||||||
@ -639,7 +638,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filter for static file
|
// filter for static file
|
||||||
if do_filter(BeforeStatic) {
|
if doFilter(BeforeStatic) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +669,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
context.Input.ParseFormOrMulitForm(MaxMemory)
|
context.Input.ParseFormOrMulitForm(MaxMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
if do_filter(BeforeRouter) {
|
if doFilter(BeforeRouter) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,17 +680,17 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !findrouter {
|
if !findrouter {
|
||||||
http_method := r.Method
|
httpMethod := r.Method
|
||||||
|
|
||||||
if http_method == "POST" && context.Input.Query("_method") == "PUT" {
|
if httpMethod == "POST" && context.Input.Query("_method") == "PUT" {
|
||||||
http_method = "PUT"
|
httpMethod = "PUT"
|
||||||
}
|
}
|
||||||
|
|
||||||
if http_method == "POST" && context.Input.Query("_method") == "DELETE" {
|
if httpMethod == "POST" && context.Input.Query("_method") == "DELETE" {
|
||||||
http_method = "DELETE"
|
httpMethod = "DELETE"
|
||||||
}
|
}
|
||||||
|
|
||||||
if t, ok := p.routers[http_method]; ok {
|
if t, ok := p.routers[httpMethod]; ok {
|
||||||
runObject, p := t.Match(urlPath)
|
runObject, p := t.Match(urlPath)
|
||||||
if r, ok := runObject.(*controllerInfo); ok {
|
if r, ok := runObject.(*controllerInfo); ok {
|
||||||
routerInfo = r
|
routerInfo = r
|
||||||
@ -718,7 +717,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
if findrouter {
|
if findrouter {
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if do_filter(BeforeExec) {
|
if doFilter(BeforeExec) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
isRunable := false
|
isRunable := false
|
||||||
@ -770,10 +769,10 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
//if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
|
//if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf
|
||||||
if EnableXSRF {
|
if EnableXSRF {
|
||||||
execController.XsrfToken()
|
execController.XSRFToken()
|
||||||
if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
|
if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" ||
|
||||||
(r.Method == "POST" && (context.Input.Query("_method") == "DELETE" || context.Input.Query("_method") == "PUT")) {
|
(r.Method == "POST" && (context.Input.Query("_method") == "DELETE" || context.Input.Query("_method") == "PUT")) {
|
||||||
execController.CheckXsrfCookie()
|
execController.CheckXSRFCookie()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,7 +797,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
execController.Options()
|
execController.Options()
|
||||||
default:
|
default:
|
||||||
if !execController.HandlerFunc(runMethod) {
|
if !execController.HandlerFunc(runMethod) {
|
||||||
in := make([]reflect.Value, 0)
|
var in []reflect.Value
|
||||||
method := vc.MethodByName(runMethod)
|
method := vc.MethodByName(runMethod)
|
||||||
method.Call(in)
|
method.Call(in)
|
||||||
}
|
}
|
||||||
@ -819,12 +818,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if do_filter(AfterExec) {
|
if doFilter(AfterExec) {
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_filter(FinishRouter)
|
doFilter(FinishRouter)
|
||||||
|
|
||||||
Admin:
|
Admin:
|
||||||
timeend := time.Since(starttime)
|
timeend := time.Since(starttime)
|
||||||
@ -850,7 +849,7 @@ Admin:
|
|||||||
} else {
|
} else {
|
||||||
devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "notmatch")
|
devinfo = fmt.Sprintf("| % -10s | % -40s | % -16s | % -10s |", r.Method, r.URL.Path, timeend.String(), "notmatch")
|
||||||
}
|
}
|
||||||
if DefaultLogFilter == nil || !DefaultLogFilter.Filter(context) {
|
if DefaultAccessLogFilter == nil || !DefaultAccessLogFilter.Filter(context) {
|
||||||
Debug(devinfo)
|
Debug(devinfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -861,15 +860,15 @@ Admin:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegistor) recoverPanic(context *beecontext.Context) {
|
func (p *ControllerRegister) recoverPanic(context *beecontext.Context) {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
if err == USERSTOPRUN {
|
if err == ErrAbort {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !RecoverPanic {
|
if !RecoverPanic {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else {
|
} else {
|
||||||
if ErrorsShow {
|
if EnableErrorsShow {
|
||||||
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
||||||
exception(fmt.Sprint(err), context)
|
exception(fmt.Sprint(err), context)
|
||||||
return
|
return
|
||||||
@ -931,6 +930,13 @@ func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|||||||
return hj.Hijack()
|
return hj.Hijack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) Flush() {
|
||||||
|
f, ok := w.writer.(http.Flusher)
|
||||||
|
if ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func tourl(params map[string]string) string {
|
func tourl(params map[string]string) string {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
return ""
|
return ""
|
||||||
|
@ -52,17 +52,17 @@ func (tc *TestController) Myext() {
|
|||||||
tc.Ctx.Output.Body([]byte(tc.Ctx.Input.Param(":ext")))
|
tc.Ctx.Output.Body([]byte(tc.Ctx.Input.Param(":ext")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TestController) GetUrl() {
|
func (tc *TestController) GetURL() {
|
||||||
tc.Ctx.Output.Body([]byte(tc.UrlFor(".Myext")))
|
tc.Ctx.Output.Body([]byte(tc.URLFor(".Myext")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestController) GetParams() {
|
func (tc *TestController) GetParams() {
|
||||||
t.Ctx.WriteString(t.Ctx.Input.Query(":last") + "+" +
|
tc.Ctx.WriteString(tc.Ctx.Input.Query(":last") + "+" +
|
||||||
t.Ctx.Input.Query(":first") + "+" + t.Ctx.Input.Query("learn"))
|
tc.Ctx.Input.Query(":first") + "+" + tc.Ctx.Input.Query("learn"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TestController) GetManyRouter() {
|
func (tc *TestController) GetManyRouter() {
|
||||||
t.Ctx.WriteString(t.Ctx.Input.Query(":id") + t.Ctx.Input.Query(":page"))
|
tc.Ctx.WriteString(tc.Ctx.Input.Query(":id") + tc.Ctx.Input.Query(":page"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResStatus struct {
|
type ResStatus struct {
|
||||||
@ -70,29 +70,29 @@ type ResStatus struct {
|
|||||||
Msg string
|
Msg string
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsonController struct {
|
type JSONController struct {
|
||||||
Controller
|
Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *JsonController) Prepare() {
|
func (jc *JSONController) Prepare() {
|
||||||
this.Data["json"] = "prepare"
|
jc.Data["json"] = "prepare"
|
||||||
this.ServeJson(true)
|
jc.ServeJSON(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *JsonController) Get() {
|
func (jc *JSONController) Get() {
|
||||||
this.Data["Username"] = "astaxie"
|
jc.Data["Username"] = "astaxie"
|
||||||
this.Ctx.Output.Body([]byte("ok"))
|
jc.Ctx.Output.Body([]byte("ok"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUrlFor(t *testing.T) {
|
func TestUrlFor(t *testing.T) {
|
||||||
handler := NewControllerRegister()
|
handler := NewControllerRegister()
|
||||||
handler.Add("/api/list", &TestController{}, "*:List")
|
handler.Add("/api/list", &TestController{}, "*:List")
|
||||||
handler.Add("/person/:last/:first", &TestController{}, "*:Param")
|
handler.Add("/person/:last/:first", &TestController{}, "*:Param")
|
||||||
if a := handler.UrlFor("TestController.List"); a != "/api/list" {
|
if a := handler.URLFor("TestController.List"); a != "/api/list" {
|
||||||
Info(a)
|
Info(a)
|
||||||
t.Errorf("TestController.List must equal to /api/list")
|
t.Errorf("TestController.List must equal to /api/list")
|
||||||
}
|
}
|
||||||
if a := handler.UrlFor("TestController.Param", ":last", "xie", ":first", "asta"); a != "/person/xie/asta" {
|
if a := handler.URLFor("TestController.Param", ":last", "xie", ":first", "asta"); a != "/person/xie/asta" {
|
||||||
t.Errorf("TestController.Param must equal to /person/xie/asta, but get " + a)
|
t.Errorf("TestController.Param must equal to /person/xie/asta, but get " + a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,39 +100,39 @@ func TestUrlFor(t *testing.T) {
|
|||||||
func TestUrlFor3(t *testing.T) {
|
func TestUrlFor3(t *testing.T) {
|
||||||
handler := NewControllerRegister()
|
handler := NewControllerRegister()
|
||||||
handler.AddAuto(&TestController{})
|
handler.AddAuto(&TestController{})
|
||||||
if a := handler.UrlFor("TestController.Myext"); a != "/test/myext" && a != "/Test/Myext" {
|
if a := handler.URLFor("TestController.Myext"); a != "/test/myext" && a != "/Test/Myext" {
|
||||||
t.Errorf("TestController.Myext must equal to /test/myext, but get " + a)
|
t.Errorf("TestController.Myext must equal to /test/myext, but get " + a)
|
||||||
}
|
}
|
||||||
if a := handler.UrlFor("TestController.GetUrl"); a != "/test/geturl" && a != "/Test/GetUrl" {
|
if a := handler.URLFor("TestController.GetURL"); a != "/test/geturl" && a != "/Test/GetURL" {
|
||||||
t.Errorf("TestController.GetUrl must equal to /test/geturl, but get " + a)
|
t.Errorf("TestController.GetURL must equal to /test/geturl, but get " + a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUrlFor2(t *testing.T) {
|
func TestUrlFor2(t *testing.T) {
|
||||||
handler := NewControllerRegister()
|
handler := NewControllerRegister()
|
||||||
handler.Add("/v1/:v/cms_:id(.+)_:page(.+).html", &TestController{}, "*:List")
|
handler.Add("/v1/:v/cms_:id(.+)_:page(.+).html", &TestController{}, "*:List")
|
||||||
handler.Add("/v1/:username/edit", &TestController{}, "get:GetUrl")
|
handler.Add("/v1/:username/edit", &TestController{}, "get:GetURL")
|
||||||
handler.Add("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", &TestController{}, "*:Param")
|
handler.Add("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", &TestController{}, "*:Param")
|
||||||
handler.Add("/:year:int/:month:int/:title/:entid", &TestController{})
|
handler.Add("/:year:int/:month:int/:title/:entid", &TestController{})
|
||||||
if handler.UrlFor("TestController.GetUrl", ":username", "astaxie") != "/v1/astaxie/edit" {
|
if handler.URLFor("TestController.GetURL", ":username", "astaxie") != "/v1/astaxie/edit" {
|
||||||
Info(handler.UrlFor("TestController.GetUrl"))
|
Info(handler.URLFor("TestController.GetURL"))
|
||||||
t.Errorf("TestController.List must equal to /v1/astaxie/edit")
|
t.Errorf("TestController.List must equal to /v1/astaxie/edit")
|
||||||
}
|
}
|
||||||
|
|
||||||
if handler.UrlFor("TestController.List", ":v", "za", ":id", "12", ":page", "123") !=
|
if handler.URLFor("TestController.List", ":v", "za", ":id", "12", ":page", "123") !=
|
||||||
"/v1/za/cms_12_123.html" {
|
"/v1/za/cms_12_123.html" {
|
||||||
Info(handler.UrlFor("TestController.List"))
|
Info(handler.URLFor("TestController.List"))
|
||||||
t.Errorf("TestController.List must equal to /v1/za/cms_12_123.html")
|
t.Errorf("TestController.List must equal to /v1/za/cms_12_123.html")
|
||||||
}
|
}
|
||||||
if handler.UrlFor("TestController.Param", ":v", "za", ":id", "12", ":page", "123") !=
|
if handler.URLFor("TestController.Param", ":v", "za", ":id", "12", ":page", "123") !=
|
||||||
"/v1/za_cms/ttt_12_123.html" {
|
"/v1/za_cms/ttt_12_123.html" {
|
||||||
Info(handler.UrlFor("TestController.Param"))
|
Info(handler.URLFor("TestController.Param"))
|
||||||
t.Errorf("TestController.List must equal to /v1/za_cms/ttt_12_123.html")
|
t.Errorf("TestController.List must equal to /v1/za_cms/ttt_12_123.html")
|
||||||
}
|
}
|
||||||
if handler.UrlFor("TestController.Get", ":year", "1111", ":month", "11",
|
if handler.URLFor("TestController.Get", ":year", "1111", ":month", "11",
|
||||||
":title", "aaaa", ":entid", "aaaa") !=
|
":title", "aaaa", ":entid", "aaaa") !=
|
||||||
"/1111/11/aaaa/aaaa" {
|
"/1111/11/aaaa/aaaa" {
|
||||||
Info(handler.UrlFor("TestController.Get"))
|
Info(handler.URLFor("TestController.Get"))
|
||||||
t.Errorf("TestController.Get must equal to /1111/11/aaaa/aaaa")
|
t.Errorf("TestController.Get must equal to /1111/11/aaaa/aaaa")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ func TestPrepare(t *testing.T) {
|
|||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
handler := NewControllerRegister()
|
handler := NewControllerRegister()
|
||||||
handler.Add("/json/list", &JsonController{})
|
handler.Add("/json/list", &JSONController{})
|
||||||
handler.ServeHTTP(w, r)
|
handler.ServeHTTP(w, r)
|
||||||
if w.Body.String() != `"prepare"` {
|
if w.Body.String() != `"prepare"` {
|
||||||
t.Errorf(w.Body.String() + "user define func can't run")
|
t.Errorf(w.Body.String() + "user define func can't run")
|
||||||
|
@ -51,7 +51,10 @@ import (
|
|||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
var mysqlpder = &MysqlProvider{}
|
var (
|
||||||
|
TableName = "session"
|
||||||
|
mysqlpder = &MysqlProvider{}
|
||||||
|
)
|
||||||
|
|
||||||
// mysql session store
|
// mysql session store
|
||||||
type MysqlSessionStore struct {
|
type MysqlSessionStore struct {
|
||||||
@ -110,7 +113,7 @@ func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
st.c.Exec("UPDATE session set `session_data`=?, `session_expiry`=? where session_key=?",
|
st.c.Exec("UPDATE "+TableName+" set `session_data`=?, `session_expiry`=? where session_key=?",
|
||||||
b, time.Now().Unix(), st.sid)
|
b, time.Now().Unix(), st.sid)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -141,11 +144,11 @@ func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
// get mysql session by sid
|
// get mysql session by sid
|
||||||
func (mp *MysqlProvider) SessionRead(sid string) (session.SessionStore, error) {
|
func (mp *MysqlProvider) SessionRead(sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
err := row.Scan(&sessiondata)
|
err := row.Scan(&sessiondata)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
c.Exec("insert into session(`session_key`,`session_data`,`session_expiry`) values(?,?,?)",
|
c.Exec("insert into "+TableName+"(`session_key`,`session_data`,`session_expiry`) values(?,?,?)",
|
||||||
sid, "", time.Now().Unix())
|
sid, "", time.Now().Unix())
|
||||||
}
|
}
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
@ -165,7 +168,7 @@ func (mp *MysqlProvider) SessionRead(sid string) (session.SessionStore, error) {
|
|||||||
func (mp *MysqlProvider) SessionExist(sid string) bool {
|
func (mp *MysqlProvider) SessionExist(sid string) bool {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", sid)
|
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", sid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
err := row.Scan(&sessiondata)
|
err := row.Scan(&sessiondata)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
@ -178,13 +181,13 @@ func (mp *MysqlProvider) SessionExist(sid string) bool {
|
|||||||
// generate new sid for mysql session
|
// generate new sid for mysql session
|
||||||
func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.SessionStore, error) {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
row := c.QueryRow("select session_data from session where session_key=?", oldsid)
|
row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid)
|
||||||
var sessiondata []byte
|
var sessiondata []byte
|
||||||
err := row.Scan(&sessiondata)
|
err := row.Scan(&sessiondata)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
c.Exec("insert into session(`session_key`,`session_data`,`session_expiry`) values(?,?,?)", oldsid, "", time.Now().Unix())
|
c.Exec("insert into "+TableName+"(`session_key`,`session_data`,`session_expiry`) values(?,?,?)", oldsid, "", time.Now().Unix())
|
||||||
}
|
}
|
||||||
c.Exec("update session set `session_key`=? where session_key=?", sid, oldsid)
|
c.Exec("update "+TableName+" set `session_key`=? where session_key=?", sid, oldsid)
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
if len(sessiondata) == 0 {
|
if len(sessiondata) == 0 {
|
||||||
kv = make(map[interface{}]interface{})
|
kv = make(map[interface{}]interface{})
|
||||||
@ -201,7 +204,7 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (session.SessionS
|
|||||||
// delete mysql session by sid
|
// delete mysql session by sid
|
||||||
func (mp *MysqlProvider) SessionDestroy(sid string) error {
|
func (mp *MysqlProvider) SessionDestroy(sid string) error {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
c.Exec("DELETE FROM session where session_key=?", sid)
|
c.Exec("DELETE FROM "+TableName+" where session_key=?", sid)
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -209,7 +212,7 @@ func (mp *MysqlProvider) SessionDestroy(sid string) error {
|
|||||||
// delete expired values in mysql session
|
// delete expired values in mysql session
|
||||||
func (mp *MysqlProvider) SessionGC() {
|
func (mp *MysqlProvider) SessionGC() {
|
||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
|
c.Exec("DELETE from "+TableName+" where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -219,7 +222,7 @@ func (mp *MysqlProvider) SessionAll() int {
|
|||||||
c := mp.connectInit()
|
c := mp.connectInit()
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
var total int
|
var total int
|
||||||
err := c.QueryRow("SELECT count(*) as num from session").Scan(&total)
|
err := c.QueryRow("SELECT count(*) as num from " + TableName).Scan(&total)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -40,16 +40,14 @@ func serverStaticRouter(ctx *context.Context) {
|
|||||||
if utils.FileExists(file) {
|
if utils.FileExists(file) {
|
||||||
http.ServeFile(ctx.ResponseWriter, ctx.Request, file)
|
http.ServeFile(ctx.ResponseWriter, ctx.Request, file)
|
||||||
return
|
return
|
||||||
} else {
|
}
|
||||||
i++
|
i++
|
||||||
if i == len(StaticDir) {
|
if i == len(StaticDir) {
|
||||||
http.NotFound(ctx.ResponseWriter, ctx.Request)
|
http.NotFound(ctx.ResponseWriter, ctx.Request)
|
||||||
return
|
return
|
||||||
} else {
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(requestPath, prefix) {
|
if strings.HasPrefix(requestPath, prefix) {
|
||||||
if len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
|
if len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
|
||||||
continue
|
continue
|
||||||
|
70
template.go
70
template.go
@ -28,17 +28,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
beegoTplFuncMap template.FuncMap
|
beegoTplFuncMap = make(template.FuncMap)
|
||||||
// beego template caching map and supported template file extensions.
|
// BeeTemplates caching map and supported template file extensions.
|
||||||
BeeTemplates map[string]*template.Template
|
BeeTemplates = make(map[string]*template.Template)
|
||||||
BeeTemplateExt []string
|
// BeeTemplateExt stores the template extention which will build
|
||||||
|
BeeTemplateExt = []string{"tpl", "html"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
BeeTemplates = make(map[string]*template.Template)
|
|
||||||
beegoTplFuncMap = make(template.FuncMap)
|
|
||||||
BeeTemplateExt = make([]string, 0)
|
|
||||||
BeeTemplateExt = append(BeeTemplateExt, "tpl", "html")
|
|
||||||
beegoTplFuncMap["dateformat"] = DateFormat
|
beegoTplFuncMap["dateformat"] = DateFormat
|
||||||
beegoTplFuncMap["date"] = Date
|
beegoTplFuncMap["date"] = Date
|
||||||
beegoTplFuncMap["compare"] = Compare
|
beegoTplFuncMap["compare"] = Compare
|
||||||
@ -46,14 +43,15 @@ func init() {
|
|||||||
beegoTplFuncMap["not_nil"] = NotNil
|
beegoTplFuncMap["not_nil"] = NotNil
|
||||||
beegoTplFuncMap["not_null"] = NotNil
|
beegoTplFuncMap["not_null"] = NotNil
|
||||||
beegoTplFuncMap["substr"] = Substr
|
beegoTplFuncMap["substr"] = Substr
|
||||||
beegoTplFuncMap["html2str"] = Html2str
|
beegoTplFuncMap["html2str"] = HTML2str
|
||||||
beegoTplFuncMap["str2html"] = Str2html
|
beegoTplFuncMap["str2html"] = Str2html
|
||||||
beegoTplFuncMap["htmlquote"] = Htmlquote
|
beegoTplFuncMap["htmlquote"] = Htmlquote
|
||||||
beegoTplFuncMap["htmlunquote"] = Htmlunquote
|
beegoTplFuncMap["htmlunquote"] = Htmlunquote
|
||||||
beegoTplFuncMap["renderform"] = RenderForm
|
beegoTplFuncMap["renderform"] = RenderForm
|
||||||
beegoTplFuncMap["assets_js"] = AssetsJs
|
beegoTplFuncMap["assets_js"] = AssetsJs
|
||||||
beegoTplFuncMap["assets_css"] = AssetsCss
|
beegoTplFuncMap["assets_css"] = AssetsCSS
|
||||||
beegoTplFuncMap["config"] = Config
|
beegoTplFuncMap["config"] = Config
|
||||||
|
beegoTplFuncMap["map_get"] = MapGet
|
||||||
|
|
||||||
// go1.2 added template funcs
|
// go1.2 added template funcs
|
||||||
// Comparisons
|
// Comparisons
|
||||||
@ -64,7 +62,7 @@ func init() {
|
|||||||
beegoTplFuncMap["lt"] = lt // <
|
beegoTplFuncMap["lt"] = lt // <
|
||||||
beegoTplFuncMap["ne"] = ne // !=
|
beegoTplFuncMap["ne"] = ne // !=
|
||||||
|
|
||||||
beegoTplFuncMap["urlfor"] = UrlFor // !=
|
beegoTplFuncMap["urlfor"] = URLFor // !=
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFuncMap let user to register a func in the template.
|
// AddFuncMap let user to register a func in the template.
|
||||||
@ -78,7 +76,7 @@ type templatefile struct {
|
|||||||
files map[string][]string
|
files map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -91,21 +89,21 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
|||||||
|
|
||||||
replace := strings.NewReplacer("\\", "/")
|
replace := strings.NewReplacer("\\", "/")
|
||||||
a := []byte(paths)
|
a := []byte(paths)
|
||||||
a = a[len([]byte(self.root)):]
|
a = a[len([]byte(tf.root)):]
|
||||||
file := strings.TrimLeft(replace.Replace(string(a)), "/")
|
file := strings.TrimLeft(replace.Replace(string(a)), "/")
|
||||||
subdir := filepath.Dir(file)
|
subdir := filepath.Dir(file)
|
||||||
if _, ok := self.files[subdir]; ok {
|
if _, ok := tf.files[subdir]; ok {
|
||||||
self.files[subdir] = append(self.files[subdir], file)
|
tf.files[subdir] = append(tf.files[subdir], file)
|
||||||
} else {
|
} else {
|
||||||
m := make([]string, 1)
|
m := make([]string, 1)
|
||||||
m[0] = file
|
m[0] = file
|
||||||
self.files[subdir] = m
|
tf.files[subdir] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// return this path contains supported template extension of beego or not.
|
// HasTemplateExt return this path contains supported template extension of beego or not.
|
||||||
func HasTemplateExt(paths string) bool {
|
func HasTemplateExt(paths string) bool {
|
||||||
for _, v := range BeeTemplateExt {
|
for _, v := range BeeTemplateExt {
|
||||||
if strings.HasSuffix(paths, "."+v) {
|
if strings.HasSuffix(paths, "."+v) {
|
||||||
@ -115,7 +113,7 @@ func HasTemplateExt(paths string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// add new extension for template.
|
// AddTemplateExt add new extension for template.
|
||||||
func AddTemplateExt(ext string) {
|
func AddTemplateExt(ext string) {
|
||||||
for _, v := range BeeTemplateExt {
|
for _, v := range BeeTemplateExt {
|
||||||
if v == ext {
|
if v == ext {
|
||||||
@ -125,15 +123,14 @@ func AddTemplateExt(ext string) {
|
|||||||
BeeTemplateExt = append(BeeTemplateExt, ext)
|
BeeTemplateExt = append(BeeTemplateExt, ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// build all template files in a directory.
|
// BuildTemplate will build all template files in a directory.
|
||||||
// it makes beego can render any template file in view directory.
|
// it makes beego can render any template file in view directory.
|
||||||
func BuildTemplate(dir string) error {
|
func BuildTemplate(dir string, files ...string) error {
|
||||||
if _, err := os.Stat(dir); err != nil {
|
if _, err := os.Stat(dir); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
return errors.New("dir open err")
|
|
||||||
}
|
}
|
||||||
|
return errors.New("dir open err")
|
||||||
}
|
}
|
||||||
self := &templatefile{
|
self := &templatefile{
|
||||||
root: dir,
|
root: dir,
|
||||||
@ -148,6 +145,7 @@ func BuildTemplate(dir string) error {
|
|||||||
}
|
}
|
||||||
for _, v := range self.files {
|
for _, v := range self.files {
|
||||||
for _, file := range v {
|
for _, file := range v {
|
||||||
|
if len(files) == 0 || utils.InSlice(file, files) {
|
||||||
t, err := getTemplate(self.root, file, v...)
|
t, err := getTemplate(self.root, file, v...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Trace("parse template err:", file, err)
|
Trace("parse template err:", file, err)
|
||||||
@ -156,6 +154,7 @@ func BuildTemplate(dir string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,3 +259,30 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetViewsPath sets view directory path in beego application.
|
||||||
|
func SetViewsPath(path string) *App {
|
||||||
|
ViewsPath = path
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStaticPath sets static directory path and proper url pattern in beego application.
|
||||||
|
// if beego.SetStaticPath("static","public"), visit /static/* to load static file in folder "public".
|
||||||
|
func SetStaticPath(url string, path string) *App {
|
||||||
|
if !strings.HasPrefix(url, "/") {
|
||||||
|
url = "/" + url
|
||||||
|
}
|
||||||
|
url = strings.TrimRight(url, "/")
|
||||||
|
StaticDir[url] = path
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelStaticPath removes the static folder setting in this url pattern in beego application.
|
||||||
|
func DelStaticPath(url string) *App {
|
||||||
|
if !strings.HasPrefix(url, "/") {
|
||||||
|
url = "/" + url
|
||||||
|
}
|
||||||
|
url = strings.TrimRight(url, "/")
|
||||||
|
delete(StaticDir, url)
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
@ -20,11 +20,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var header string = `{{define "header"}}
|
var header = `{{define "header"}}
|
||||||
<h1>Hello, astaxie!</h1>
|
<h1>Hello, astaxie!</h1>
|
||||||
{{end}}`
|
{{end}}`
|
||||||
|
|
||||||
var index string = `<!DOCTYPE html>
|
var index = `<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>beego welcome template</title>
|
<title>beego welcome template</title>
|
||||||
@ -37,7 +37,7 @@ var index string = `<!DOCTYPE html>
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
var block string = `{{define "block"}}
|
var block = `{{define "block"}}
|
||||||
<h1>Hello, blocks!</h1>
|
<h1>Hello, blocks!</h1>
|
||||||
{{end}}`
|
{{end}}`
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ func TestTemplate(t *testing.T) {
|
|||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
var menu string = `<div class="menu">
|
var menu = `<div class="menu">
|
||||||
<ul>
|
<ul>
|
||||||
<li>menu1</li>
|
<li>menu1</li>
|
||||||
<li>menu2</li>
|
<li>menu2</li>
|
||||||
@ -90,7 +90,7 @@ var menu string = `<div class="menu">
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
var user string = `<!DOCTYPE html>
|
var user = `<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>beego welcome template</title>
|
<title>beego welcome template</title>
|
||||||
@ -123,7 +123,7 @@ func TestRelativeTemplate(t *testing.T) {
|
|||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := BuildTemplate(dir); err != nil {
|
if err := BuildTemplate(dir, files[1]); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := BeeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil {
|
if err := BeeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil {
|
||||||
|
118
templatefunc.go
118
templatefunc.go
@ -44,8 +44,8 @@ func Substr(s string, start, length int) string {
|
|||||||
return string(bt[start:end])
|
return string(bt[start:end])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Html2str returns escaping text convert from html.
|
// HTML2str returns escaping text convert from html.
|
||||||
func Html2str(html string) string {
|
func HTML2str(html string) string {
|
||||||
src := string(html)
|
src := string(html)
|
||||||
|
|
||||||
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
|
re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
|
||||||
@ -115,7 +115,7 @@ var datePatterns = []string{
|
|||||||
"r", time.RFC1123Z,
|
"r", time.RFC1123Z,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse Date use PHP time format.
|
// DateParse Parse Date use PHP time format.
|
||||||
func DateParse(dateString, format string) (time.Time, error) {
|
func DateParse(dateString, format string) (time.Time, error) {
|
||||||
replacer := strings.NewReplacer(datePatterns...)
|
replacer := strings.NewReplacer(datePatterns...)
|
||||||
format = replacer.Replace(format)
|
format = replacer.Replace(format)
|
||||||
@ -139,14 +139,17 @@ func Compare(a, b interface{}) (equal bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CompareNot !Compare
|
||||||
func CompareNot(a, b interface{}) (equal bool) {
|
func CompareNot(a, b interface{}) (equal bool) {
|
||||||
return !Compare(a, b)
|
return !Compare(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotNil(a interface{}) (is_nil bool) {
|
// NotNil the same as CompareNot
|
||||||
|
func NotNil(a interface{}) (isNil bool) {
|
||||||
return CompareNot(a, nil)
|
return CompareNot(a, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config get the Appconfig
|
||||||
func Config(returnType, key string, defaultVal interface{}) (value interface{}, err error) {
|
func Config(returnType, key string, defaultVal interface{}) (value interface{}, err error) {
|
||||||
switch returnType {
|
switch returnType {
|
||||||
case "String":
|
case "String":
|
||||||
@ -162,12 +165,12 @@ func Config(returnType, key string, defaultVal interface{}) (value interface{},
|
|||||||
case "DIY":
|
case "DIY":
|
||||||
value, err = AppConfig.DIY(key)
|
value, err = AppConfig.DIY(key)
|
||||||
default:
|
default:
|
||||||
err = errors.New("Config keys must be of type String, Bool, Int, Int64, Float, or DIY!")
|
err = errors.New("Config keys must be of type String, Bool, Int, Int64, Float, or DIY")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if reflect.TypeOf(returnType) != reflect.TypeOf(defaultVal) {
|
if reflect.TypeOf(returnType) != reflect.TypeOf(defaultVal) {
|
||||||
err = errors.New("defaultVal type does not match returnType!")
|
err = errors.New("defaultVal type does not match returnType")
|
||||||
} else {
|
} else {
|
||||||
value, err = defaultVal, nil
|
value, err = defaultVal, nil
|
||||||
}
|
}
|
||||||
@ -184,7 +187,7 @@ func Config(returnType, key string, defaultVal interface{}) (value interface{},
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert string to template.HTML type.
|
// Str2html Convert string to template.HTML type.
|
||||||
func Str2html(raw string) template.HTML {
|
func Str2html(raw string) template.HTML {
|
||||||
return template.HTML(raw)
|
return template.HTML(raw)
|
||||||
}
|
}
|
||||||
@ -237,14 +240,14 @@ func Htmlunquote(src string) string {
|
|||||||
return strings.TrimSpace(text)
|
return strings.TrimSpace(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UrlFor returns url string with another registered controller handler with params.
|
// URLFor returns url string with another registered controller handler with params.
|
||||||
// usage:
|
// usage:
|
||||||
//
|
//
|
||||||
// UrlFor(".index")
|
// URLFor(".index")
|
||||||
// print UrlFor("index")
|
// print URLFor("index")
|
||||||
// router /login
|
// router /login
|
||||||
// print UrlFor("login")
|
// print URLFor("login")
|
||||||
// print UrlFor("login", "next","/"")
|
// print URLFor("login", "next","/"")
|
||||||
// router /profile/:username
|
// router /profile/:username
|
||||||
// print UrlFor("profile", ":username","John Doe")
|
// print UrlFor("profile", ":username","John Doe")
|
||||||
// result:
|
// result:
|
||||||
@ -254,11 +257,11 @@ func Htmlunquote(src string) string {
|
|||||||
// /user/John%20Doe
|
// /user/John%20Doe
|
||||||
//
|
//
|
||||||
// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
|
// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
|
||||||
func UrlFor(endpoint string, values ...interface{}) string {
|
func URLFor(endpoint string, values ...interface{}) string {
|
||||||
return BeeApp.Handlers.UrlFor(endpoint, values...)
|
return BeeApp.Handlers.URLFor(endpoint, values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns script tag with src string.
|
// AssetsJs returns script tag with src string.
|
||||||
func AssetsJs(src string) template.HTML {
|
func AssetsJs(src string) template.HTML {
|
||||||
text := string(src)
|
text := string(src)
|
||||||
|
|
||||||
@ -267,8 +270,8 @@ func AssetsJs(src string) template.HTML {
|
|||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns stylesheet link tag with src string.
|
// AssetsCSS returns stylesheet link tag with src string.
|
||||||
func AssetsCss(src string) template.HTML {
|
func AssetsCSS(src string) template.HTML {
|
||||||
text := string(src)
|
text := string(src)
|
||||||
|
|
||||||
text = "<link href=\"" + src + "\" rel=\"stylesheet\" />"
|
text = "<link href=\"" + src + "\" rel=\"stylesheet\" />"
|
||||||
@ -276,7 +279,7 @@ func AssetsCss(src string) template.HTML {
|
|||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse form values to struct via tag.
|
// ParseForm will parse form values to struct via tag.
|
||||||
func ParseForm(form url.Values, obj interface{}) error {
|
func ParseForm(form url.Values, obj interface{}) error {
|
||||||
objT := reflect.TypeOf(obj)
|
objT := reflect.TypeOf(obj)
|
||||||
objV := reflect.ValueOf(obj)
|
objV := reflect.ValueOf(obj)
|
||||||
@ -352,7 +355,7 @@ func ParseForm(form url.Values, obj interface{}) error {
|
|||||||
if len(tags) > 1 {
|
if len(tags) > 1 {
|
||||||
format = tags[1]
|
format = tags[1]
|
||||||
}
|
}
|
||||||
t, err := time.Parse(format, value)
|
t, err := time.ParseInLocation(format, value, time.Local)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -398,7 +401,7 @@ var unKind = map[reflect.Kind]bool{
|
|||||||
reflect.UnsafePointer: true,
|
reflect.UnsafePointer: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// render object to form html.
|
// RenderForm will render object to form html.
|
||||||
// obj must be a struct pointer.
|
// obj must be a struct pointer.
|
||||||
func RenderForm(obj interface{}) template.HTML {
|
func RenderForm(obj interface{}) template.HTML {
|
||||||
objT := reflect.TypeOf(obj)
|
objT := reflect.TypeOf(obj)
|
||||||
@ -651,4 +654,77 @@ func ge(arg1, arg2 interface{}) (bool, error) {
|
|||||||
return !lessThan, nil
|
return !lessThan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// go1.2 added template funcs. end
|
// MapGet getting value from map by keys
|
||||||
|
// usage:
|
||||||
|
// Data["m"] = map[string]interface{} {
|
||||||
|
// "a": 1,
|
||||||
|
// "1": map[string]float64{
|
||||||
|
// "c": 4,
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {{ map_get m "a" }} // return 1
|
||||||
|
// {{ map_get m 1 "c" }} // return 4
|
||||||
|
func MapGet(arg1 interface{}, arg2 ...interface{}) (interface{}, error) {
|
||||||
|
arg1Type := reflect.TypeOf(arg1)
|
||||||
|
arg1Val := reflect.ValueOf(arg1)
|
||||||
|
|
||||||
|
if arg1Type.Kind() == reflect.Map && len(arg2) > 0 {
|
||||||
|
// check whether arg2[0] type equals to arg1 key type
|
||||||
|
// if they are different, make convertion
|
||||||
|
arg2Val := reflect.ValueOf(arg2[0])
|
||||||
|
arg2Type := reflect.TypeOf(arg2[0])
|
||||||
|
if arg2Type.Kind() != arg1Type.Key().Kind() {
|
||||||
|
// convert arg2Value to string
|
||||||
|
var arg2ConvertedVal interface{}
|
||||||
|
arg2String := fmt.Sprintf("%v", arg2[0])
|
||||||
|
|
||||||
|
// convert string representation to any other type
|
||||||
|
switch arg1Type.Key().Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
arg2ConvertedVal, _ = strconv.ParseBool(arg2String)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
arg2ConvertedVal, _ = strconv.ParseInt(arg2String, 0, 64)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
arg2ConvertedVal, _ = strconv.ParseUint(arg2String, 0, 64)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
arg2ConvertedVal, _ = strconv.ParseFloat(arg2String, 64)
|
||||||
|
case reflect.String:
|
||||||
|
arg2ConvertedVal = arg2String
|
||||||
|
default:
|
||||||
|
arg2ConvertedVal = arg2Val.Interface()
|
||||||
|
}
|
||||||
|
arg2Val = reflect.ValueOf(arg2ConvertedVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
storedVal := arg1Val.MapIndex(arg2Val)
|
||||||
|
|
||||||
|
if storedVal.IsValid() {
|
||||||
|
var result interface{}
|
||||||
|
|
||||||
|
switch arg1Type.Elem().Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
result = storedVal.Bool()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
result = storedVal.Int()
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
result = storedVal.Uint()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
result = storedVal.Float()
|
||||||
|
case reflect.String:
|
||||||
|
result = storedVal.String()
|
||||||
|
default:
|
||||||
|
result = storedVal.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is more keys, handle this recursively
|
||||||
|
if len(arg2) > 1 {
|
||||||
|
return MapGet(result, arg2[1:]...)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ func TestHtml2str(t *testing.T) {
|
|||||||
|
|
||||||
|
|
||||||
\n`
|
\n`
|
||||||
if Html2str(h) != "123\\n\n\\n" {
|
if HTML2str(h) != "123\\n\n\\n" {
|
||||||
t.Error("should be equal")
|
t.Error("should be equal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ func TestHtmlunquote(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseForm(t *testing.T) {
|
func TestParseForm(t *testing.T) {
|
||||||
type user struct {
|
type user struct {
|
||||||
Id int `form:"-"`
|
ID int `form:"-"`
|
||||||
tag string `form:"tag"`
|
tag string `form:"tag"`
|
||||||
Name interface{} `form:"username"`
|
Name interface{} `form:"username"`
|
||||||
Age int `form:"age,text"`
|
Age int `form:"age,text"`
|
||||||
@ -123,7 +123,7 @@ func TestParseForm(t *testing.T) {
|
|||||||
|
|
||||||
u := user{}
|
u := user{}
|
||||||
form := url.Values{
|
form := url.Values{
|
||||||
"Id": []string{"1"},
|
"ID": []string{"1"},
|
||||||
"-": []string{"1"},
|
"-": []string{"1"},
|
||||||
"tag": []string{"no"},
|
"tag": []string{"no"},
|
||||||
"username": []string{"test"},
|
"username": []string{"test"},
|
||||||
@ -139,8 +139,8 @@ func TestParseForm(t *testing.T) {
|
|||||||
if err := ParseForm(form, &u); err != nil {
|
if err := ParseForm(form, &u); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if u.Id != 0 {
|
if u.ID != 0 {
|
||||||
t.Errorf("Id should equal 0 but got %v", u.Id)
|
t.Errorf("ID should equal 0 but got %v", u.ID)
|
||||||
}
|
}
|
||||||
if len(u.tag) != 0 {
|
if len(u.tag) != 0 {
|
||||||
t.Errorf("tag's length should equal 0 but got %v", len(u.tag))
|
t.Errorf("tag's length should equal 0 but got %v", len(u.tag))
|
||||||
@ -168,7 +168,7 @@ func TestParseForm(t *testing.T) {
|
|||||||
|
|
||||||
func TestRenderForm(t *testing.T) {
|
func TestRenderForm(t *testing.T) {
|
||||||
type user struct {
|
type user struct {
|
||||||
Id int `form:"-"`
|
ID int `form:"-"`
|
||||||
tag string `form:"tag"`
|
tag string `form:"tag"`
|
||||||
Name interface{} `form:"username"`
|
Name interface{} `form:"username"`
|
||||||
Age int `form:"age,text,年龄:"`
|
Age int `form:"age,text,年龄:"`
|
||||||
@ -244,3 +244,80 @@ func TestParseFormTag(t *testing.T) {
|
|||||||
t.Errorf("Form Tag that should be ignored was not correctly parsed.")
|
t.Errorf("Form Tag that should be ignored was not correctly parsed.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMapGet(t *testing.T) {
|
||||||
|
// test one level map
|
||||||
|
m1 := map[string]int64{
|
||||||
|
"a": 1,
|
||||||
|
"1": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err := MapGet(m1, "a"); err == nil {
|
||||||
|
if res.(int64) != 1 {
|
||||||
|
t.Errorf("Should return 1, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err := MapGet(m1, "1"); err == nil {
|
||||||
|
if res.(int64) != 2 {
|
||||||
|
t.Errorf("Should return 2, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err := MapGet(m1, 1); err == nil {
|
||||||
|
if res.(int64) != 2 {
|
||||||
|
t.Errorf("Should return 2, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test 2 level map
|
||||||
|
m2 := map[string]interface{}{
|
||||||
|
"1": map[string]float64{
|
||||||
|
"2": 3.5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err := MapGet(m2, 1, 2); err == nil {
|
||||||
|
if res.(float64) != 3.5 {
|
||||||
|
t.Errorf("Should return 3.5, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test 5 level map
|
||||||
|
m5 := map[string]interface{}{
|
||||||
|
"1": map[string]interface{}{
|
||||||
|
"2": map[string]interface{}{
|
||||||
|
"3": map[string]interface{}{
|
||||||
|
"4": map[string]interface{}{
|
||||||
|
"5": 1.2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err := MapGet(m5, 1, 2, 3, 4, 5); err == nil {
|
||||||
|
if res.(float64) != 1.2 {
|
||||||
|
t.Errorf("Should return 1.2, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether element not exists in map
|
||||||
|
if res, err := MapGet(m5, 5, 4, 3, 2, 1); err == nil {
|
||||||
|
if res != nil {
|
||||||
|
t.Errorf("Should return nil, but return %v", res)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Error happens %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
31
tree.go
31
tree.go
@ -22,6 +22,10 @@ import (
|
|||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Tree has three elements: FixRouter/wildcard/leaves
|
||||||
|
// fixRouter sotres Fixed Router
|
||||||
|
// wildcard stores params
|
||||||
|
// leaves store the endpoint information
|
||||||
type Tree struct {
|
type Tree struct {
|
||||||
//search fix route first
|
//search fix route first
|
||||||
fixrouters map[string]*Tree
|
fixrouters map[string]*Tree
|
||||||
@ -33,13 +37,14 @@ type Tree struct {
|
|||||||
leaves []*leafInfo
|
leaves []*leafInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTree return a new Tree
|
||||||
func NewTree() *Tree {
|
func NewTree() *Tree {
|
||||||
return &Tree{
|
return &Tree{
|
||||||
fixrouters: make(map[string]*Tree),
|
fixrouters: make(map[string]*Tree),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add Tree to the exist Tree
|
// AddTree will add tree to the exist Tree
|
||||||
// prefix should has no params
|
// prefix should has no params
|
||||||
func (t *Tree) AddTree(prefix string, tree *Tree) {
|
func (t *Tree) AddTree(prefix string, tree *Tree) {
|
||||||
t.addtree(splitPath(prefix), tree, nil, "")
|
t.addtree(splitPath(prefix), tree, nil, "")
|
||||||
@ -187,7 +192,7 @@ func filterTreeWithPrefix(t *Tree, wildcards []string, reg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// call addseg function
|
// AddRouter call addseg function
|
||||||
func (t *Tree) AddRouter(pattern string, runObject interface{}) {
|
func (t *Tree) AddRouter(pattern string, runObject interface{}) {
|
||||||
t.addseg(splitPath(pattern), runObject, nil, "")
|
t.addseg(splitPath(pattern), runObject, nil, "")
|
||||||
}
|
}
|
||||||
@ -266,7 +271,7 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// match router to runObject & params
|
// Match router to runObject & params
|
||||||
func (t *Tree) Match(pattern string) (runObject interface{}, params map[string]string) {
|
func (t *Tree) Match(pattern string) (runObject interface{}, params map[string]string) {
|
||||||
if len(pattern) == 0 || pattern[0] != '/' {
|
if len(pattern) == 0 || pattern[0] != '/' {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -349,7 +354,7 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
params[v] = ""
|
params[v] = ""
|
||||||
j += 1
|
j++
|
||||||
}
|
}
|
||||||
return true, params
|
return true, params
|
||||||
}
|
}
|
||||||
@ -402,7 +407,7 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
params[v] = wildcardValues[j]
|
params[v] = wildcardValues[j]
|
||||||
j += 1
|
j++
|
||||||
}
|
}
|
||||||
if len(params) != len(wildcardValues) {
|
if len(params) != len(wildcardValues) {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -453,9 +458,8 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
if strings.HasPrefix(key, "*") {
|
if strings.HasPrefix(key, "*") {
|
||||||
if key == "*.*" {
|
if key == "*.*" {
|
||||||
return true, []string{".", ":path", ":ext"}, ""
|
return true, []string{".", ":path", ":ext"}, ""
|
||||||
} else {
|
|
||||||
return true, []string{":splat"}, ""
|
|
||||||
}
|
}
|
||||||
|
return true, []string{":splat"}, ""
|
||||||
}
|
}
|
||||||
if strings.ContainsAny(key, ":") {
|
if strings.ContainsAny(key, ":") {
|
||||||
var paramsNum int
|
var paramsNum int
|
||||||
@ -469,7 +473,7 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
reg := regexp.MustCompile(`[a-zA-Z0-9_]+`)
|
reg := regexp.MustCompile(`[a-zA-Z0-9_]+`)
|
||||||
for i, v := range key {
|
for i, v := range key {
|
||||||
if skipnum > 0 {
|
if skipnum > 0 {
|
||||||
skipnum -= 1
|
skipnum--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if start {
|
if start {
|
||||||
@ -483,7 +487,7 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
startexp = false
|
startexp = false
|
||||||
skipnum = 3
|
skipnum = 3
|
||||||
param = make([]rune, 0)
|
param = make([]rune, 0)
|
||||||
paramsNum += 1
|
paramsNum++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,7 +495,7 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
if key[i+1:i+7] == "string" {
|
if key[i+1:i+7] == "string" {
|
||||||
out = append(out, []rune(`([\w]+)`)...)
|
out = append(out, []rune(`([\w]+)`)...)
|
||||||
params = append(params, ":"+string(param))
|
params = append(params, ":"+string(param))
|
||||||
paramsNum += 1
|
paramsNum++
|
||||||
start = false
|
start = false
|
||||||
startexp = false
|
startexp = false
|
||||||
skipnum = 6
|
skipnum = 6
|
||||||
@ -509,7 +513,7 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
out = append(out, []rune(`(.+)`)...)
|
out = append(out, []rune(`(.+)`)...)
|
||||||
params = append(params, ":"+string(param))
|
params = append(params, ":"+string(param))
|
||||||
param = make([]rune, 0)
|
param = make([]rune, 0)
|
||||||
paramsNum += 1
|
paramsNum++
|
||||||
start = false
|
start = false
|
||||||
startexp = false
|
startexp = false
|
||||||
}
|
}
|
||||||
@ -527,7 +531,7 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
startexp = true
|
startexp = true
|
||||||
start = false
|
start = false
|
||||||
params = append(params, ":"+string(param))
|
params = append(params, ":"+string(param))
|
||||||
paramsNum += 1
|
paramsNum++
|
||||||
expt = make([]rune, 0)
|
expt = make([]rune, 0)
|
||||||
expt = append(expt, '(')
|
expt = append(expt, '(')
|
||||||
} else if v == ')' {
|
} else if v == ')' {
|
||||||
@ -548,7 +552,6 @@ func splitSegment(key string) (bool, []string, string) {
|
|||||||
params = append(params, ":"+string(param))
|
params = append(params, ":"+string(param))
|
||||||
}
|
}
|
||||||
return true, params, string(out)
|
return true, params, string(out)
|
||||||
} else {
|
}
|
||||||
return false, nil, ""
|
return false, nil, ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -457,7 +457,7 @@ func (b Base64) GetLimitValue() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// just for chinese mobile phone number
|
// just for chinese mobile phone number
|
||||||
var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][67]|[4][579]))\\d{8}$")
|
var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][067]|[4][579]))\\d{8}$")
|
||||||
|
|
||||||
type Mobile struct {
|
type Mobile struct {
|
||||||
Match
|
Match
|
||||||
|
Loading…
Reference in New Issue
Block a user