mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 09:30:56 +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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/session"
|
||||
"html/template"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
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 {
|
||||
BeeApp.Router(rootpath, c, mappingMethods...)
|
||||
return BeeApp
|
||||
@ -232,11 +24,6 @@ func AutoRouter(c ControllerInterface) *App {
|
||||
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 {
|
||||
ErrorMaps[err] = h
|
||||
return BeeApp
|
||||
@ -257,37 +44,18 @@ func DelStaticPath(url string) *App {
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
func Filter(filter http.HandlerFunc) *App {
|
||||
BeeApp.Filter(filter)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
func FilterParam(param string, filter http.HandlerFunc) *App {
|
||||
BeeApp.FilterParam(param, 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)
|
||||
//action has four values:
|
||||
//BeforRouter
|
||||
//AfterStatic
|
||||
//BeforExec
|
||||
//AfterExec
|
||||
func AddFilter(pattern, action string, filter FilterFunc) *App {
|
||||
BeeApp.Filter(pattern, action, filter)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
func Run() {
|
||||
//if AppConfigPath not In the conf/app.conf reParse config
|
||||
if AppConfigPath != path.Join(AppPath, "conf", "app.conf") {
|
||||
err := ParseConfig()
|
||||
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 {
|
||||
GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath)
|
||||
go GlobalSessions.GC()
|
||||
}
|
||||
|
||||
if AutoRender {
|
||||
err := BuildTemplate(ViewsPath)
|
||||
if err != nil {
|
||||
if RunMode == "dev" {
|
||||
Warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
registerErrorHander()
|
||||
BeeApp.Run()
|
||||
}
|
||||
|
199
config.go
199
config.go
@ -1,131 +1,91 @@
|
||||
package beego
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"github.com/astaxie/beego/config"
|
||||
"github.com/astaxie/beego/session"
|
||||
"html/template"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
var (
|
||||
bComment = []byte{'#'}
|
||||
bEmpty = []byte{}
|
||||
bEqual = []byte{'='}
|
||||
bDQuote = []byte{'"'}
|
||||
BeeApp *App
|
||||
AppName string
|
||||
AppPath string
|
||||
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.
|
||||
type Config struct {
|
||||
filename string
|
||||
comment map[int][]string // id: []{comment, key...}; id 1 is for main comment.
|
||||
data map[string]string // key: value
|
||||
offset map[string]int64 // key: offset; for editing.
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// ParseFile creates a new Config and parses the file configuration from the
|
||||
// named file.
|
||||
func LoadConfig(name string) (*Config, error) {
|
||||
file, err := os.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
file.Name(),
|
||||
make(map[int][]string),
|
||||
make(map[string]string),
|
||||
make(map[string]int64),
|
||||
sync.RWMutex{},
|
||||
}
|
||||
cfg.Lock()
|
||||
defer cfg.Unlock()
|
||||
defer file.Close()
|
||||
|
||||
var comment bytes.Buffer
|
||||
buf := bufio.NewReader(file)
|
||||
|
||||
for nComment, off := 0, int64(1); ; {
|
||||
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 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())
|
||||
}
|
||||
|
||||
func ParseConfig() (err error) {
|
||||
AppConfig, err = LoadConfig(AppConfigPath)
|
||||
AppConfig, err := config.NewConfig("ini", AppConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
@ -204,6 +164,15 @@ func ParseConfig() (err error) {
|
||||
if tplright := AppConfig.String("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
|
||||
}
|
||||
|
@ -16,6 +16,11 @@ func (ctx *Context) Redirect(status int, localurl string) {
|
||||
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) {
|
||||
ctx.Output.Body([]byte(content))
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
type BeegoOutput struct {
|
||||
context *Context
|
||||
Context *Context
|
||||
Status int
|
||||
EnableGzip bool
|
||||
res http.ResponseWriter
|
||||
@ -35,8 +35,8 @@ func (output *BeegoOutput) Header(key, val string) {
|
||||
|
||||
func (output *BeegoOutput) Body(content []byte) {
|
||||
output_writer := output.res.(io.Writer)
|
||||
if output.EnableGzip == true && output.context.Input.Header("Accept-Encoding") != "" {
|
||||
splitted := strings.SplitN(output.context.Input.Header("Accept-Encoding"), ",", -1)
|
||||
if output.EnableGzip == true && output.Context.Input.Header("Accept-Encoding") != "" {
|
||||
splitted := strings.SplitN(output.Context.Input.Header("Accept-Encoding"), ",", -1)
|
||||
encodings := make([]string, len(splitted))
|
||||
|
||||
for i, val := range splitted {
|
||||
@ -120,23 +120,40 @@ func sanitizeValue(v string) string {
|
||||
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")
|
||||
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 {
|
||||
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
if coding {
|
||||
content = []byte(stringsToJson(string(content)))
|
||||
}
|
||||
output.Body(content)
|
||||
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")
|
||||
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 {
|
||||
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
callback := output.context.Input.Query("callback")
|
||||
callback := output.Context.Input.Query("callback")
|
||||
if callback == "" {
|
||||
return errors.New(`"callback" parameter required`)
|
||||
}
|
||||
@ -148,10 +165,17 @@ func (output *BeegoOutput) Jsonp(data string) error {
|
||||
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")
|
||||
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 {
|
||||
http.Error(output.res, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
output.Body(content)
|
||||
@ -166,7 +190,7 @@ func (output *BeegoOutput) Download(file string) {
|
||||
output.Header("Expires", "0")
|
||||
output.Header("Cache-Control", "must-revalidate")
|
||||
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) {
|
||||
@ -219,3 +243,17 @@ func (output *BeegoOutput) IsClientError(status int) bool {
|
||||
func (output *BeegoOutput) IsServerError(status int) bool {
|
||||
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 (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/astaxie/beego/session"
|
||||
"html/template"
|
||||
"io"
|
||||
@ -26,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
Ctx *Context
|
||||
Ctx *context.Context
|
||||
Data map[interface{}]interface{}
|
||||
ChildName string
|
||||
TplNames string
|
||||
@ -39,7 +36,7 @@ type Controller struct {
|
||||
}
|
||||
|
||||
type ControllerInterface interface {
|
||||
Init(ct *Context, cn string)
|
||||
Init(ct *Context, childName string)
|
||||
Prepare()
|
||||
Get()
|
||||
Post()
|
||||
@ -52,11 +49,11 @@ type ControllerInterface interface {
|
||||
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.Layout = ""
|
||||
c.TplNames = ""
|
||||
c.ChildName = cn
|
||||
c.ChildName = childName
|
||||
c.Ctx = ctx
|
||||
c.TplExt = "tpl"
|
||||
}
|
||||
@ -109,8 +106,8 @@ func (c *Controller) Render() error {
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
c.writeToWriter(rb)
|
||||
c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
|
||||
c.Ctx.Output.Body(rb)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -172,41 +169,6 @@ func (c *Controller) RenderBytes() ([]byte, error) {
|
||||
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) {
|
||||
c.Ctx.Redirect(code, url)
|
||||
}
|
||||
@ -216,63 +178,37 @@ func (c *Controller) Abort(code string) {
|
||||
}
|
||||
|
||||
func (c *Controller) ServeJson(encoding ...bool) {
|
||||
var content []byte
|
||||
var err error
|
||||
var hasIndent bool
|
||||
var hasencoding bool
|
||||
if RunMode == "prod" {
|
||||
content, err = json.Marshal(c.Data["json"])
|
||||
hasIndent = false
|
||||
} 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 {
|
||||
content = []byte(stringsToJson(string(content)))
|
||||
hasencoding = true
|
||||
}
|
||||
c.writeToWriter(content)
|
||||
c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeJsonp() {
|
||||
var content []byte
|
||||
var err error
|
||||
var hasIndent bool
|
||||
if RunMode == "prod" {
|
||||
content, err = json.Marshal(c.Data["jsonp"])
|
||||
hasIndent = false
|
||||
} else {
|
||||
content, err = json.MarshalIndent(c.Data["jsonp"], "", " ")
|
||||
hasIndent = true
|
||||
}
|
||||
if err != nil {
|
||||
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())
|
||||
c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent)
|
||||
}
|
||||
|
||||
func (c *Controller) ServeXml() {
|
||||
var content []byte
|
||||
var err error
|
||||
var hasIndent bool
|
||||
if RunMode == "prod" {
|
||||
content, err = xml.Marshal(c.Data["xml"])
|
||||
hasIndent = false
|
||||
} else {
|
||||
content, err = xml.MarshalIndent(c.Data["xml"], "", " ")
|
||||
hasIndent = true
|
||||
}
|
||||
if err != nil {
|
||||
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)
|
||||
c.Ctx.Output.Xml(c.Data["xml"], hasIndent)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
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) {
|
||||
return c.Ctx.Request.FormFile(key)
|
||||
}
|
||||
@ -365,7 +305,7 @@ func (c *Controller) DestroySession() {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
beecontext "github.com/astaxie/beego/context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -25,22 +24,11 @@ type controllerInfo struct {
|
||||
hasMethod bool
|
||||
}
|
||||
|
||||
type userHandler struct {
|
||||
pattern string
|
||||
regex *regexp.Regexp
|
||||
params map[int]string
|
||||
h http.Handler
|
||||
}
|
||||
|
||||
type ControllerRegistor struct {
|
||||
routers []*controllerInfo
|
||||
fixrouters []*controllerInfo
|
||||
enableFilter bool
|
||||
filters []http.HandlerFunc
|
||||
enableAfter bool
|
||||
afterFilters []http.HandlerFunc
|
||||
enableUser bool
|
||||
userHandlers map[string]*userHandler
|
||||
filters map[string][]*FilterRouter
|
||||
enableAuto bool
|
||||
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
|
||||
}
|
||||
@ -48,8 +36,8 @@ type ControllerRegistor struct {
|
||||
func NewControllerRegistor() *ControllerRegistor {
|
||||
return &ControllerRegistor{
|
||||
routers: make([]*controllerInfo, 0),
|
||||
userHandlers: make(map[string]*userHandler),
|
||||
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) {
|
||||
p.enableUser = true
|
||||
parts := strings.Split(pattern, "/")
|
||||
// Filter adds the middleware filter.
|
||||
func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) {
|
||||
p.enableFilter = true
|
||||
mr := new(FilterRouter)
|
||||
mr.filterFunc = filter
|
||||
|
||||
parts := strings.Split(pattern, "/")
|
||||
j := 0
|
||||
params := make(map[int]string)
|
||||
for i, part := range parts {
|
||||
if strings.HasPrefix(part, ":") {
|
||||
expr := "([^/]+)"
|
||||
expr := "(.+)"
|
||||
//a user may choose to override the defult expression
|
||||
// similar to expressjs: ‘/user/:id([0-9]+)’
|
||||
if index := strings.Index(part, "("); index != -1 {
|
||||
expr = 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
|
||||
j++
|
||||
}
|
||||
}
|
||||
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
|
||||
if j != 0 {
|
||||
pattern = strings.Join(parts, "/")
|
||||
regex, regexErr := regexp.Compile(pattern)
|
||||
if regexErr != nil {
|
||||
@ -218,73 +210,11 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) {
|
||||
panic(regexErr)
|
||||
return
|
||||
}
|
||||
|
||||
//now create the Route
|
||||
uh := &userHandler{}
|
||||
uh.regex = regex
|
||||
uh.params = params
|
||||
uh.pattern = pattern
|
||||
uh.h = c
|
||||
p.userHandlers[pattern] = uh
|
||||
mr.regex = regex
|
||||
mr.hasregex = true
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
})
|
||||
mr.pattern = pattern
|
||||
p.filters[action] = append(p.filters[action], mr)
|
||||
}
|
||||
|
||||
// AutoRoute
|
||||
@ -320,13 +250,30 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
}()
|
||||
|
||||
w := &responseWriter{writer: rw}
|
||||
|
||||
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 findrouter bool
|
||||
|
||||
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
|
||||
for prefix, staticDir := range StaticDir {
|
||||
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
|
||||
|
||||
var requestbody []byte
|
||||
|
||||
if CopyRequestBody {
|
||||
requestbody, _ = ioutil.ReadAll(r.Body)
|
||||
|
||||
r.Body.Close()
|
||||
|
||||
bf := bytes.NewBuffer(requestbody)
|
||||
|
||||
r.Body = ioutil.NopCloser(bf)
|
||||
context.Input.Body()
|
||||
}
|
||||
|
||||
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
|
||||
for _, route := range p.fixrouters {
|
||||
n := len(requestPath)
|
||||
@ -471,23 +379,21 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
if runrouter != nil {
|
||||
//execute middleware filters
|
||||
if p.enableFilter {
|
||||
for _, filter := range p.filters {
|
||||
filter(w, r)
|
||||
if w.started {
|
||||
return
|
||||
if l, ok := p.filters["BeforExec"]; ok {
|
||||
for _, filterR := range l {
|
||||
if filterR.ValidRouter(r.URL.Path) {
|
||||
filterR.filterFunc(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Invoke the request handler
|
||||
vc := reflect.New(runrouter.controllerType)
|
||||
|
||||
//call the controller init function
|
||||
init := vc.MethodByName("Init")
|
||||
in := make([]reflect.Value, 2)
|
||||
ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody}
|
||||
|
||||
in[0] = reflect.ValueOf(ct)
|
||||
in[0] = reflect.ValueOf(context)
|
||||
in[1] = reflect.ValueOf(runrouter.controllerType.Name())
|
||||
init.Call(in)
|
||||
//call prepare function
|
||||
@ -617,14 +523,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
method = vc.MethodByName("Finish")
|
||||
method.Call(in)
|
||||
//execute middleware filters
|
||||
if p.enableAfter {
|
||||
for _, filter := range p.afterFilters {
|
||||
filter(w, r)
|
||||
if w.started {
|
||||
return
|
||||
if p.enableFilter {
|
||||
if l, ok := p.filters["AfterExec"]; ok {
|
||||
for _, filterR := range l {
|
||||
if filterR.ValidRouter(r.URL.Path) {
|
||||
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)) {
|
||||
//execute middleware filters
|
||||
if p.enableFilter {
|
||||
for _, filter := range p.filters {
|
||||
filter(w, r)
|
||||
if w.started {
|
||||
return
|
||||
if l, ok := p.filters["BeforExec"]; ok {
|
||||
for _, filterR := range l {
|
||||
if filterR.ValidRouter(r.URL.Path) {
|
||||
filterR.filterFunc(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -672,9 +581,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
//call the controller init function
|
||||
init := vc.MethodByName("Init")
|
||||
in := make([]reflect.Value, 2)
|
||||
ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody}
|
||||
|
||||
in[0] = reflect.ValueOf(ct)
|
||||
in[0] = reflect.ValueOf(context)
|
||||
in[1] = reflect.ValueOf(controllerType.Name())
|
||||
init.Call(in)
|
||||
//call prepare function
|
||||
@ -702,11 +609,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
method = vc.MethodByName("Finish")
|
||||
method.Call(in)
|
||||
//execute middleware filters
|
||||
if p.enableAfter {
|
||||
for _, filter := range p.afterFilters {
|
||||
filter(w, r)
|
||||
if w.started {
|
||||
return
|
||||
if p.enableFilter {
|
||||
if l, ok := p.filters["AfterExec"]; ok {
|
||||
for _, filterR := range l {
|
||||
if filterR.ValidRouter(r.URL.Path) {
|
||||
filterR.filterFunc(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -714,6 +622,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
||||
method.Call(in)
|
||||
// set find
|
||||
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 !findrouter {
|
||||
if h, ok := ErrorMaps["404"]; ok {
|
||||
|
Loading…
Reference in New Issue
Block a user