mirror of
https://github.com/astaxie/beego.git
synced 2024-11-25 22:11:29 +00:00
change a log about new version
This commit is contained in:
parent
5b9ae54441
commit
bd61dd9ffc
108
app.go
Normal file
108
app.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package beego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/fcgi"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FilterFunc func(*context.Context)
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
Handlers *ControllerRegistor
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new PatternServeMux.
|
||||||
|
func NewApp() *App {
|
||||||
|
cr := NewControllerRegistor()
|
||||||
|
app := &App{Handlers: cr}
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) Run() {
|
||||||
|
addr := HttpAddr
|
||||||
|
|
||||||
|
if HttpPort != 0 {
|
||||||
|
addr = fmt.Sprintf("%s:%d", HttpAddr, HttpPort)
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
l net.Listener
|
||||||
|
)
|
||||||
|
if UseFcgi {
|
||||||
|
if HttpPort == 0 {
|
||||||
|
l, err = net.Listen("unix", addr)
|
||||||
|
} else {
|
||||||
|
l, err = net.Listen("tcp", addr)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
BeeLogger.Fatal("Listen: ", err)
|
||||||
|
}
|
||||||
|
err = fcgi.Serve(l, app.Handlers)
|
||||||
|
} else {
|
||||||
|
if EnableHotUpdate {
|
||||||
|
server := &http.Server{
|
||||||
|
Handler: app.Handlers,
|
||||||
|
ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
||||||
|
WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
||||||
|
}
|
||||||
|
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
|
if nil != err {
|
||||||
|
BeeLogger.Fatal("ResolveTCPAddr:", err)
|
||||||
|
}
|
||||||
|
l, err = GetInitListner(laddr)
|
||||||
|
theStoppable = newStoppable(l)
|
||||||
|
err = server.Serve(theStoppable)
|
||||||
|
theStoppable.wg.Wait()
|
||||||
|
CloseSelf()
|
||||||
|
} else {
|
||||||
|
s := &http.Server{
|
||||||
|
Addr: addr,
|
||||||
|
Handler: app.Handlers,
|
||||||
|
ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
||||||
|
WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
||||||
|
}
|
||||||
|
if HttpTLS {
|
||||||
|
err = s.ListenAndServeTLS(HttpCertFile, HttpKeyFile)
|
||||||
|
} else {
|
||||||
|
err = s.ListenAndServe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
BeeLogger.Fatal("ListenAndServe: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
|
||||||
|
app.Handlers.Add(path, c, mappingMethods...)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) AutoRouter(c ControllerInterface) *App {
|
||||||
|
app.Handlers.AddAuto(c)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) Filter(pattern, action string, filter FilterFunc) *App {
|
||||||
|
app.Handlers.AddFilter(pattern, action, filter)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) SetViewsPath(path string) *App {
|
||||||
|
ViewsPath = path
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) SetStaticPath(url string, path string) *App {
|
||||||
|
StaticDir[url] = path
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *App) DelStaticPath(url string) *App {
|
||||||
|
delete(StaticDir, url)
|
||||||
|
return app
|
||||||
|
}
|
256
beego.go
256
beego.go
@ -1,221 +1,13 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
"html/template"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/fcgi"
|
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "0.9.0"
|
const VERSION = "0.9.0"
|
||||||
|
|
||||||
var (
|
|
||||||
BeeApp *App
|
|
||||||
AppName string
|
|
||||||
AppPath string
|
|
||||||
AppConfigPath string
|
|
||||||
StaticDir map[string]string
|
|
||||||
TemplateCache map[string]*template.Template
|
|
||||||
HttpAddr string
|
|
||||||
HttpPort int
|
|
||||||
RecoverPanic bool
|
|
||||||
AutoRender bool
|
|
||||||
PprofOn bool
|
|
||||||
ViewsPath string
|
|
||||||
RunMode string //"dev" or "prod"
|
|
||||||
AppConfig *Config
|
|
||||||
//related to session
|
|
||||||
GlobalSessions *session.Manager //GlobalSessions
|
|
||||||
SessionOn bool // whether auto start session,default is false
|
|
||||||
SessionProvider string // default session provider memory mysql redis
|
|
||||||
SessionName string // sessionName cookie's name
|
|
||||||
SessionGCMaxLifetime int64 // session's gc maxlifetime
|
|
||||||
SessionSavePath string // session savepath if use mysql/redis/file this set to the connectinfo
|
|
||||||
UseFcgi bool
|
|
||||||
MaxMemory int64
|
|
||||||
EnableGzip bool // enable gzip
|
|
||||||
DirectoryIndex bool //enable DirectoryIndex default is false
|
|
||||||
EnableHotUpdate bool //enable HotUpdate default is false
|
|
||||||
HttpServerTimeOut int64 //set httpserver timeout
|
|
||||||
ErrorsShow bool //set weather show errors
|
|
||||||
XSRFKEY string //set XSRF
|
|
||||||
EnableXSRF bool
|
|
||||||
XSRFExpire int
|
|
||||||
CopyRequestBody bool //When in raw application, You want to the reqeustbody
|
|
||||||
TemplateLeft string
|
|
||||||
TemplateRight string
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
os.Chdir(path.Dir(os.Args[0]))
|
|
||||||
BeeApp = NewApp()
|
|
||||||
AppPath, _ = os.Getwd()
|
|
||||||
StaticDir = make(map[string]string)
|
|
||||||
TemplateCache = make(map[string]*template.Template)
|
|
||||||
HttpAddr = ""
|
|
||||||
HttpPort = 8080
|
|
||||||
AppName = "beego"
|
|
||||||
RunMode = "dev" //default runmod
|
|
||||||
AutoRender = true
|
|
||||||
RecoverPanic = true
|
|
||||||
PprofOn = false
|
|
||||||
ViewsPath = "views"
|
|
||||||
SessionOn = false
|
|
||||||
SessionProvider = "memory"
|
|
||||||
SessionName = "beegosessionID"
|
|
||||||
SessionGCMaxLifetime = 3600
|
|
||||||
SessionSavePath = ""
|
|
||||||
UseFcgi = false
|
|
||||||
MaxMemory = 1 << 26 //64MB
|
|
||||||
EnableGzip = false
|
|
||||||
StaticDir["/static"] = "static"
|
|
||||||
AppConfigPath = path.Join(AppPath, "conf", "app.conf")
|
|
||||||
HttpServerTimeOut = 0
|
|
||||||
ErrorsShow = true
|
|
||||||
XSRFKEY = "beegoxsrf"
|
|
||||||
XSRFExpire = 60
|
|
||||||
TemplateLeft = "{{"
|
|
||||||
TemplateRight = "}}"
|
|
||||||
ParseConfig()
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
||||||
}
|
|
||||||
|
|
||||||
type App struct {
|
|
||||||
Handlers *ControllerRegistor
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new PatternServeMux.
|
|
||||||
func NewApp() *App {
|
|
||||||
cr := NewControllerRegistor()
|
|
||||||
app := &App{Handlers: cr}
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) Run() {
|
|
||||||
addr := HttpAddr
|
|
||||||
|
|
||||||
if HttpPort != 0 {
|
|
||||||
addr = fmt.Sprintf("%s:%d", HttpAddr, HttpPort)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
l net.Listener
|
|
||||||
)
|
|
||||||
if UseFcgi {
|
|
||||||
if HttpPort == 0 {
|
|
||||||
l, err = net.Listen("unix", addr)
|
|
||||||
} else {
|
|
||||||
l, err = net.Listen("tcp", addr)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
BeeLogger.Fatal("Listen: ", err)
|
|
||||||
}
|
|
||||||
err = fcgi.Serve(l, app.Handlers)
|
|
||||||
} else {
|
|
||||||
if EnableHotUpdate {
|
|
||||||
server := &http.Server{
|
|
||||||
Handler: app.Handlers,
|
|
||||||
ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
|
||||||
WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
|
||||||
}
|
|
||||||
laddr, err := net.ResolveTCPAddr("tcp", addr)
|
|
||||||
if nil != err {
|
|
||||||
BeeLogger.Fatal("ResolveTCPAddr:", err)
|
|
||||||
}
|
|
||||||
l, err = GetInitListner(laddr)
|
|
||||||
theStoppable = newStoppable(l)
|
|
||||||
err = server.Serve(theStoppable)
|
|
||||||
theStoppable.wg.Wait()
|
|
||||||
CloseSelf()
|
|
||||||
} else {
|
|
||||||
s := &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
Handler: app.Handlers,
|
|
||||||
ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
|
||||||
WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second,
|
|
||||||
}
|
|
||||||
err = s.ListenAndServe()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
BeeLogger.Fatal("ListenAndServe: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
|
|
||||||
app.Handlers.Add(path, c, mappingMethods...)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) AutoRouter(c ControllerInterface) *App {
|
|
||||||
app.Handlers.AddAuto(c)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) Filter(filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.Filter(filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) FilterParam(param string, filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.FilterParam(param, filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) FilterPrefixPath(path string, filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.FilterPrefixPath(path, filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) FilterAfter(filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.FilterAfter(filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) FilterParamAfter(param string, filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.FilterParamAfter(param, filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) FilterPrefixPathAfter(path string, filter http.HandlerFunc) *App {
|
|
||||||
app.Handlers.FilterPrefixPathAfter(path, filter)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) SetViewsPath(path string) *App {
|
|
||||||
ViewsPath = path
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) SetStaticPath(url string, path string) *App {
|
|
||||||
StaticDir[url] = path
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) DelStaticPath(url string) *App {
|
|
||||||
delete(StaticDir, url)
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) ErrorLog(ctx *Context) {
|
|
||||||
BeeLogger.Printf("[ERR] host: '%s', request: '%s %s', proto: '%s', ua: '%s', remote: '%s'\n", ctx.Request.Host, ctx.Request.Method, ctx.Request.URL.Path, ctx.Request.Proto, ctx.Request.UserAgent(), ctx.Request.RemoteAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *App) AccessLog(ctx *Context) {
|
|
||||||
BeeLogger.Printf("[ACC] host: '%s', request: '%s %s', proto: '%s', ua: '%s', remote: '%s'\n", ctx.Request.Host, ctx.Request.Method, ctx.Request.URL.Path, ctx.Request.Proto, ctx.Request.UserAgent(), ctx.Request.RemoteAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterController(path string, c ControllerInterface) *App {
|
|
||||||
BeeApp.Router(path, c)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
|
func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
|
||||||
BeeApp.Router(rootpath, c, mappingMethods...)
|
BeeApp.Router(rootpath, c, mappingMethods...)
|
||||||
return BeeApp
|
return BeeApp
|
||||||
@ -232,11 +24,6 @@ func AutoRouter(c ControllerInterface) *App {
|
|||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
func RouterHandler(path string, c http.Handler) *App {
|
|
||||||
BeeApp.Handlers.AddHandler(path, c)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func Errorhandler(err string, h http.HandlerFunc) *App {
|
func Errorhandler(err string, h http.HandlerFunc) *App {
|
||||||
ErrorMaps[err] = h
|
ErrorMaps[err] = h
|
||||||
return BeeApp
|
return BeeApp
|
||||||
@ -257,37 +44,18 @@ func DelStaticPath(url string) *App {
|
|||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
func Filter(filter http.HandlerFunc) *App {
|
//action has four values:
|
||||||
BeeApp.Filter(filter)
|
//BeforRouter
|
||||||
return BeeApp
|
//AfterStatic
|
||||||
}
|
//BeforExec
|
||||||
|
//AfterExec
|
||||||
func FilterParam(param string, filter http.HandlerFunc) *App {
|
func AddFilter(pattern, action string, filter FilterFunc) *App {
|
||||||
BeeApp.FilterParam(param, filter)
|
BeeApp.Filter(pattern, action, filter)
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func FilterPrefixPath(path string, filter http.HandlerFunc) *App {
|
|
||||||
BeeApp.FilterPrefixPath(path, filter)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func FilterAfter(filter http.HandlerFunc) *App {
|
|
||||||
BeeApp.FilterAfter(filter)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func FilterParamAfter(param string, filter http.HandlerFunc) *App {
|
|
||||||
BeeApp.FilterParamAfter(param, filter)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
func FilterPrefixPathAfter(path string, filter http.HandlerFunc) *App {
|
|
||||||
BeeApp.FilterPrefixPathAfter(path, filter)
|
|
||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run() {
|
func Run() {
|
||||||
|
//if AppConfigPath not In the conf/app.conf reParse config
|
||||||
if AppConfigPath != path.Join(AppPath, "conf", "app.conf") {
|
if AppConfigPath != path.Join(AppPath, "conf", "app.conf") {
|
||||||
err := ParseConfig()
|
err := ParseConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -296,20 +64,20 @@ func Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if PprofOn {
|
|
||||||
BeeApp.Router(`/debug/pprof`, &ProfController{})
|
|
||||||
BeeApp.Router(`/debug/pprof/:pp([\w]+)`, &ProfController{})
|
|
||||||
}
|
|
||||||
if SessionOn {
|
if SessionOn {
|
||||||
GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath)
|
GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath)
|
||||||
go GlobalSessions.GC()
|
go GlobalSessions.GC()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if AutoRender {
|
||||||
err := BuildTemplate(ViewsPath)
|
err := BuildTemplate(ViewsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if RunMode == "dev" {
|
if RunMode == "dev" {
|
||||||
Warn(err)
|
Warn(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
registerErrorHander()
|
registerErrorHander()
|
||||||
BeeApp.Run()
|
BeeApp.Run()
|
||||||
}
|
}
|
||||||
|
199
config.go
199
config.go
@ -1,131 +1,91 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"github.com/astaxie/beego/config"
|
||||||
"bytes"
|
"github.com/astaxie/beego/session"
|
||||||
"errors"
|
"html/template"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"unicode"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
bComment = []byte{'#'}
|
BeeApp *App
|
||||||
bEmpty = []byte{}
|
AppName string
|
||||||
bEqual = []byte{'='}
|
AppPath string
|
||||||
bDQuote = []byte{'"'}
|
AppConfigPath string
|
||||||
|
StaticDir map[string]string
|
||||||
|
TemplateCache map[string]*template.Template
|
||||||
|
HttpAddr string
|
||||||
|
HttpPort int
|
||||||
|
HttpTLS bool
|
||||||
|
HttpCertFile string
|
||||||
|
HttpKeyFile string
|
||||||
|
RecoverPanic bool
|
||||||
|
AutoRender bool
|
||||||
|
PprofOn bool
|
||||||
|
ViewsPath string
|
||||||
|
RunMode string //"dev" or "prod"
|
||||||
|
AppConfig config.ConfigContainer
|
||||||
|
//related to session
|
||||||
|
GlobalSessions *session.Manager //GlobalSessions
|
||||||
|
SessionOn bool // whether auto start session,default is false
|
||||||
|
SessionProvider string // default session provider memory mysql redis
|
||||||
|
SessionName string // sessionName cookie's name
|
||||||
|
SessionGCMaxLifetime int64 // session's gc maxlifetime
|
||||||
|
SessionSavePath string // session savepath if use mysql/redis/file this set to the connectinfo
|
||||||
|
UseFcgi bool
|
||||||
|
MaxMemory int64
|
||||||
|
EnableGzip bool // enable gzip
|
||||||
|
DirectoryIndex bool //enable DirectoryIndex default is false
|
||||||
|
EnableHotUpdate bool //enable HotUpdate default is false
|
||||||
|
HttpServerTimeOut int64 //set httpserver timeout
|
||||||
|
ErrorsShow bool //set weather show errors
|
||||||
|
XSRFKEY string //set XSRF
|
||||||
|
EnableXSRF bool
|
||||||
|
XSRFExpire int
|
||||||
|
CopyRequestBody bool //When in raw application, You want to the reqeustbody
|
||||||
|
TemplateLeft string
|
||||||
|
TemplateRight string
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Config represents the configuration.
|
func init() {
|
||||||
type Config struct {
|
os.Chdir(path.Dir(os.Args[0]))
|
||||||
filename string
|
BeeApp = NewApp()
|
||||||
comment map[int][]string // id: []{comment, key...}; id 1 is for main comment.
|
AppPath, _ = os.Getwd()
|
||||||
data map[string]string // key: value
|
StaticDir = make(map[string]string)
|
||||||
offset map[string]int64 // key: offset; for editing.
|
TemplateCache = make(map[string]*template.Template)
|
||||||
sync.RWMutex
|
HttpAddr = ""
|
||||||
}
|
HttpPort = 8080
|
||||||
|
AppName = "beego"
|
||||||
// ParseFile creates a new Config and parses the file configuration from the
|
RunMode = "dev" //default runmod
|
||||||
// named file.
|
AutoRender = true
|
||||||
func LoadConfig(name string) (*Config, error) {
|
RecoverPanic = true
|
||||||
file, err := os.Open(name)
|
PprofOn = false
|
||||||
if err != nil {
|
ViewsPath = "views"
|
||||||
return nil, err
|
SessionOn = false
|
||||||
}
|
SessionProvider = "memory"
|
||||||
|
SessionName = "beegosessionID"
|
||||||
cfg := &Config{
|
SessionGCMaxLifetime = 3600
|
||||||
file.Name(),
|
SessionSavePath = ""
|
||||||
make(map[int][]string),
|
UseFcgi = false
|
||||||
make(map[string]string),
|
MaxMemory = 1 << 26 //64MB
|
||||||
make(map[string]int64),
|
EnableGzip = false
|
||||||
sync.RWMutex{},
|
StaticDir["/static"] = "static"
|
||||||
}
|
AppConfigPath = path.Join(AppPath, "conf", "app.conf")
|
||||||
cfg.Lock()
|
HttpServerTimeOut = 0
|
||||||
defer cfg.Unlock()
|
ErrorsShow = true
|
||||||
defer file.Close()
|
XSRFKEY = "beegoxsrf"
|
||||||
|
XSRFExpire = 60
|
||||||
var comment bytes.Buffer
|
TemplateLeft = "{{"
|
||||||
buf := bufio.NewReader(file)
|
TemplateRight = "}}"
|
||||||
|
ParseConfig()
|
||||||
for nComment, off := 0, int64(1); ; {
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
line, _, err := buf.ReadLine()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if bytes.Equal(line, bEmpty) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
off += int64(len(line))
|
|
||||||
|
|
||||||
if bytes.HasPrefix(line, bComment) {
|
|
||||||
line = bytes.TrimLeft(line, "#")
|
|
||||||
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
|
|
||||||
comment.Write(line)
|
|
||||||
comment.WriteByte('\n')
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if comment.Len() != 0 {
|
|
||||||
cfg.comment[nComment] = []string{comment.String()}
|
|
||||||
comment.Reset()
|
|
||||||
nComment++
|
|
||||||
}
|
|
||||||
|
|
||||||
val := bytes.SplitN(line, bEqual, 2)
|
|
||||||
if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) {
|
|
||||||
val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`)
|
|
||||||
}
|
|
||||||
|
|
||||||
key := strings.TrimSpace(string(val[0]))
|
|
||||||
cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key)
|
|
||||||
cfg.data[key] = strings.TrimSpace(string(val[1]))
|
|
||||||
cfg.offset[key] = off
|
|
||||||
}
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool returns the boolean value for a given key.
|
|
||||||
func (c *Config) Bool(key string) (bool, error) {
|
|
||||||
return strconv.ParseBool(c.data[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int returns the integer value for a given key.
|
|
||||||
func (c *Config) Int(key string) (int, error) {
|
|
||||||
return strconv.Atoi(c.data[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Int64(key string) (int64, error) {
|
|
||||||
return strconv.ParseInt(c.data[key], 10, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float returns the float value for a given key.
|
|
||||||
func (c *Config) Float(key string) (float64, error) {
|
|
||||||
return strconv.ParseFloat(c.data[key], 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string value for a given key.
|
|
||||||
func (c *Config) String(key string) string {
|
|
||||||
return c.data[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteValue writes a new value for key.
|
|
||||||
func (c *Config) SetValue(key, value string) error {
|
|
||||||
c.Lock()
|
|
||||||
defer c.Unlock()
|
|
||||||
|
|
||||||
if _, found := c.data[key]; !found {
|
|
||||||
return errors.New("key not found: " + key)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.data[key] = value
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseConfig() (err error) {
|
func ParseConfig() (err error) {
|
||||||
AppConfig, err = LoadConfig(AppConfigPath)
|
AppConfig, err := config.NewConfig("ini", AppConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@ -204,6 +164,15 @@ func ParseConfig() (err error) {
|
|||||||
if tplright := AppConfig.String("templateright"); tplright != "" {
|
if tplright := AppConfig.String("templateright"); tplright != "" {
|
||||||
TemplateRight = tplright
|
TemplateRight = tplright
|
||||||
}
|
}
|
||||||
|
if httptls, err := AppConfig.Bool("HttpTLS"); err == nil {
|
||||||
|
HttpTLS = httptls
|
||||||
|
}
|
||||||
|
if certfile := AppConfig.String("HttpCertFile"); certfile != "" {
|
||||||
|
HttpCertFile = certfile
|
||||||
|
}
|
||||||
|
if keyfile := AppConfig.String("HttpKeyFile"); keyfile != "" {
|
||||||
|
HttpKeyFile = keyfile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,11 @@ func (ctx *Context) Redirect(status int, localurl string) {
|
|||||||
ctx.Output.SetStatus(status)
|
ctx.Output.SetStatus(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *Context) Abort(status int, body string) {
|
||||||
|
ctx.Output.SetStatus(status)
|
||||||
|
ctx.Output.Body([]byte(body))
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *Context) WriteString(content string) {
|
func (ctx *Context) WriteString(content string) {
|
||||||
ctx.Output.Body([]byte(content))
|
ctx.Output.Body([]byte(content))
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type BeegoOutput struct {
|
type BeegoOutput struct {
|
||||||
context *Context
|
Context *Context
|
||||||
Status int
|
Status int
|
||||||
EnableGzip bool
|
EnableGzip bool
|
||||||
res http.ResponseWriter
|
res http.ResponseWriter
|
||||||
@ -35,8 +35,8 @@ func (output *BeegoOutput) Header(key, val string) {
|
|||||||
|
|
||||||
func (output *BeegoOutput) Body(content []byte) {
|
func (output *BeegoOutput) Body(content []byte) {
|
||||||
output_writer := output.res.(io.Writer)
|
output_writer := output.res.(io.Writer)
|
||||||
if output.EnableGzip == true && output.context.Input.Header("Accept-Encoding") != "" {
|
if output.EnableGzip == true && output.Context.Input.Header("Accept-Encoding") != "" {
|
||||||
splitted := strings.SplitN(output.context.Input.Header("Accept-Encoding"), ",", -1)
|
splitted := strings.SplitN(output.Context.Input.Header("Accept-Encoding"), ",", -1)
|
||||||
encodings := make([]string, len(splitted))
|
encodings := make([]string, len(splitted))
|
||||||
|
|
||||||
for i, val := range splitted {
|
for i, val := range splitted {
|
||||||
@ -120,23 +120,40 @@ func sanitizeValue(v string) string {
|
|||||||
return cookieValueSanitizer.Replace(v)
|
return cookieValueSanitizer.Replace(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (output *BeegoOutput) Json(data string) error {
|
func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) error {
|
||||||
output.Header("Content-Type", "application/json;charset=UTF-8")
|
output.Header("Content-Type", "application/json;charset=UTF-8")
|
||||||
content, err := json.Marshal(data)
|
var content []byte
|
||||||
|
var err error
|
||||||
|
if hasIndent {
|
||||||
|
content, err = json.MarshalIndent(data, "", " ")
|
||||||
|
} else {
|
||||||
|
content, err = json.Marshal(data)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if coding {
|
||||||
|
content = []byte(stringsToJson(string(content)))
|
||||||
|
}
|
||||||
output.Body(content)
|
output.Body(content)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (output *BeegoOutput) Jsonp(data string) error {
|
func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error {
|
||||||
output.Header("Content-Type", "application/javascript;charset=UTF-8")
|
output.Header("Content-Type", "application/javascript;charset=UTF-8")
|
||||||
content, err := json.Marshal(data)
|
var content []byte
|
||||||
|
var err error
|
||||||
|
if hasIndent {
|
||||||
|
content, err = json.MarshalIndent(data, "", " ")
|
||||||
|
} else {
|
||||||
|
content, err = json.Marshal(data)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
callback := output.context.Input.Query("callback")
|
callback := output.Context.Input.Query("callback")
|
||||||
if callback == "" {
|
if callback == "" {
|
||||||
return errors.New(`"callback" parameter required`)
|
return errors.New(`"callback" parameter required`)
|
||||||
}
|
}
|
||||||
@ -148,10 +165,17 @@ func (output *BeegoOutput) Jsonp(data string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (output *BeegoOutput) Xml(data string) error {
|
func (output *BeegoOutput) Xml(data string, hasIndent bool) error {
|
||||||
output.Header("Content-Type", "application/xml;charset=UTF-8")
|
output.Header("Content-Type", "application/xml;charset=UTF-8")
|
||||||
content, err := xml.Marshal(data)
|
var content []byte
|
||||||
|
var err error
|
||||||
|
if hasIndent {
|
||||||
|
content, err = xml.MarshalIndent(data, "", " ")
|
||||||
|
} else {
|
||||||
|
content, err = xml.Marshal(data)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
output.Body(content)
|
output.Body(content)
|
||||||
@ -166,7 +190,7 @@ func (output *BeegoOutput) Download(file string) {
|
|||||||
output.Header("Expires", "0")
|
output.Header("Expires", "0")
|
||||||
output.Header("Cache-Control", "must-revalidate")
|
output.Header("Cache-Control", "must-revalidate")
|
||||||
output.Header("Pragma", "public")
|
output.Header("Pragma", "public")
|
||||||
http.ServeFile(output.res, output.context.Request, file)
|
http.ServeFile(output.res, output.Context.Request, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (output *BeegoOutput) ContentType(ext string) {
|
func (output *BeegoOutput) ContentType(ext string) {
|
||||||
@ -219,3 +243,17 @@ func (output *BeegoOutput) IsClientError(status int) bool {
|
|||||||
func (output *BeegoOutput) IsServerError(status int) bool {
|
func (output *BeegoOutput) IsServerError(status int) bool {
|
||||||
return output.Status >= 500 && output.Status < 600
|
return output.Status >= 500 && output.Status < 600
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringsToJson(str string) string {
|
||||||
|
rs := []rune(str)
|
||||||
|
jsons := ""
|
||||||
|
for _, r := range rs {
|
||||||
|
rint := int(r)
|
||||||
|
if rint < 128 {
|
||||||
|
jsons += string(r)
|
||||||
|
} else {
|
||||||
|
jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsons
|
||||||
|
}
|
||||||
|
112
controller.go
112
controller.go
@ -2,15 +2,12 @@ package beego
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/flate"
|
|
||||||
"compress/gzip"
|
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
@ -26,7 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
Ctx *Context
|
Ctx *context.Context
|
||||||
Data map[interface{}]interface{}
|
Data map[interface{}]interface{}
|
||||||
ChildName string
|
ChildName string
|
||||||
TplNames string
|
TplNames string
|
||||||
@ -39,7 +36,7 @@ type Controller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ControllerInterface interface {
|
type ControllerInterface interface {
|
||||||
Init(ct *Context, cn string)
|
Init(ct *Context, childName string)
|
||||||
Prepare()
|
Prepare()
|
||||||
Get()
|
Get()
|
||||||
Post()
|
Post()
|
||||||
@ -52,11 +49,11 @@ type ControllerInterface interface {
|
|||||||
Render() error
|
Render() error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) Init(ctx *Context, cn string) {
|
func (c *Controller) Init(ctx *context.Context, childName string) {
|
||||||
c.Data = make(map[interface{}]interface{})
|
c.Data = make(map[interface{}]interface{})
|
||||||
c.Layout = ""
|
c.Layout = ""
|
||||||
c.TplNames = ""
|
c.TplNames = ""
|
||||||
c.ChildName = cn
|
c.ChildName = childName
|
||||||
c.Ctx = ctx
|
c.Ctx = ctx
|
||||||
c.TplExt = "tpl"
|
c.TplExt = "tpl"
|
||||||
}
|
}
|
||||||
@ -109,8 +106,8 @@ func (c *Controller) Render() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
|
c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
c.writeToWriter(rb)
|
c.Ctx.Output.Body(rb)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -172,41 +169,6 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
|||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) writeToWriter(rb []byte) {
|
|
||||||
output_writer := c.Ctx.ResponseWriter.(io.Writer)
|
|
||||||
if EnableGzip == true && c.Ctx.Request.Header.Get("Accept-Encoding") != "" {
|
|
||||||
splitted := strings.SplitN(c.Ctx.Request.Header.Get("Accept-Encoding"), ",", -1)
|
|
||||||
encodings := make([]string, len(splitted))
|
|
||||||
|
|
||||||
for i, val := range splitted {
|
|
||||||
encodings[i] = strings.TrimSpace(val)
|
|
||||||
}
|
|
||||||
for _, val := range encodings {
|
|
||||||
if val == "gzip" {
|
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Encoding", "gzip")
|
|
||||||
output_writer, _ = gzip.NewWriterLevel(c.Ctx.ResponseWriter, gzip.BestSpeed)
|
|
||||||
|
|
||||||
break
|
|
||||||
} else if val == "deflate" {
|
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Encoding", "deflate")
|
|
||||||
output_writer, _ = flate.NewWriter(c.Ctx.ResponseWriter, flate.BestSpeed)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.Ctx.SetHeader("Content-Length", strconv.Itoa(len(rb)), true)
|
|
||||||
}
|
|
||||||
output_writer.Write(rb)
|
|
||||||
switch output_writer.(type) {
|
|
||||||
case *gzip.Writer:
|
|
||||||
output_writer.(*gzip.Writer).Close()
|
|
||||||
case *flate.Writer:
|
|
||||||
output_writer.(*flate.Writer).Close()
|
|
||||||
case io.WriteCloser:
|
|
||||||
output_writer.(io.WriteCloser).Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -216,63 +178,37 @@ func (c *Controller) Abort(code string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeJson(encoding ...bool) {
|
func (c *Controller) ServeJson(encoding ...bool) {
|
||||||
var content []byte
|
var hasIndent bool
|
||||||
var err error
|
var hasencoding bool
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
content, err = json.Marshal(c.Data["json"])
|
hasIndent = false
|
||||||
} else {
|
} else {
|
||||||
content, err = json.MarshalIndent(c.Data["json"], "", " ")
|
hasIndent = true
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
|
||||||
if len(encoding) > 0 && encoding[0] == true {
|
if len(encoding) > 0 && encoding[0] == true {
|
||||||
content = []byte(stringsToJson(string(content)))
|
hasencoding = true
|
||||||
}
|
}
|
||||||
c.writeToWriter(content)
|
c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeJsonp() {
|
func (c *Controller) ServeJsonp() {
|
||||||
var content []byte
|
var hasIndent bool
|
||||||
var err error
|
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
content, err = json.Marshal(c.Data["jsonp"])
|
hasIndent = false
|
||||||
} else {
|
} else {
|
||||||
content, err = json.MarshalIndent(c.Data["jsonp"], "", " ")
|
hasIndent = true
|
||||||
}
|
}
|
||||||
if err != nil {
|
c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent)
|
||||||
http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback := c.Ctx.Request.Form.Get("callback")
|
|
||||||
if callback == "" {
|
|
||||||
http.Error(c.Ctx.ResponseWriter, `"callback" parameter required`, http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback_content := bytes.NewBufferString(callback)
|
|
||||||
callback_content.WriteString("(")
|
|
||||||
callback_content.Write(content)
|
|
||||||
callback_content.WriteString(");\r\n")
|
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/javascript;charset=UTF-8")
|
|
||||||
c.writeToWriter(callback_content.Bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ServeXml() {
|
func (c *Controller) ServeXml() {
|
||||||
var content []byte
|
var hasIndent bool
|
||||||
var err error
|
|
||||||
if RunMode == "prod" {
|
if RunMode == "prod" {
|
||||||
content, err = xml.Marshal(c.Data["xml"])
|
hasIndent = false
|
||||||
} else {
|
} else {
|
||||||
content, err = xml.MarshalIndent(c.Data["xml"], "", " ")
|
hasIndent = true
|
||||||
}
|
}
|
||||||
if err != nil {
|
c.Ctx.Output.Xml(c.Data["xml"], hasIndent)
|
||||||
http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/xml;charset=UTF-8")
|
|
||||||
c.writeToWriter(content)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) Input() url.Values {
|
func (c *Controller) Input() url.Values {
|
||||||
@ -313,6 +249,10 @@ func (c *Controller) GetBool(key string) (bool, error) {
|
|||||||
return strconv.ParseBool(c.Input().Get(key))
|
return strconv.ParseBool(c.Input().Get(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) GetFloat(key string) (float64, error) {
|
||||||
|
return strconv.ParseFloat(c.Input().Get(key), 64)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
||||||
return c.Ctx.Request.FormFile(key)
|
return c.Ctx.Request.FormFile(key)
|
||||||
}
|
}
|
||||||
@ -365,7 +305,7 @@ func (c *Controller) DestroySession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) IsAjax() bool {
|
func (c *Controller) IsAjax() bool {
|
||||||
return (c.Ctx.Request.Header.Get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest")
|
return c.Ctx.Input.IsAjax()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) XsrfToken() string {
|
func (c *Controller) XsrfToken() string {
|
||||||
|
31
filter.go
Normal file
31
filter.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package beego
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FilterRouter struct {
|
||||||
|
pattern string
|
||||||
|
regex *regexp.Regexp
|
||||||
|
filterFunc FilterFunc
|
||||||
|
hasregex bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *FilterRouter) ValidRouter(router string) bool {
|
||||||
|
if mr.pattern == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if router == mr.pattern {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if mr.hasregex {
|
||||||
|
if mr.regex.MatchString(router) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
matches := mr.regex.FindStringSubmatch(router)
|
||||||
|
if len(matches[0]) == len(router) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
280
middleware/error.go
Normal file
280
middleware/error.go
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tpl = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>beego application error</title>
|
||||||
|
<style>
|
||||||
|
html, body, body * {padding: 0; margin: 0;}
|
||||||
|
#header {background:#ffd; border-bottom:solid 2px #A31515; padding: 20px 10px;}
|
||||||
|
#header h2{ }
|
||||||
|
#footer {border-top:solid 1px #aaa; padding: 5px 10px; font-size: 12px; color:green;}
|
||||||
|
#content {padding: 5px;}
|
||||||
|
#content .stack b{ font-size: 13px; color: red;}
|
||||||
|
#content .stack pre{padding-left: 10px;}
|
||||||
|
table {}
|
||||||
|
td.t {text-align: right; padding-right: 5px; color: #888;}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="header">
|
||||||
|
<h2>{{.AppError}}</h2>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="t">Request Method: </td><td>{{.RequestMethod}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="t">Request URL: </td><td>{{.RequestURL}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="t">RemoteAddr: </td><td>{{.RemoteAddr }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="stack">
|
||||||
|
<b>Stack</b>
|
||||||
|
<pre>{{.Stack}}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<p>beego {{ .BeegoVersion }} (beego framework)</p>
|
||||||
|
<p>golang version: {{.GoVersion}}</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
||||||
|
func ShowErr(err interface{}, rw http.ResponseWriter, r *http.Request, Stack string) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(tpl)
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["AppError"] = AppName + ":" + fmt.Sprint(err)
|
||||||
|
data["RequestMethod"] = r.Method
|
||||||
|
data["RequestURL"] = r.RequestURI
|
||||||
|
data["RemoteAddr"] = r.RemoteAddr
|
||||||
|
data["Stack"] = Stack
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
data["GoVersion"] = runtime.Version()
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errtpl = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<style type="text/css">
|
||||||
|
* {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color:#EFEFEF;
|
||||||
|
font: .9em "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper{
|
||||||
|
width:600px;
|
||||||
|
margin:40px auto 0;
|
||||||
|
text-align:center;
|
||||||
|
-moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||||
|
-webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||||
|
box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper h1{
|
||||||
|
color:#FFF;
|
||||||
|
text-align:center;
|
||||||
|
margin-bottom:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper a{
|
||||||
|
display:block;
|
||||||
|
font-size:.9em;
|
||||||
|
padding-top:20px;
|
||||||
|
color:#FFF;
|
||||||
|
text-decoration:none;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width:600px;
|
||||||
|
padding-bottom:15px;
|
||||||
|
background-color:#FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navtop{
|
||||||
|
height:40px;
|
||||||
|
background-color:#24B2EB;
|
||||||
|
padding:13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding:10px 10px 25px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin:;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button{
|
||||||
|
color:white;
|
||||||
|
padding:15px 20px;
|
||||||
|
text-shadow:1px 1px 0 #00A5FF;
|
||||||
|
font-weight:bold;
|
||||||
|
text-align:center;
|
||||||
|
border:1px solid #24B2EB;
|
||||||
|
margin:0px 200px;
|
||||||
|
clear:both;
|
||||||
|
background-color: #24B2EB;
|
||||||
|
border-radius:100px;
|
||||||
|
-moz-border-radius:100px;
|
||||||
|
-webkit-border-radius:100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button:hover{
|
||||||
|
text-decoration:none;
|
||||||
|
background-color: #24B2EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="container">
|
||||||
|
<div class="navtop">
|
||||||
|
<h1>{{.Title}}</h1>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
{{.Content}}
|
||||||
|
<a href="/" title="Home" class="button">Go Home</a><br />
|
||||||
|
|
||||||
|
<br>power by beego {{.BeegoVersion}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
||||||
|
var ErrorMaps map[string]http.HandlerFunc
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ErrorMaps = make(map[string]http.HandlerFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
//404
|
||||||
|
func NotFound(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Page Not Found"
|
||||||
|
data["Content"] = template.HTML("<br>The Page You have requested flown the coop." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>The page has moved" +
|
||||||
|
"<br>The page no longer exists" +
|
||||||
|
"<br>You were looking for your puppy and got lost" +
|
||||||
|
"<br>You like 404 pages" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//401
|
||||||
|
func Unauthorized(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Unauthorized"
|
||||||
|
data["Content"] = template.HTML("<br>The Page You have requested can't authorized." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>Check the credentials that you supplied" +
|
||||||
|
"<br>Check the address for errors" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
rw.WriteHeader(http.StatusUnauthorized)
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//403
|
||||||
|
func Forbidden(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Forbidden"
|
||||||
|
data["Content"] = template.HTML("<br>The Page You have requested forbidden." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>Your address may be blocked" +
|
||||||
|
"<br>The site may be disabled" +
|
||||||
|
"<br>You need to log in" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
rw.WriteHeader(http.StatusForbidden)
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//503
|
||||||
|
func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Service Unavailable"
|
||||||
|
data["Content"] = template.HTML("<br>The Page You have requested unavailable." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br><br>The page is overloaded" +
|
||||||
|
"<br>Please try again later." +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
rw.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
//500
|
||||||
|
func InternalServerError(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Internal Server Error"
|
||||||
|
data["Content"] = template.HTML("<br>The Page You have requested has down now." +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>simply try again later" +
|
||||||
|
"<br>you should report the fault to the website administrator" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerErrorHander() {
|
||||||
|
if _, ok := ErrorMaps["404"]; !ok {
|
||||||
|
ErrorMaps["404"] = NotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["401"]; !ok {
|
||||||
|
ErrorMaps["401"] = Unauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["403"]; !ok {
|
||||||
|
ErrorMaps["403"] = Forbidden
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["503"]; !ok {
|
||||||
|
ErrorMaps["503"] = ServiceUnavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["500"]; !ok {
|
||||||
|
ErrorMaps["500"] = InternalServerError
|
||||||
|
}
|
||||||
|
}
|
1
middleware/i18n.go
Normal file
1
middleware/i18n.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package middleware
|
226
middleware/profile.go
Normal file
226
middleware/profile.go
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
|
"runtime/pprof"
|
||||||
|
"strconv"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var heapProfileCounter int32
|
||||||
|
var startTime = time.Now()
|
||||||
|
var pid int
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pid = os.Getpid()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartCPUProfile() {
|
||||||
|
f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
pprof.StartCPUProfile(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopCPUProfile() {
|
||||||
|
pprof.StopCPUProfile()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartBlockProfile(rate int) {
|
||||||
|
runtime.SetBlockProfileRate(rate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopBlockProfile() {
|
||||||
|
filename := "block-" + strconv.Itoa(pid) + ".pprof"
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
|
||||||
|
log.Fatalf(" can't write %s: %s", filename, err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetMemProfileRate(rate int) {
|
||||||
|
runtime.MemProfileRate = rate
|
||||||
|
}
|
||||||
|
|
||||||
|
func GC() {
|
||||||
|
runtime.GC()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DumpHeap() {
|
||||||
|
filename := "heap-" + strconv.Itoa(pid) + "-" + strconv.Itoa(int(atomic.AddInt32(&heapProfileCounter, 1))) + ".pprof"
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "testing: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = pprof.WriteHeapProfile(f); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", filename, err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
//func showSystemStat(interval time.Duration, count int) {
|
||||||
|
|
||||||
|
// usage1 := &syscall.Rusage{}
|
||||||
|
// var lastUtime int64
|
||||||
|
// var lastStime int64
|
||||||
|
|
||||||
|
// counter := 0
|
||||||
|
// for {
|
||||||
|
|
||||||
|
// //http://man7.org/linux/man-pages/man3/vtimes.3.html
|
||||||
|
// syscall.Getrusage(syscall.RUSAGE_SELF, usage1)
|
||||||
|
|
||||||
|
// utime := (usage1.Utime.Sec * 1000000000) + int64(usage1.Utime.Usec)
|
||||||
|
// stime := (usage1.Stime.Sec * 1000000000) + int64(usage1.Stime.Usec)
|
||||||
|
// userCPUUtil := float64(utime-lastUtime) * 100 / float64(interval)
|
||||||
|
// sysCPUUtil := float64(stime-lastStime) * 100 / float64(interval)
|
||||||
|
// memUtil := usage1.Maxrss * 1024
|
||||||
|
|
||||||
|
// lastUtime = utime
|
||||||
|
// lastStime = stime
|
||||||
|
|
||||||
|
// if counter > 0 {
|
||||||
|
// fmt.Printf("cpu: %3.2f%% us %3.2f%% sy, mem:%s \n", userCPUUtil, sysCPUUtil, toH(uint64(memUtil)))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// counter += 1
|
||||||
|
// if count >= 1 && count < counter {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// time.Sleep(interval)
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func ShowSystemStat(seconds int) {
|
||||||
|
// go func() {
|
||||||
|
// interval := time.Duration(seconds) * time.Second
|
||||||
|
// showSystemStat(interval, 0)
|
||||||
|
// }()
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func PrintSystemStats() {
|
||||||
|
// interval := time.Duration(1) * time.Second
|
||||||
|
// showSystemStat(interval, 1)
|
||||||
|
//}
|
||||||
|
|
||||||
|
func ShowGCStat() {
|
||||||
|
go func() {
|
||||||
|
var numGC int64
|
||||||
|
|
||||||
|
interval := time.Duration(100) * time.Millisecond
|
||||||
|
gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}
|
||||||
|
memStats := &runtime.MemStats{}
|
||||||
|
for {
|
||||||
|
debug.ReadGCStats(gcstats)
|
||||||
|
if gcstats.NumGC > numGC {
|
||||||
|
runtime.ReadMemStats(memStats)
|
||||||
|
|
||||||
|
printGC(memStats, gcstats)
|
||||||
|
numGC = gcstats.NumGC
|
||||||
|
}
|
||||||
|
time.Sleep(interval)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintGCSummary() {
|
||||||
|
memStats := &runtime.MemStats{}
|
||||||
|
runtime.ReadMemStats(memStats)
|
||||||
|
gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}
|
||||||
|
debug.ReadGCStats(gcstats)
|
||||||
|
|
||||||
|
printGC(memStats, gcstats)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) {
|
||||||
|
|
||||||
|
if gcstats.NumGC > 0 {
|
||||||
|
lastPause := gcstats.Pause[0]
|
||||||
|
elapsed := time.Now().Sub(startTime)
|
||||||
|
overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100
|
||||||
|
allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
|
||||||
|
|
||||||
|
fmt.Printf("NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n",
|
||||||
|
gcstats.NumGC,
|
||||||
|
toS(lastPause),
|
||||||
|
toS(avg(gcstats.Pause)),
|
||||||
|
overhead,
|
||||||
|
toH(memStats.Alloc),
|
||||||
|
toH(memStats.Sys),
|
||||||
|
toH(uint64(allocatedRate)),
|
||||||
|
toS(gcstats.PauseQuantiles[94]),
|
||||||
|
toS(gcstats.PauseQuantiles[98]),
|
||||||
|
toS(gcstats.PauseQuantiles[99]))
|
||||||
|
} else {
|
||||||
|
// while GC has disabled
|
||||||
|
elapsed := time.Now().Sub(startTime)
|
||||||
|
allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
|
||||||
|
|
||||||
|
fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n",
|
||||||
|
toH(memStats.Alloc),
|
||||||
|
toH(memStats.Sys),
|
||||||
|
toH(uint64(allocatedRate)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func avg(items []time.Duration) time.Duration {
|
||||||
|
var sum time.Duration
|
||||||
|
for _, item := range items {
|
||||||
|
sum += item
|
||||||
|
}
|
||||||
|
return time.Duration(int64(sum) / int64(len(items)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// human readable format
|
||||||
|
func toH(bytes uint64) string {
|
||||||
|
switch {
|
||||||
|
case bytes < 1024:
|
||||||
|
return fmt.Sprintf("%dB", bytes)
|
||||||
|
case bytes < 1024*1024:
|
||||||
|
return fmt.Sprintf("%.2fK", float64(bytes)/1024)
|
||||||
|
case bytes < 1024*1024*1024:
|
||||||
|
return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// short string format
|
||||||
|
func toS(d time.Duration) string {
|
||||||
|
|
||||||
|
u := uint64(d)
|
||||||
|
if u < uint64(time.Second) {
|
||||||
|
switch {
|
||||||
|
case u == 0:
|
||||||
|
return "0"
|
||||||
|
case u < uint64(time.Microsecond):
|
||||||
|
return fmt.Sprintf("%.2fns", float64(u))
|
||||||
|
case u < uint64(time.Millisecond):
|
||||||
|
return fmt.Sprintf("%.2fus", float64(u)/1000)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%.2fms", float64(u)/1000/1000)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch {
|
||||||
|
case u < uint64(time.Minute):
|
||||||
|
return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000)
|
||||||
|
case u < uint64(time.Hour):
|
||||||
|
return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
middleware/session.go
Normal file
14
middleware/session.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
GlobalSessions *session.Manager
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartSession(provideName, cookieName string, maxlifetime int64, savePath string) {
|
||||||
|
GlobalSessions, _ = session.NewManager(provideName, cookieName, maxlifetime, savePath)
|
||||||
|
go GlobalSessions.GC()
|
||||||
|
}
|
25
pprof.go
25
pprof.go
@ -1,25 +0,0 @@
|
|||||||
package beego
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/pprof"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProfController struct {
|
|
||||||
Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *ProfController) Get() {
|
|
||||||
switch this.Ctx.Params[":pp"] {
|
|
||||||
default:
|
|
||||||
pprof.Index(this.Ctx.ResponseWriter, this.Ctx.Request)
|
|
||||||
case "":
|
|
||||||
pprof.Index(this.Ctx.ResponseWriter, this.Ctx.Request)
|
|
||||||
case "cmdline":
|
|
||||||
pprof.Cmdline(this.Ctx.ResponseWriter, this.Ctx.Request)
|
|
||||||
case "profile":
|
|
||||||
pprof.Profile(this.Ctx.ResponseWriter, this.Ctx.Request)
|
|
||||||
case "symbol":
|
|
||||||
pprof.Symbol(this.Ctx.ResponseWriter, this.Ctx.Request)
|
|
||||||
}
|
|
||||||
this.Ctx.ResponseWriter.WriteHeader(200)
|
|
||||||
}
|
|
252
router.go
252
router.go
@ -1,9 +1,8 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
beecontext "github.com/astaxie/beego/context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -25,22 +24,11 @@ type controllerInfo struct {
|
|||||||
hasMethod bool
|
hasMethod bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type userHandler struct {
|
|
||||||
pattern string
|
|
||||||
regex *regexp.Regexp
|
|
||||||
params map[int]string
|
|
||||||
h http.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
type ControllerRegistor struct {
|
type ControllerRegistor struct {
|
||||||
routers []*controllerInfo
|
routers []*controllerInfo
|
||||||
fixrouters []*controllerInfo
|
fixrouters []*controllerInfo
|
||||||
enableFilter bool
|
enableFilter bool
|
||||||
filters []http.HandlerFunc
|
filters map[string][]*FilterRouter
|
||||||
enableAfter bool
|
|
||||||
afterFilters []http.HandlerFunc
|
|
||||||
enableUser bool
|
|
||||||
userHandlers map[string]*userHandler
|
|
||||||
enableAuto bool
|
enableAuto bool
|
||||||
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
|
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
|
||||||
}
|
}
|
||||||
@ -48,8 +36,8 @@ type ControllerRegistor struct {
|
|||||||
func NewControllerRegistor() *ControllerRegistor {
|
func NewControllerRegistor() *ControllerRegistor {
|
||||||
return &ControllerRegistor{
|
return &ControllerRegistor{
|
||||||
routers: make([]*controllerInfo, 0),
|
routers: make([]*controllerInfo, 0),
|
||||||
userHandlers: make(map[string]*userHandler),
|
|
||||||
autoRouter: make(map[string]map[string]reflect.Type),
|
autoRouter: make(map[string]map[string]reflect.Type),
|
||||||
|
filters: make(map[string][]*FilterRouter),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,35 +170,39 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) {
|
// Filter adds the middleware filter.
|
||||||
p.enableUser = true
|
func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) {
|
||||||
parts := strings.Split(pattern, "/")
|
p.enableFilter = true
|
||||||
|
mr := new(FilterRouter)
|
||||||
|
mr.filterFunc = filter
|
||||||
|
|
||||||
|
parts := strings.Split(pattern, "/")
|
||||||
j := 0
|
j := 0
|
||||||
params := make(map[int]string)
|
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
if strings.HasPrefix(part, ":") {
|
if strings.HasPrefix(part, ":") {
|
||||||
expr := "([^/]+)"
|
expr := "(.+)"
|
||||||
//a user may choose to override the defult expression
|
//a user may choose to override the defult expression
|
||||||
// similar to expressjs: ‘/user/:id([0-9]+)’
|
// similar to expressjs: ‘/user/:id([0-9]+)’
|
||||||
if index := strings.Index(part, "("); index != -1 {
|
if index := strings.Index(part, "("); index != -1 {
|
||||||
expr = part[index:]
|
expr = part[index:]
|
||||||
part = part[:index]
|
part = part[:index]
|
||||||
|
//match /user/:id:int ([0-9]+)
|
||||||
|
//match /post/:username:string ([\w]+)
|
||||||
|
} else if lindex := strings.LastIndex(part, ":"); lindex != 0 {
|
||||||
|
switch part[lindex:] {
|
||||||
|
case ":int":
|
||||||
|
expr = "([0-9]+)"
|
||||||
|
part = part[:lindex]
|
||||||
|
case ":string":
|
||||||
|
expr = `([\w]+)`
|
||||||
|
part = part[:lindex]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
params[j] = part
|
|
||||||
parts[i] = expr
|
parts[i] = expr
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if j == 0 {
|
if j != 0 {
|
||||||
//now create the Route
|
|
||||||
uh := &userHandler{}
|
|
||||||
uh.pattern = pattern
|
|
||||||
uh.h = c
|
|
||||||
p.userHandlers[pattern] = uh
|
|
||||||
} else { // add regexp routers
|
|
||||||
//recreate the url pattern, with parameters replaced
|
|
||||||
//by regular expressions. then compile the regex
|
|
||||||
pattern = strings.Join(parts, "/")
|
pattern = strings.Join(parts, "/")
|
||||||
regex, regexErr := regexp.Compile(pattern)
|
regex, regexErr := regexp.Compile(pattern)
|
||||||
if regexErr != nil {
|
if regexErr != nil {
|
||||||
@ -218,73 +210,11 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) {
|
|||||||
panic(regexErr)
|
panic(regexErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
mr.regex = regex
|
||||||
//now create the Route
|
mr.hasregex = true
|
||||||
uh := &userHandler{}
|
|
||||||
uh.regex = regex
|
|
||||||
uh.params = params
|
|
||||||
uh.pattern = pattern
|
|
||||||
uh.h = c
|
|
||||||
p.userHandlers[pattern] = uh
|
|
||||||
}
|
}
|
||||||
}
|
mr.pattern = pattern
|
||||||
|
p.filters[action] = append(p.filters[action], mr)
|
||||||
// Filter adds the middleware filter.
|
|
||||||
func (p *ControllerRegistor) Filter(filter http.HandlerFunc) {
|
|
||||||
p.enableFilter = true
|
|
||||||
p.filters = append(p.filters, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterParam adds the middleware filter if the REST URL parameter exists.
|
|
||||||
func (p *ControllerRegistor) FilterParam(param string, filter http.HandlerFunc) {
|
|
||||||
if !strings.HasPrefix(param, ":") {
|
|
||||||
param = ":" + param
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Filter(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
p := r.URL.Query().Get(param)
|
|
||||||
if len(p) > 0 {
|
|
||||||
filter(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterPrefixPath adds the middleware filter if the prefix path exists.
|
|
||||||
func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFunc) {
|
|
||||||
p.Filter(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if strings.HasPrefix(r.URL.Path, path) {
|
|
||||||
filter(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter adds the middleware after filter.
|
|
||||||
func (p *ControllerRegistor) FilterAfter(filter http.HandlerFunc) {
|
|
||||||
p.enableAfter = true
|
|
||||||
p.afterFilters = append(p.afterFilters, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterParam adds the middleware filter if the REST URL parameter exists.
|
|
||||||
func (p *ControllerRegistor) FilterParamAfter(param string, filter http.HandlerFunc) {
|
|
||||||
if !strings.HasPrefix(param, ":") {
|
|
||||||
param = ":" + param
|
|
||||||
}
|
|
||||||
|
|
||||||
p.FilterAfter(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
p := r.URL.Query().Get(param)
|
|
||||||
if len(p) > 0 {
|
|
||||||
filter(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilterPrefixPath adds the middleware filter if the prefix path exists.
|
|
||||||
func (p *ControllerRegistor) FilterPrefixPathAfter(path string, filter http.HandlerFunc) {
|
|
||||||
p.FilterAfter(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if strings.HasPrefix(r.URL.Path, path) {
|
|
||||||
filter(w, r)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoRoute
|
// AutoRoute
|
||||||
@ -320,13 +250,30 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
w := &responseWriter{writer: rw}
|
w := &responseWriter{writer: rw}
|
||||||
|
|
||||||
w.Header().Set("Server", "beegoServer")
|
w.Header().Set("Server", "beegoServer")
|
||||||
|
context := &beecontext.Context{
|
||||||
|
ResponseWriter: w,
|
||||||
|
Request: r,
|
||||||
|
Input: beecontext.NewInput(r),
|
||||||
|
Output: beecontext.NewOutput(w),
|
||||||
|
}
|
||||||
|
context.Output.Context = context
|
||||||
var runrouter *controllerInfo
|
var runrouter *controllerInfo
|
||||||
var findrouter bool
|
var findrouter bool
|
||||||
|
|
||||||
params := make(map[string]string)
|
params := make(map[string]string)
|
||||||
|
|
||||||
|
context.Input.Param = params
|
||||||
|
if p.enableFilter {
|
||||||
|
if l, ok := p.filters["BeforRouter"]; ok {
|
||||||
|
for _, filterR := range l {
|
||||||
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//static file server
|
//static file server
|
||||||
for prefix, staticDir := range StaticDir {
|
for prefix, staticDir := range StaticDir {
|
||||||
if r.URL.Path == "/favicon.ico" {
|
if r.URL.Path == "/favicon.ico" {
|
||||||
@ -359,62 +306,23 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.enableFilter {
|
||||||
|
if l, ok := p.filters["AfterStatic"]; ok {
|
||||||
|
for _, filterR := range l {
|
||||||
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
requestPath := r.URL.Path
|
requestPath := r.URL.Path
|
||||||
|
|
||||||
var requestbody []byte
|
|
||||||
|
|
||||||
if CopyRequestBody {
|
if CopyRequestBody {
|
||||||
requestbody, _ = ioutil.ReadAll(r.Body)
|
context.Input.Body()
|
||||||
|
|
||||||
r.Body.Close()
|
|
||||||
|
|
||||||
bf := bytes.NewBuffer(requestbody)
|
|
||||||
|
|
||||||
r.Body = ioutil.NopCloser(bf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ParseMultipartForm(MaxMemory)
|
r.ParseMultipartForm(MaxMemory)
|
||||||
|
|
||||||
//user defined Handler
|
|
||||||
if p.enableUser {
|
|
||||||
for pattern, c := range p.userHandlers {
|
|
||||||
if c.regex == nil && pattern == requestPath {
|
|
||||||
c.h.ServeHTTP(rw, r)
|
|
||||||
return
|
|
||||||
} else if c.regex == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if Route pattern matches url
|
|
||||||
if !c.regex.MatchString(requestPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//get submatches (params)
|
|
||||||
matches := c.regex.FindStringSubmatch(requestPath)
|
|
||||||
|
|
||||||
//double check that the Route matches the URL pattern.
|
|
||||||
if len(matches[0]) != len(requestPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.params) > 0 {
|
|
||||||
//add url parameters to the query param map
|
|
||||||
values := r.URL.Query()
|
|
||||||
for i, match := range matches[1:] {
|
|
||||||
values.Add(c.params[i], match)
|
|
||||||
r.Form.Add(c.params[i], match)
|
|
||||||
params[c.params[i]] = match
|
|
||||||
}
|
|
||||||
//reassemble query params and add to RawQuery
|
|
||||||
r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
|
|
||||||
//r.URL.RawQuery = url.Values(values).Encode()
|
|
||||||
}
|
|
||||||
c.h.ServeHTTP(rw, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//first find path from the fixrouters to Improve Performance
|
//first find path from the fixrouters to Improve Performance
|
||||||
for _, route := range p.fixrouters {
|
for _, route := range p.fixrouters {
|
||||||
n := len(requestPath)
|
n := len(requestPath)
|
||||||
@ -471,23 +379,21 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
if runrouter != nil {
|
if runrouter != nil {
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.enableFilter {
|
if p.enableFilter {
|
||||||
for _, filter := range p.filters {
|
if l, ok := p.filters["BeforExec"]; ok {
|
||||||
filter(w, r)
|
for _, filterR := range l {
|
||||||
if w.started {
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
return
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Invoke the request handler
|
//Invoke the request handler
|
||||||
vc := reflect.New(runrouter.controllerType)
|
vc := reflect.New(runrouter.controllerType)
|
||||||
|
|
||||||
//call the controller init function
|
//call the controller init function
|
||||||
init := vc.MethodByName("Init")
|
init := vc.MethodByName("Init")
|
||||||
in := make([]reflect.Value, 2)
|
in := make([]reflect.Value, 2)
|
||||||
ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody}
|
in[0] = reflect.ValueOf(context)
|
||||||
|
|
||||||
in[0] = reflect.ValueOf(ct)
|
|
||||||
in[1] = reflect.ValueOf(runrouter.controllerType.Name())
|
in[1] = reflect.ValueOf(runrouter.controllerType.Name())
|
||||||
init.Call(in)
|
init.Call(in)
|
||||||
//call prepare function
|
//call prepare function
|
||||||
@ -617,14 +523,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
method = vc.MethodByName("Finish")
|
method = vc.MethodByName("Finish")
|
||||||
method.Call(in)
|
method.Call(in)
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.enableAfter {
|
if p.enableFilter {
|
||||||
for _, filter := range p.afterFilters {
|
if l, ok := p.filters["AfterExec"]; ok {
|
||||||
filter(w, r)
|
for _, filterR := range l {
|
||||||
if w.started {
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
return
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -651,10 +559,11 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) {
|
if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) {
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.enableFilter {
|
if p.enableFilter {
|
||||||
for _, filter := range p.filters {
|
if l, ok := p.filters["BeforExec"]; ok {
|
||||||
filter(w, r)
|
for _, filterR := range l {
|
||||||
if w.started {
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
return
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -672,9 +581,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
//call the controller init function
|
//call the controller init function
|
||||||
init := vc.MethodByName("Init")
|
init := vc.MethodByName("Init")
|
||||||
in := make([]reflect.Value, 2)
|
in := make([]reflect.Value, 2)
|
||||||
ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody}
|
in[0] = reflect.ValueOf(context)
|
||||||
|
|
||||||
in[0] = reflect.ValueOf(ct)
|
|
||||||
in[1] = reflect.ValueOf(controllerType.Name())
|
in[1] = reflect.ValueOf(controllerType.Name())
|
||||||
init.Call(in)
|
init.Call(in)
|
||||||
//call prepare function
|
//call prepare function
|
||||||
@ -702,11 +609,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
method = vc.MethodByName("Finish")
|
method = vc.MethodByName("Finish")
|
||||||
method.Call(in)
|
method.Call(in)
|
||||||
//execute middleware filters
|
//execute middleware filters
|
||||||
if p.enableAfter {
|
if p.enableFilter {
|
||||||
for _, filter := range p.afterFilters {
|
if l, ok := p.filters["AfterExec"]; ok {
|
||||||
filter(w, r)
|
for _, filterR := range l {
|
||||||
if w.started {
|
if filterR.ValidRouter(r.URL.Path) {
|
||||||
return
|
filterR.filterFunc(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,6 +622,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
method.Call(in)
|
method.Call(in)
|
||||||
// set find
|
// set find
|
||||||
findrouter = true
|
findrouter = true
|
||||||
|
goto Last
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -721,6 +630,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Last:
|
||||||
//if no matches to url, throw a not found exception
|
//if no matches to url, throw a not found exception
|
||||||
if !findrouter {
|
if !findrouter {
|
||||||
if h, ok := ErrorMaps["404"]; ok {
|
if h, ok := ErrorMaps["404"]; ok {
|
||||||
|
Loading…
Reference in New Issue
Block a user