change a log about new version
Showing
14 changed files
with
923 additions
and
658 deletions
app.go
0 → 100644
| 1 | package beego | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "github.com/astaxie/beego/context" | ||
| 6 | "net" | ||
| 7 | "net/http" | ||
| 8 | "net/http/fcgi" | ||
| 9 | "time" | ||
| 10 | ) | ||
| 11 | |||
| 12 | type FilterFunc func(*context.Context) | ||
| 13 | |||
| 14 | type App struct { | ||
| 15 | Handlers *ControllerRegistor | ||
| 16 | } | ||
| 17 | |||
| 18 | // New returns a new PatternServeMux. | ||
| 19 | func NewApp() *App { | ||
| 20 | cr := NewControllerRegistor() | ||
| 21 | app := &App{Handlers: cr} | ||
| 22 | return app | ||
| 23 | } | ||
| 24 | |||
| 25 | func (app *App) Run() { | ||
| 26 | addr := HttpAddr | ||
| 27 | |||
| 28 | if HttpPort != 0 { | ||
| 29 | addr = fmt.Sprintf("%s:%d", HttpAddr, HttpPort) | ||
| 30 | } | ||
| 31 | var ( | ||
| 32 | err error | ||
| 33 | l net.Listener | ||
| 34 | ) | ||
| 35 | if UseFcgi { | ||
| 36 | if HttpPort == 0 { | ||
| 37 | l, err = net.Listen("unix", addr) | ||
| 38 | } else { | ||
| 39 | l, err = net.Listen("tcp", addr) | ||
| 40 | } | ||
| 41 | if err != nil { | ||
| 42 | BeeLogger.Fatal("Listen: ", err) | ||
| 43 | } | ||
| 44 | err = fcgi.Serve(l, app.Handlers) | ||
| 45 | } else { | ||
| 46 | if EnableHotUpdate { | ||
| 47 | server := &http.Server{ | ||
| 48 | Handler: app.Handlers, | ||
| 49 | ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 50 | WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 51 | } | ||
| 52 | laddr, err := net.ResolveTCPAddr("tcp", addr) | ||
| 53 | if nil != err { | ||
| 54 | BeeLogger.Fatal("ResolveTCPAddr:", err) | ||
| 55 | } | ||
| 56 | l, err = GetInitListner(laddr) | ||
| 57 | theStoppable = newStoppable(l) | ||
| 58 | err = server.Serve(theStoppable) | ||
| 59 | theStoppable.wg.Wait() | ||
| 60 | CloseSelf() | ||
| 61 | } else { | ||
| 62 | s := &http.Server{ | ||
| 63 | Addr: addr, | ||
| 64 | Handler: app.Handlers, | ||
| 65 | ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 66 | WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 67 | } | ||
| 68 | if HttpTLS { | ||
| 69 | err = s.ListenAndServeTLS(HttpCertFile, HttpKeyFile) | ||
| 70 | } else { | ||
| 71 | err = s.ListenAndServe() | ||
| 72 | } | ||
| 73 | } | ||
| 74 | } | ||
| 75 | if err != nil { | ||
| 76 | BeeLogger.Fatal("ListenAndServe: ", err) | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App { | ||
| 81 | app.Handlers.Add(path, c, mappingMethods...) | ||
| 82 | return app | ||
| 83 | } | ||
| 84 | |||
| 85 | func (app *App) AutoRouter(c ControllerInterface) *App { | ||
| 86 | app.Handlers.AddAuto(c) | ||
| 87 | return app | ||
| 88 | } | ||
| 89 | |||
| 90 | func (app *App) Filter(pattern, action string, filter FilterFunc) *App { | ||
| 91 | app.Handlers.AddFilter(pattern, action, filter) | ||
| 92 | return app | ||
| 93 | } | ||
| 94 | |||
| 95 | func (app *App) SetViewsPath(path string) *App { | ||
| 96 | ViewsPath = path | ||
| 97 | return app | ||
| 98 | } | ||
| 99 | |||
| 100 | func (app *App) SetStaticPath(url string, path string) *App { | ||
| 101 | StaticDir[url] = path | ||
| 102 | return app | ||
| 103 | } | ||
| 104 | |||
| 105 | func (app *App) DelStaticPath(url string) *App { | ||
| 106 | delete(StaticDir, url) | ||
| 107 | return app | ||
| 108 | } |
| 1 | package beego | 1 | package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "fmt" | ||
| 5 | "github.com/astaxie/beego/session" | 4 | "github.com/astaxie/beego/session" |
| 6 | "html/template" | ||
| 7 | "net" | ||
| 8 | "net/http" | 5 | "net/http" |
| 9 | "net/http/fcgi" | ||
| 10 | "os" | ||
| 11 | "path" | 6 | "path" |
| 12 | "runtime" | ||
| 13 | "time" | ||
| 14 | ) | 7 | ) |
| 15 | 8 | ||
| 16 | const VERSION = "0.9.0" | 9 | const VERSION = "0.9.0" |
| 17 | 10 | ||
| 18 | var ( | ||
| 19 | BeeApp *App | ||
| 20 | AppName string | ||
| 21 | AppPath string | ||
| 22 | AppConfigPath string | ||
| 23 | StaticDir map[string]string | ||
| 24 | TemplateCache map[string]*template.Template | ||
| 25 | HttpAddr string | ||
| 26 | HttpPort int | ||
| 27 | RecoverPanic bool | ||
| 28 | AutoRender bool | ||
| 29 | PprofOn bool | ||
| 30 | ViewsPath string | ||
| 31 | RunMode string //"dev" or "prod" | ||
| 32 | AppConfig *Config | ||
| 33 | //related to session | ||
| 34 | GlobalSessions *session.Manager //GlobalSessions | ||
| 35 | SessionOn bool // whether auto start session,default is false | ||
| 36 | SessionProvider string // default session provider memory mysql redis | ||
| 37 | SessionName string // sessionName cookie's name | ||
| 38 | SessionGCMaxLifetime int64 // session's gc maxlifetime | ||
| 39 | SessionSavePath string // session savepath if use mysql/redis/file this set to the connectinfo | ||
| 40 | UseFcgi bool | ||
| 41 | MaxMemory int64 | ||
| 42 | EnableGzip bool // enable gzip | ||
| 43 | DirectoryIndex bool //enable DirectoryIndex default is false | ||
| 44 | EnableHotUpdate bool //enable HotUpdate default is false | ||
| 45 | HttpServerTimeOut int64 //set httpserver timeout | ||
| 46 | ErrorsShow bool //set weather show errors | ||
| 47 | XSRFKEY string //set XSRF | ||
| 48 | EnableXSRF bool | ||
| 49 | XSRFExpire int | ||
| 50 | CopyRequestBody bool //When in raw application, You want to the reqeustbody | ||
| 51 | TemplateLeft string | ||
| 52 | TemplateRight string | ||
| 53 | ) | ||
| 54 | |||
| 55 | func init() { | ||
| 56 | os.Chdir(path.Dir(os.Args[0])) | ||
| 57 | BeeApp = NewApp() | ||
| 58 | AppPath, _ = os.Getwd() | ||
| 59 | StaticDir = make(map[string]string) | ||
| 60 | TemplateCache = make(map[string]*template.Template) | ||
| 61 | HttpAddr = "" | ||
| 62 | HttpPort = 8080 | ||
| 63 | AppName = "beego" | ||
| 64 | RunMode = "dev" //default runmod | ||
| 65 | AutoRender = true | ||
| 66 | RecoverPanic = true | ||
| 67 | PprofOn = false | ||
| 68 | ViewsPath = "views" | ||
| 69 | SessionOn = false | ||
| 70 | SessionProvider = "memory" | ||
| 71 | SessionName = "beegosessionID" | ||
| 72 | SessionGCMaxLifetime = 3600 | ||
| 73 | SessionSavePath = "" | ||
| 74 | UseFcgi = false | ||
| 75 | MaxMemory = 1 << 26 //64MB | ||
| 76 | EnableGzip = false | ||
| 77 | StaticDir["/static"] = "static" | ||
| 78 | AppConfigPath = path.Join(AppPath, "conf", "app.conf") | ||
| 79 | HttpServerTimeOut = 0 | ||
| 80 | ErrorsShow = true | ||
| 81 | XSRFKEY = "beegoxsrf" | ||
| 82 | XSRFExpire = 60 | ||
| 83 | TemplateLeft = "{{" | ||
| 84 | TemplateRight = "}}" | ||
| 85 | ParseConfig() | ||
| 86 | runtime.GOMAXPROCS(runtime.NumCPU()) | ||
| 87 | } | ||
| 88 | |||
| 89 | type App struct { | ||
| 90 | Handlers *ControllerRegistor | ||
| 91 | } | ||
| 92 | |||
| 93 | // New returns a new PatternServeMux. | ||
| 94 | func NewApp() *App { | ||
| 95 | cr := NewControllerRegistor() | ||
| 96 | app := &App{Handlers: cr} | ||
| 97 | return app | ||
| 98 | } | ||
| 99 | |||
| 100 | func (app *App) Run() { | ||
| 101 | addr := HttpAddr | ||
| 102 | |||
| 103 | if HttpPort != 0 { | ||
| 104 | addr = fmt.Sprintf("%s:%d", HttpAddr, HttpPort) | ||
| 105 | } | ||
| 106 | var ( | ||
| 107 | err error | ||
| 108 | l net.Listener | ||
| 109 | ) | ||
| 110 | if UseFcgi { | ||
| 111 | if HttpPort == 0 { | ||
| 112 | l, err = net.Listen("unix", addr) | ||
| 113 | } else { | ||
| 114 | l, err = net.Listen("tcp", addr) | ||
| 115 | } | ||
| 116 | if err != nil { | ||
| 117 | BeeLogger.Fatal("Listen: ", err) | ||
| 118 | } | ||
| 119 | err = fcgi.Serve(l, app.Handlers) | ||
| 120 | } else { | ||
| 121 | if EnableHotUpdate { | ||
| 122 | server := &http.Server{ | ||
| 123 | Handler: app.Handlers, | ||
| 124 | ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 125 | WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 126 | } | ||
| 127 | laddr, err := net.ResolveTCPAddr("tcp", addr) | ||
| 128 | if nil != err { | ||
| 129 | BeeLogger.Fatal("ResolveTCPAddr:", err) | ||
| 130 | } | ||
| 131 | l, err = GetInitListner(laddr) | ||
| 132 | theStoppable = newStoppable(l) | ||
| 133 | err = server.Serve(theStoppable) | ||
| 134 | theStoppable.wg.Wait() | ||
| 135 | CloseSelf() | ||
| 136 | } else { | ||
| 137 | s := &http.Server{ | ||
| 138 | Addr: addr, | ||
| 139 | Handler: app.Handlers, | ||
| 140 | ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 141 | WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, | ||
| 142 | } | ||
| 143 | err = s.ListenAndServe() | ||
| 144 | } | ||
| 145 | } | ||
| 146 | if err != nil { | ||
| 147 | BeeLogger.Fatal("ListenAndServe: ", err) | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App { | ||
| 152 | app.Handlers.Add(path, c, mappingMethods...) | ||
| 153 | return app | ||
| 154 | } | ||
| 155 | |||
| 156 | func (app *App) AutoRouter(c ControllerInterface) *App { | ||
| 157 | app.Handlers.AddAuto(c) | ||
| 158 | return app | ||
| 159 | } | ||
| 160 | |||
| 161 | func (app *App) Filter(filter http.HandlerFunc) *App { | ||
| 162 | app.Handlers.Filter(filter) | ||
| 163 | return app | ||
| 164 | } | ||
| 165 | |||
| 166 | func (app *App) FilterParam(param string, filter http.HandlerFunc) *App { | ||
| 167 | app.Handlers.FilterParam(param, filter) | ||
| 168 | return app | ||
| 169 | } | ||
| 170 | |||
| 171 | func (app *App) FilterPrefixPath(path string, filter http.HandlerFunc) *App { | ||
| 172 | app.Handlers.FilterPrefixPath(path, filter) | ||
| 173 | return app | ||
| 174 | } | ||
| 175 | |||
| 176 | func (app *App) FilterAfter(filter http.HandlerFunc) *App { | ||
| 177 | app.Handlers.FilterAfter(filter) | ||
| 178 | return app | ||
| 179 | } | ||
| 180 | |||
| 181 | func (app *App) FilterParamAfter(param string, filter http.HandlerFunc) *App { | ||
| 182 | app.Handlers.FilterParamAfter(param, filter) | ||
| 183 | return app | ||
| 184 | } | ||
| 185 | |||
| 186 | func (app *App) FilterPrefixPathAfter(path string, filter http.HandlerFunc) *App { | ||
| 187 | app.Handlers.FilterPrefixPathAfter(path, filter) | ||
| 188 | return app | ||
| 189 | } | ||
| 190 | |||
| 191 | func (app *App) SetViewsPath(path string) *App { | ||
| 192 | ViewsPath = path | ||
| 193 | return app | ||
| 194 | } | ||
| 195 | |||
| 196 | func (app *App) SetStaticPath(url string, path string) *App { | ||
| 197 | StaticDir[url] = path | ||
| 198 | return app | ||
| 199 | } | ||
| 200 | |||
| 201 | func (app *App) DelStaticPath(url string) *App { | ||
| 202 | delete(StaticDir, url) | ||
| 203 | return app | ||
| 204 | } | ||
| 205 | |||
| 206 | func (app *App) ErrorLog(ctx *Context) { | ||
| 207 | 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) | ||
| 208 | } | ||
| 209 | |||
| 210 | func (app *App) AccessLog(ctx *Context) { | ||
| 211 | 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) | ||
| 212 | } | ||
| 213 | |||
| 214 | func RegisterController(path string, c ControllerInterface) *App { | ||
| 215 | BeeApp.Router(path, c) | ||
| 216 | return BeeApp | ||
| 217 | } | ||
| 218 | |||
| 219 | func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App { | 11 | func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App { |
| 220 | BeeApp.Router(rootpath, c, mappingMethods...) | 12 | BeeApp.Router(rootpath, c, mappingMethods...) |
| 221 | return BeeApp | 13 | return BeeApp |
| ... | @@ -232,11 +24,6 @@ func AutoRouter(c ControllerInterface) *App { | ... | @@ -232,11 +24,6 @@ func AutoRouter(c ControllerInterface) *App { |
| 232 | return BeeApp | 24 | return BeeApp |
| 233 | } | 25 | } |
| 234 | 26 | ||
| 235 | func RouterHandler(path string, c http.Handler) *App { | ||
| 236 | BeeApp.Handlers.AddHandler(path, c) | ||
| 237 | return BeeApp | ||
| 238 | } | ||
| 239 | |||
| 240 | func Errorhandler(err string, h http.HandlerFunc) *App { | 27 | func Errorhandler(err string, h http.HandlerFunc) *App { |
| 241 | ErrorMaps[err] = h | 28 | ErrorMaps[err] = h |
| 242 | return BeeApp | 29 | return BeeApp |
| ... | @@ -257,37 +44,18 @@ func DelStaticPath(url string) *App { | ... | @@ -257,37 +44,18 @@ func DelStaticPath(url string) *App { |
| 257 | return BeeApp | 44 | return BeeApp |
| 258 | } | 45 | } |
| 259 | 46 | ||
| 260 | func Filter(filter http.HandlerFunc) *App { | 47 | //action has four values: |
| 261 | BeeApp.Filter(filter) | 48 | //BeforRouter |
| 262 | return BeeApp | 49 | //AfterStatic |
| 263 | } | 50 | //BeforExec |
| 264 | 51 | //AfterExec | |
| 265 | func FilterParam(param string, filter http.HandlerFunc) *App { | 52 | func AddFilter(pattern, action string, filter FilterFunc) *App { |
| 266 | BeeApp.FilterParam(param, filter) | 53 | BeeApp.Filter(pattern, action, filter) |
| 267 | return BeeApp | ||
| 268 | } | ||
| 269 | |||
| 270 | func FilterPrefixPath(path string, filter http.HandlerFunc) *App { | ||
| 271 | BeeApp.FilterPrefixPath(path, filter) | ||
| 272 | return BeeApp | ||
| 273 | } | ||
| 274 | |||
| 275 | func FilterAfter(filter http.HandlerFunc) *App { | ||
| 276 | BeeApp.FilterAfter(filter) | ||
| 277 | return BeeApp | ||
| 278 | } | ||
| 279 | |||
| 280 | func FilterParamAfter(param string, filter http.HandlerFunc) *App { | ||
| 281 | BeeApp.FilterParamAfter(param, filter) | ||
| 282 | return BeeApp | ||
| 283 | } | ||
| 284 | |||
| 285 | func FilterPrefixPathAfter(path string, filter http.HandlerFunc) *App { | ||
| 286 | BeeApp.FilterPrefixPathAfter(path, filter) | ||
| 287 | return BeeApp | 54 | return BeeApp |
| 288 | } | 55 | } |
| 289 | 56 | ||
| 290 | func Run() { | 57 | func Run() { |
| 58 | //if AppConfigPath not In the conf/app.conf reParse config | ||
| 291 | if AppConfigPath != path.Join(AppPath, "conf", "app.conf") { | 59 | if AppConfigPath != path.Join(AppPath, "conf", "app.conf") { |
| 292 | err := ParseConfig() | 60 | err := ParseConfig() |
| 293 | if err != nil { | 61 | if err != nil { |
| ... | @@ -296,18 +64,18 @@ func Run() { | ... | @@ -296,18 +64,18 @@ func Run() { |
| 296 | } | 64 | } |
| 297 | } | 65 | } |
| 298 | } | 66 | } |
| 299 | if PprofOn { | 67 | |
| 300 | BeeApp.Router(`/debug/pprof`, &ProfController{}) | ||
| 301 | BeeApp.Router(`/debug/pprof/:pp([\w]+)`, &ProfController{}) | ||
| 302 | } | ||
| 303 | if SessionOn { | 68 | if SessionOn { |
| 304 | GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath) | 69 | GlobalSessions, _ = session.NewManager(SessionProvider, SessionName, SessionGCMaxLifetime, SessionSavePath) |
| 305 | go GlobalSessions.GC() | 70 | go GlobalSessions.GC() |
| 306 | } | 71 | } |
| 307 | err := BuildTemplate(ViewsPath) | 72 | |
| 308 | if err != nil { | 73 | if AutoRender { |
| 309 | if RunMode == "dev" { | 74 | err := BuildTemplate(ViewsPath) |
| 310 | Warn(err) | 75 | if err != nil { |
| 76 | if RunMode == "dev" { | ||
| 77 | Warn(err) | ||
| 78 | } | ||
| 311 | } | 79 | } |
| 312 | } | 80 | } |
| 313 | registerErrorHander() | 81 | registerErrorHander() | ... | ... |
| 1 | package beego | 1 | package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "bufio" | 4 | "github.com/astaxie/beego/config" |
| 5 | "bytes" | 5 | "github.com/astaxie/beego/session" |
| 6 | "errors" | 6 | "html/template" |
| 7 | "io" | ||
| 8 | "os" | 7 | "os" |
| 8 | "path" | ||
| 9 | "runtime" | ||
| 9 | "strconv" | 10 | "strconv" |
| 10 | "strings" | ||
| 11 | "sync" | ||
| 12 | "unicode" | ||
| 13 | ) | 11 | ) |
| 14 | 12 | ||
| 15 | var ( | 13 | var ( |
| 16 | bComment = []byte{'#'} | 14 | BeeApp *App |
| 17 | bEmpty = []byte{} | 15 | AppName string |
| 18 | bEqual = []byte{'='} | 16 | AppPath string |
| 19 | bDQuote = []byte{'"'} | 17 | AppConfigPath string |
| 18 | StaticDir map[string]string | ||
| 19 | TemplateCache map[string]*template.Template | ||
| 20 | HttpAddr string | ||
| 21 | HttpPort int | ||
| 22 | HttpTLS bool | ||
| 23 | HttpCertFile string | ||
| 24 | HttpKeyFile string | ||
| 25 | RecoverPanic bool | ||
| 26 | AutoRender bool | ||
| 27 | PprofOn bool | ||
| 28 | ViewsPath string | ||
| 29 | RunMode string //"dev" or "prod" | ||
| 30 | AppConfig config.ConfigContainer | ||
| 31 | //related to session | ||
| 32 | GlobalSessions *session.Manager //GlobalSessions | ||
| 33 | SessionOn bool // whether auto start session,default is false | ||
| 34 | SessionProvider string // default session provider memory mysql redis | ||
| 35 | SessionName string // sessionName cookie's name | ||
| 36 | SessionGCMaxLifetime int64 // session's gc maxlifetime | ||
| 37 | SessionSavePath string // session savepath if use mysql/redis/file this set to the connectinfo | ||
| 38 | UseFcgi bool | ||
| 39 | MaxMemory int64 | ||
| 40 | EnableGzip bool // enable gzip | ||
| 41 | DirectoryIndex bool //enable DirectoryIndex default is false | ||
| 42 | EnableHotUpdate bool //enable HotUpdate default is false | ||
| 43 | HttpServerTimeOut int64 //set httpserver timeout | ||
| 44 | ErrorsShow bool //set weather show errors | ||
| 45 | XSRFKEY string //set XSRF | ||
| 46 | EnableXSRF bool | ||
| 47 | XSRFExpire int | ||
| 48 | CopyRequestBody bool //When in raw application, You want to the reqeustbody | ||
| 49 | TemplateLeft string | ||
| 50 | TemplateRight string | ||
| 20 | ) | 51 | ) |
| 21 | 52 | ||
| 22 | // A Config represents the configuration. | 53 | func init() { |
| 23 | type Config struct { | 54 | os.Chdir(path.Dir(os.Args[0])) |
| 24 | filename string | 55 | BeeApp = NewApp() |
| 25 | comment map[int][]string // id: []{comment, key...}; id 1 is for main comment. | 56 | AppPath, _ = os.Getwd() |
| 26 | data map[string]string // key: value | 57 | StaticDir = make(map[string]string) |
| 27 | offset map[string]int64 // key: offset; for editing. | 58 | TemplateCache = make(map[string]*template.Template) |
| 28 | sync.RWMutex | 59 | HttpAddr = "" |
| 29 | } | 60 | HttpPort = 8080 |
| 30 | 61 | AppName = "beego" | |
| 31 | // ParseFile creates a new Config and parses the file configuration from the | 62 | RunMode = "dev" //default runmod |
| 32 | // named file. | 63 | AutoRender = true |
| 33 | func LoadConfig(name string) (*Config, error) { | 64 | RecoverPanic = true |
| 34 | file, err := os.Open(name) | 65 | PprofOn = false |
| 35 | if err != nil { | 66 | ViewsPath = "views" |
| 36 | return nil, err | 67 | SessionOn = false |
| 37 | } | 68 | SessionProvider = "memory" |
| 38 | 69 | SessionName = "beegosessionID" | |
| 39 | cfg := &Config{ | 70 | SessionGCMaxLifetime = 3600 |
| 40 | file.Name(), | 71 | SessionSavePath = "" |
| 41 | make(map[int][]string), | 72 | UseFcgi = false |
| 42 | make(map[string]string), | 73 | MaxMemory = 1 << 26 //64MB |
| 43 | make(map[string]int64), | 74 | EnableGzip = false |
| 44 | sync.RWMutex{}, | 75 | StaticDir["/static"] = "static" |
| 45 | } | 76 | AppConfigPath = path.Join(AppPath, "conf", "app.conf") |
| 46 | cfg.Lock() | 77 | HttpServerTimeOut = 0 |
| 47 | defer cfg.Unlock() | 78 | ErrorsShow = true |
| 48 | defer file.Close() | 79 | XSRFKEY = "beegoxsrf" |
| 49 | 80 | XSRFExpire = 60 | |
| 50 | var comment bytes.Buffer | 81 | TemplateLeft = "{{" |
| 51 | buf := bufio.NewReader(file) | 82 | TemplateRight = "}}" |
| 52 | 83 | ParseConfig() | |
| 53 | for nComment, off := 0, int64(1); ; { | 84 | runtime.GOMAXPROCS(runtime.NumCPU()) |
| 54 | line, _, err := buf.ReadLine() | ||
| 55 | if err == io.EOF { | ||
| 56 | break | ||
| 57 | } | ||
| 58 | if bytes.Equal(line, bEmpty) { | ||
| 59 | continue | ||
| 60 | } | ||
| 61 | |||
| 62 | off += int64(len(line)) | ||
| 63 | |||
| 64 | if bytes.HasPrefix(line, bComment) { | ||
| 65 | line = bytes.TrimLeft(line, "#") | ||
| 66 | line = bytes.TrimLeftFunc(line, unicode.IsSpace) | ||
| 67 | comment.Write(line) | ||
| 68 | comment.WriteByte('\n') | ||
| 69 | continue | ||
| 70 | } | ||
| 71 | if comment.Len() != 0 { | ||
| 72 | cfg.comment[nComment] = []string{comment.String()} | ||
| 73 | comment.Reset() | ||
| 74 | nComment++ | ||
| 75 | } | ||
| 76 | |||
| 77 | val := bytes.SplitN(line, bEqual, 2) | ||
| 78 | if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) { | ||
| 79 | val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`) | ||
| 80 | } | ||
| 81 | |||
| 82 | key := strings.TrimSpace(string(val[0])) | ||
| 83 | cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key) | ||
| 84 | cfg.data[key] = strings.TrimSpace(string(val[1])) | ||
| 85 | cfg.offset[key] = off | ||
| 86 | } | ||
| 87 | return cfg, nil | ||
| 88 | } | ||
| 89 | |||
| 90 | // Bool returns the boolean value for a given key. | ||
| 91 | func (c *Config) Bool(key string) (bool, error) { | ||
| 92 | return strconv.ParseBool(c.data[key]) | ||
| 93 | } | ||
| 94 | |||
| 95 | // Int returns the integer value for a given key. | ||
| 96 | func (c *Config) Int(key string) (int, error) { | ||
| 97 | return strconv.Atoi(c.data[key]) | ||
| 98 | } | ||
| 99 | |||
| 100 | func (c *Config) Int64(key string) (int64, error) { | ||
| 101 | return strconv.ParseInt(c.data[key], 10, 64) | ||
| 102 | } | ||
| 103 | |||
| 104 | // Float returns the float value for a given key. | ||
| 105 | func (c *Config) Float(key string) (float64, error) { | ||
| 106 | return strconv.ParseFloat(c.data[key], 64) | ||
| 107 | } | ||
| 108 | |||
| 109 | // String returns the string value for a given key. | ||
| 110 | func (c *Config) String(key string) string { | ||
| 111 | return c.data[key] | ||
| 112 | } | ||
| 113 | |||
| 114 | // WriteValue writes a new value for key. | ||
| 115 | func (c *Config) SetValue(key, value string) error { | ||
| 116 | c.Lock() | ||
| 117 | defer c.Unlock() | ||
| 118 | |||
| 119 | if _, found := c.data[key]; !found { | ||
| 120 | return errors.New("key not found: " + key) | ||
| 121 | } | ||
| 122 | |||
| 123 | c.data[key] = value | ||
| 124 | return nil | ||
| 125 | } | 85 | } |
| 126 | 86 | ||
| 127 | func ParseConfig() (err error) { | 87 | func ParseConfig() (err error) { |
| 128 | AppConfig, err = LoadConfig(AppConfigPath) | 88 | AppConfig, err := config.NewConfig("ini", AppConfigPath) |
| 129 | if err != nil { | 89 | if err != nil { |
| 130 | return err | 90 | return err |
| 131 | } else { | 91 | } else { |
| ... | @@ -204,6 +164,15 @@ func ParseConfig() (err error) { | ... | @@ -204,6 +164,15 @@ func ParseConfig() (err error) { |
| 204 | if tplright := AppConfig.String("templateright"); tplright != "" { | 164 | if tplright := AppConfig.String("templateright"); tplright != "" { |
| 205 | TemplateRight = tplright | 165 | TemplateRight = tplright |
| 206 | } | 166 | } |
| 167 | if httptls, err := AppConfig.Bool("HttpTLS"); err == nil { | ||
| 168 | HttpTLS = httptls | ||
| 169 | } | ||
| 170 | if certfile := AppConfig.String("HttpCertFile"); certfile != "" { | ||
| 171 | HttpCertFile = certfile | ||
| 172 | } | ||
| 173 | if keyfile := AppConfig.String("HttpKeyFile"); keyfile != "" { | ||
| 174 | HttpKeyFile = keyfile | ||
| 175 | } | ||
| 207 | } | 176 | } |
| 208 | return nil | 177 | return nil |
| 209 | } | 178 | } | ... | ... |
| ... | @@ -16,6 +16,11 @@ func (ctx *Context) Redirect(status int, localurl string) { | ... | @@ -16,6 +16,11 @@ func (ctx *Context) Redirect(status int, localurl string) { |
| 16 | ctx.Output.SetStatus(status) | 16 | ctx.Output.SetStatus(status) |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | func (ctx *Context) Abort(status int, body string) { | ||
| 20 | ctx.Output.SetStatus(status) | ||
| 21 | ctx.Output.Body([]byte(body)) | ||
| 22 | } | ||
| 23 | |||
| 19 | func (ctx *Context) WriteString(content string) { | 24 | func (ctx *Context) WriteString(content string) { |
| 20 | ctx.Output.Body([]byte(content)) | 25 | ctx.Output.Body([]byte(content)) |
| 21 | } | 26 | } | ... | ... |
| ... | @@ -17,7 +17,7 @@ import ( | ... | @@ -17,7 +17,7 @@ import ( |
| 17 | ) | 17 | ) |
| 18 | 18 | ||
| 19 | type BeegoOutput struct { | 19 | type BeegoOutput struct { |
| 20 | context *Context | 20 | Context *Context |
| 21 | Status int | 21 | Status int |
| 22 | EnableGzip bool | 22 | EnableGzip bool |
| 23 | res http.ResponseWriter | 23 | res http.ResponseWriter |
| ... | @@ -35,8 +35,8 @@ func (output *BeegoOutput) Header(key, val string) { | ... | @@ -35,8 +35,8 @@ func (output *BeegoOutput) Header(key, val string) { |
| 35 | 35 | ||
| 36 | func (output *BeegoOutput) Body(content []byte) { | 36 | func (output *BeegoOutput) Body(content []byte) { |
| 37 | output_writer := output.res.(io.Writer) | 37 | output_writer := output.res.(io.Writer) |
| 38 | if output.EnableGzip == true && output.context.Input.Header("Accept-Encoding") != "" { | 38 | if output.EnableGzip == true && output.Context.Input.Header("Accept-Encoding") != "" { |
| 39 | splitted := strings.SplitN(output.context.Input.Header("Accept-Encoding"), ",", -1) | 39 | splitted := strings.SplitN(output.Context.Input.Header("Accept-Encoding"), ",", -1) |
| 40 | encodings := make([]string, len(splitted)) | 40 | encodings := make([]string, len(splitted)) |
| 41 | 41 | ||
| 42 | for i, val := range splitted { | 42 | for i, val := range splitted { |
| ... | @@ -120,23 +120,40 @@ func sanitizeValue(v string) string { | ... | @@ -120,23 +120,40 @@ func sanitizeValue(v string) string { |
| 120 | return cookieValueSanitizer.Replace(v) | 120 | return cookieValueSanitizer.Replace(v) |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | func (output *BeegoOutput) Json(data string) error { | 123 | func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) error { |
| 124 | output.Header("Content-Type", "application/json;charset=UTF-8") | 124 | output.Header("Content-Type", "application/json;charset=UTF-8") |
| 125 | content, err := json.Marshal(data) | 125 | var content []byte |
| 126 | var err error | ||
| 127 | if hasIndent { | ||
| 128 | content, err = json.MarshalIndent(data, "", " ") | ||
| 129 | } else { | ||
| 130 | content, err = json.Marshal(data) | ||
| 131 | } | ||
| 126 | if err != nil { | 132 | if err != nil { |
| 133 | http.Error(output.res, err.Error(), http.StatusInternalServerError) | ||
| 127 | return err | 134 | return err |
| 128 | } | 135 | } |
| 136 | if coding { | ||
| 137 | content = []byte(stringsToJson(string(content))) | ||
| 138 | } | ||
| 129 | output.Body(content) | 139 | output.Body(content) |
| 130 | return nil | 140 | return nil |
| 131 | } | 141 | } |
| 132 | 142 | ||
| 133 | func (output *BeegoOutput) Jsonp(data string) error { | 143 | func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error { |
| 134 | output.Header("Content-Type", "application/javascript;charset=UTF-8") | 144 | output.Header("Content-Type", "application/javascript;charset=UTF-8") |
| 135 | content, err := json.Marshal(data) | 145 | var content []byte |
| 146 | var err error | ||
| 147 | if hasIndent { | ||
| 148 | content, err = json.MarshalIndent(data, "", " ") | ||
| 149 | } else { | ||
| 150 | content, err = json.Marshal(data) | ||
| 151 | } | ||
| 136 | if err != nil { | 152 | if err != nil { |
| 153 | http.Error(output.res, err.Error(), http.StatusInternalServerError) | ||
| 137 | return err | 154 | return err |
| 138 | } | 155 | } |
| 139 | callback := output.context.Input.Query("callback") | 156 | callback := output.Context.Input.Query("callback") |
| 140 | if callback == "" { | 157 | if callback == "" { |
| 141 | return errors.New(`"callback" parameter required`) | 158 | return errors.New(`"callback" parameter required`) |
| 142 | } | 159 | } |
| ... | @@ -148,10 +165,17 @@ func (output *BeegoOutput) Jsonp(data string) error { | ... | @@ -148,10 +165,17 @@ func (output *BeegoOutput) Jsonp(data string) error { |
| 148 | return nil | 165 | return nil |
| 149 | } | 166 | } |
| 150 | 167 | ||
| 151 | func (output *BeegoOutput) Xml(data string) error { | 168 | func (output *BeegoOutput) Xml(data string, hasIndent bool) error { |
| 152 | output.Header("Content-Type", "application/xml;charset=UTF-8") | 169 | output.Header("Content-Type", "application/xml;charset=UTF-8") |
| 153 | content, err := xml.Marshal(data) | 170 | var content []byte |
| 171 | var err error | ||
| 172 | if hasIndent { | ||
| 173 | content, err = xml.MarshalIndent(data, "", " ") | ||
| 174 | } else { | ||
| 175 | content, err = xml.Marshal(data) | ||
| 176 | } | ||
| 154 | if err != nil { | 177 | if err != nil { |
| 178 | http.Error(output.res, err.Error(), http.StatusInternalServerError) | ||
| 155 | return err | 179 | return err |
| 156 | } | 180 | } |
| 157 | output.Body(content) | 181 | output.Body(content) |
| ... | @@ -166,7 +190,7 @@ func (output *BeegoOutput) Download(file string) { | ... | @@ -166,7 +190,7 @@ func (output *BeegoOutput) Download(file string) { |
| 166 | output.Header("Expires", "0") | 190 | output.Header("Expires", "0") |
| 167 | output.Header("Cache-Control", "must-revalidate") | 191 | output.Header("Cache-Control", "must-revalidate") |
| 168 | output.Header("Pragma", "public") | 192 | output.Header("Pragma", "public") |
| 169 | http.ServeFile(output.res, output.context.Request, file) | 193 | http.ServeFile(output.res, output.Context.Request, file) |
| 170 | } | 194 | } |
| 171 | 195 | ||
| 172 | func (output *BeegoOutput) ContentType(ext string) { | 196 | func (output *BeegoOutput) ContentType(ext string) { |
| ... | @@ -219,3 +243,17 @@ func (output *BeegoOutput) IsClientError(status int) bool { | ... | @@ -219,3 +243,17 @@ func (output *BeegoOutput) IsClientError(status int) bool { |
| 219 | func (output *BeegoOutput) IsServerError(status int) bool { | 243 | func (output *BeegoOutput) IsServerError(status int) bool { |
| 220 | return output.Status >= 500 && output.Status < 600 | 244 | return output.Status >= 500 && output.Status < 600 |
| 221 | } | 245 | } |
| 246 | |||
| 247 | func stringsToJson(str string) string { | ||
| 248 | rs := []rune(str) | ||
| 249 | jsons := "" | ||
| 250 | for _, r := range rs { | ||
| 251 | rint := int(r) | ||
| 252 | if rint < 128 { | ||
| 253 | jsons += string(r) | ||
| 254 | } else { | ||
| 255 | jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json | ||
| 256 | } | ||
| 257 | } | ||
| 258 | return jsons | ||
| 259 | } | ... | ... |
| ... | @@ -2,15 +2,12 @@ package beego | ... | @@ -2,15 +2,12 @@ package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "bytes" | 4 | "bytes" |
| 5 | "compress/flate" | ||
| 6 | "compress/gzip" | ||
| 7 | "crypto/hmac" | 5 | "crypto/hmac" |
| 8 | "crypto/sha1" | 6 | "crypto/sha1" |
| 9 | "encoding/base64" | 7 | "encoding/base64" |
| 10 | "encoding/json" | ||
| 11 | "encoding/xml" | ||
| 12 | "errors" | 8 | "errors" |
| 13 | "fmt" | 9 | "fmt" |
| 10 | "github.com/astaxie/beego/context" | ||
| 14 | "github.com/astaxie/beego/session" | 11 | "github.com/astaxie/beego/session" |
| 15 | "html/template" | 12 | "html/template" |
| 16 | "io" | 13 | "io" |
| ... | @@ -26,7 +23,7 @@ import ( | ... | @@ -26,7 +23,7 @@ import ( |
| 26 | ) | 23 | ) |
| 27 | 24 | ||
| 28 | type Controller struct { | 25 | type Controller struct { |
| 29 | Ctx *Context | 26 | Ctx *context.Context |
| 30 | Data map[interface{}]interface{} | 27 | Data map[interface{}]interface{} |
| 31 | ChildName string | 28 | ChildName string |
| 32 | TplNames string | 29 | TplNames string |
| ... | @@ -39,7 +36,7 @@ type Controller struct { | ... | @@ -39,7 +36,7 @@ type Controller struct { |
| 39 | } | 36 | } |
| 40 | 37 | ||
| 41 | type ControllerInterface interface { | 38 | type ControllerInterface interface { |
| 42 | Init(ct *Context, cn string) | 39 | Init(ct *Context, childName string) |
| 43 | Prepare() | 40 | Prepare() |
| 44 | Get() | 41 | Get() |
| 45 | Post() | 42 | Post() |
| ... | @@ -52,11 +49,11 @@ type ControllerInterface interface { | ... | @@ -52,11 +49,11 @@ type ControllerInterface interface { |
| 52 | Render() error | 49 | Render() error |
| 53 | } | 50 | } |
| 54 | 51 | ||
| 55 | func (c *Controller) Init(ctx *Context, cn string) { | 52 | func (c *Controller) Init(ctx *context.Context, childName string) { |
| 56 | c.Data = make(map[interface{}]interface{}) | 53 | c.Data = make(map[interface{}]interface{}) |
| 57 | c.Layout = "" | 54 | c.Layout = "" |
| 58 | c.TplNames = "" | 55 | c.TplNames = "" |
| 59 | c.ChildName = cn | 56 | c.ChildName = childName |
| 60 | c.Ctx = ctx | 57 | c.Ctx = ctx |
| 61 | c.TplExt = "tpl" | 58 | c.TplExt = "tpl" |
| 62 | } | 59 | } |
| ... | @@ -109,8 +106,8 @@ func (c *Controller) Render() error { | ... | @@ -109,8 +106,8 @@ func (c *Controller) Render() error { |
| 109 | if err != nil { | 106 | if err != nil { |
| 110 | return err | 107 | return err |
| 111 | } else { | 108 | } else { |
| 112 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/html; charset=utf-8") | 109 | c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8") |
| 113 | c.writeToWriter(rb) | 110 | c.Ctx.Output.Body(rb) |
| 114 | } | 111 | } |
| 115 | return nil | 112 | return nil |
| 116 | } | 113 | } |
| ... | @@ -172,41 +169,6 @@ func (c *Controller) RenderBytes() ([]byte, error) { | ... | @@ -172,41 +169,6 @@ func (c *Controller) RenderBytes() ([]byte, error) { |
| 172 | return []byte{}, nil | 169 | return []byte{}, nil |
| 173 | } | 170 | } |
| 174 | 171 | ||
| 175 | func (c *Controller) writeToWriter(rb []byte) { | ||
| 176 | output_writer := c.Ctx.ResponseWriter.(io.Writer) | ||
| 177 | if EnableGzip == true && c.Ctx.Request.Header.Get("Accept-Encoding") != "" { | ||
| 178 | splitted := strings.SplitN(c.Ctx.Request.Header.Get("Accept-Encoding"), ",", -1) | ||
| 179 | encodings := make([]string, len(splitted)) | ||
| 180 | |||
| 181 | for i, val := range splitted { | ||
| 182 | encodings[i] = strings.TrimSpace(val) | ||
| 183 | } | ||
| 184 | for _, val := range encodings { | ||
| 185 | if val == "gzip" { | ||
| 186 | c.Ctx.ResponseWriter.Header().Set("Content-Encoding", "gzip") | ||
| 187 | output_writer, _ = gzip.NewWriterLevel(c.Ctx.ResponseWriter, gzip.BestSpeed) | ||
| 188 | |||
| 189 | break | ||
| 190 | } else if val == "deflate" { | ||
| 191 | c.Ctx.ResponseWriter.Header().Set("Content-Encoding", "deflate") | ||
| 192 | output_writer, _ = flate.NewWriter(c.Ctx.ResponseWriter, flate.BestSpeed) | ||
| 193 | break | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } else { | ||
| 197 | c.Ctx.SetHeader("Content-Length", strconv.Itoa(len(rb)), true) | ||
| 198 | } | ||
| 199 | output_writer.Write(rb) | ||
| 200 | switch output_writer.(type) { | ||
| 201 | case *gzip.Writer: | ||
| 202 | output_writer.(*gzip.Writer).Close() | ||
| 203 | case *flate.Writer: | ||
| 204 | output_writer.(*flate.Writer).Close() | ||
| 205 | case io.WriteCloser: | ||
| 206 | output_writer.(io.WriteCloser).Close() | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | func (c *Controller) Redirect(url string, code int) { | 172 | func (c *Controller) Redirect(url string, code int) { |
| 211 | c.Ctx.Redirect(code, url) | 173 | c.Ctx.Redirect(code, url) |
| 212 | } | 174 | } |
| ... | @@ -216,63 +178,37 @@ func (c *Controller) Abort(code string) { | ... | @@ -216,63 +178,37 @@ func (c *Controller) Abort(code string) { |
| 216 | } | 178 | } |
| 217 | 179 | ||
| 218 | func (c *Controller) ServeJson(encoding ...bool) { | 180 | func (c *Controller) ServeJson(encoding ...bool) { |
| 219 | var content []byte | 181 | var hasIndent bool |
| 220 | var err error | 182 | var hasencoding bool |
| 221 | if RunMode == "prod" { | 183 | if RunMode == "prod" { |
| 222 | content, err = json.Marshal(c.Data["json"]) | 184 | hasIndent = false |
| 223 | } else { | 185 | } else { |
| 224 | content, err = json.MarshalIndent(c.Data["json"], "", " ") | 186 | hasIndent = true |
| 225 | } | 187 | } |
| 226 | if err != nil { | ||
| 227 | http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError) | ||
| 228 | return | ||
| 229 | } | ||
| 230 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json;charset=UTF-8") | ||
| 231 | if len(encoding) > 0 && encoding[0] == true { | 188 | if len(encoding) > 0 && encoding[0] == true { |
| 232 | content = []byte(stringsToJson(string(content))) | 189 | hasencoding = true |
| 233 | } | 190 | } |
| 234 | c.writeToWriter(content) | 191 | c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding) |
| 235 | } | 192 | } |
| 236 | 193 | ||
| 237 | func (c *Controller) ServeJsonp() { | 194 | func (c *Controller) ServeJsonp() { |
| 238 | var content []byte | 195 | var hasIndent bool |
| 239 | var err error | ||
| 240 | if RunMode == "prod" { | 196 | if RunMode == "prod" { |
| 241 | content, err = json.Marshal(c.Data["jsonp"]) | 197 | hasIndent = false |
| 242 | } else { | 198 | } else { |
| 243 | content, err = json.MarshalIndent(c.Data["jsonp"], "", " ") | 199 | hasIndent = true |
| 244 | } | ||
| 245 | if err != nil { | ||
| 246 | http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError) | ||
| 247 | return | ||
| 248 | } | ||
| 249 | callback := c.Ctx.Request.Form.Get("callback") | ||
| 250 | if callback == "" { | ||
| 251 | http.Error(c.Ctx.ResponseWriter, `"callback" parameter required`, http.StatusInternalServerError) | ||
| 252 | return | ||
| 253 | } | 200 | } |
| 254 | callback_content := bytes.NewBufferString(callback) | 201 | c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent) |
| 255 | callback_content.WriteString("(") | ||
| 256 | callback_content.Write(content) | ||
| 257 | callback_content.WriteString(");\r\n") | ||
| 258 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/javascript;charset=UTF-8") | ||
| 259 | c.writeToWriter(callback_content.Bytes()) | ||
| 260 | } | 202 | } |
| 261 | 203 | ||
| 262 | func (c *Controller) ServeXml() { | 204 | func (c *Controller) ServeXml() { |
| 263 | var content []byte | 205 | var hasIndent bool |
| 264 | var err error | ||
| 265 | if RunMode == "prod" { | 206 | if RunMode == "prod" { |
| 266 | content, err = xml.Marshal(c.Data["xml"]) | 207 | hasIndent = false |
| 267 | } else { | 208 | } else { |
| 268 | content, err = xml.MarshalIndent(c.Data["xml"], "", " ") | 209 | hasIndent = true |
| 269 | } | 210 | } |
| 270 | if err != nil { | 211 | c.Ctx.Output.Xml(c.Data["xml"], hasIndent) |
| 271 | http.Error(c.Ctx.ResponseWriter, err.Error(), http.StatusInternalServerError) | ||
| 272 | return | ||
| 273 | } | ||
| 274 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/xml;charset=UTF-8") | ||
| 275 | c.writeToWriter(content) | ||
| 276 | } | 212 | } |
| 277 | 213 | ||
| 278 | func (c *Controller) Input() url.Values { | 214 | func (c *Controller) Input() url.Values { |
| ... | @@ -313,6 +249,10 @@ func (c *Controller) GetBool(key string) (bool, error) { | ... | @@ -313,6 +249,10 @@ func (c *Controller) GetBool(key string) (bool, error) { |
| 313 | return strconv.ParseBool(c.Input().Get(key)) | 249 | return strconv.ParseBool(c.Input().Get(key)) |
| 314 | } | 250 | } |
| 315 | 251 | ||
| 252 | func (c *Controller) GetFloat(key string) (float64, error) { | ||
| 253 | return strconv.ParseFloat(c.Input().Get(key), 64) | ||
| 254 | } | ||
| 255 | |||
| 316 | func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) { | 256 | func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) { |
| 317 | return c.Ctx.Request.FormFile(key) | 257 | return c.Ctx.Request.FormFile(key) |
| 318 | } | 258 | } |
| ... | @@ -365,7 +305,7 @@ func (c *Controller) DestroySession() { | ... | @@ -365,7 +305,7 @@ func (c *Controller) DestroySession() { |
| 365 | } | 305 | } |
| 366 | 306 | ||
| 367 | func (c *Controller) IsAjax() bool { | 307 | func (c *Controller) IsAjax() bool { |
| 368 | return (c.Ctx.Request.Header.Get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest") | 308 | return c.Ctx.Input.IsAjax() |
| 369 | } | 309 | } |
| 370 | 310 | ||
| 371 | func (c *Controller) XsrfToken() string { | 311 | func (c *Controller) XsrfToken() string { | ... | ... |
filter.go
0 → 100644
| 1 | package beego | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "regexp" | ||
| 5 | ) | ||
| 6 | |||
| 7 | type FilterRouter struct { | ||
| 8 | pattern string | ||
| 9 | regex *regexp.Regexp | ||
| 10 | filterFunc FilterFunc | ||
| 11 | hasregex bool | ||
| 12 | } | ||
| 13 | |||
| 14 | func (mr *FilterRouter) ValidRouter(router string) bool { | ||
| 15 | if mr.pattern == "" { | ||
| 16 | return true | ||
| 17 | } | ||
| 18 | if router == mr.pattern { | ||
| 19 | return true | ||
| 20 | } | ||
| 21 | if mr.hasregex { | ||
| 22 | if mr.regex.MatchString(router) { | ||
| 23 | return true | ||
| 24 | } | ||
| 25 | matches := mr.regex.FindStringSubmatch(router) | ||
| 26 | if len(matches[0]) == len(router) { | ||
| 27 | return true | ||
| 28 | } | ||
| 29 | } | ||
| 30 | return false | ||
| 31 | } |
middleware/error.go
0 → 100644
| 1 | package middleware | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "html/template" | ||
| 6 | "net/http" | ||
| 7 | "runtime" | ||
| 8 | ) | ||
| 9 | |||
| 10 | var tpl = ` | ||
| 11 | <!DOCTYPE html> | ||
| 12 | <html> | ||
| 13 | <head> | ||
| 14 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
| 15 | <title>beego application error</title> | ||
| 16 | <style> | ||
| 17 | html, body, body * {padding: 0; margin: 0;} | ||
| 18 | #header {background:#ffd; border-bottom:solid 2px #A31515; padding: 20px 10px;} | ||
| 19 | #header h2{ } | ||
| 20 | #footer {border-top:solid 1px #aaa; padding: 5px 10px; font-size: 12px; color:green;} | ||
| 21 | #content {padding: 5px;} | ||
| 22 | #content .stack b{ font-size: 13px; color: red;} | ||
| 23 | #content .stack pre{padding-left: 10px;} | ||
| 24 | table {} | ||
| 25 | td.t {text-align: right; padding-right: 5px; color: #888;} | ||
| 26 | </style> | ||
| 27 | <script type="text/javascript"> | ||
| 28 | </script> | ||
| 29 | </head> | ||
| 30 | <body> | ||
| 31 | <div id="header"> | ||
| 32 | <h2>{{.AppError}}</h2> | ||
| 33 | </div> | ||
| 34 | <div id="content"> | ||
| 35 | <table> | ||
| 36 | <tr> | ||
| 37 | <td class="t">Request Method: </td><td>{{.RequestMethod}}</td> | ||
| 38 | </tr> | ||
| 39 | <tr> | ||
| 40 | <td class="t">Request URL: </td><td>{{.RequestURL}}</td> | ||
| 41 | </tr> | ||
| 42 | <tr> | ||
| 43 | <td class="t">RemoteAddr: </td><td>{{.RemoteAddr }}</td> | ||
| 44 | </tr> | ||
| 45 | </table> | ||
| 46 | <div class="stack"> | ||
| 47 | <b>Stack</b> | ||
| 48 | <pre>{{.Stack}}</pre> | ||
| 49 | </div> | ||
| 50 | </div> | ||
| 51 | <div id="footer"> | ||
| 52 | <p>beego {{ .BeegoVersion }} (beego framework)</p> | ||
| 53 | <p>golang version: {{.GoVersion}}</p> | ||
| 54 | </div> | ||
| 55 | </body> | ||
| 56 | </html> | ||
| 57 | ` | ||
| 58 | |||
| 59 | func ShowErr(err interface{}, rw http.ResponseWriter, r *http.Request, Stack string) { | ||
| 60 | t, _ := template.New("beegoerrortemp").Parse(tpl) | ||
| 61 | data := make(map[string]string) | ||
| 62 | data["AppError"] = AppName + ":" + fmt.Sprint(err) | ||
| 63 | data["RequestMethod"] = r.Method | ||
| 64 | data["RequestURL"] = r.RequestURI | ||
| 65 | data["RemoteAddr"] = r.RemoteAddr | ||
| 66 | data["Stack"] = Stack | ||
| 67 | data["BeegoVersion"] = VERSION | ||
| 68 | data["GoVersion"] = runtime.Version() | ||
| 69 | t.Execute(rw, data) | ||
| 70 | } | ||
| 71 | |||
| 72 | var errtpl = ` | ||
| 73 | <!DOCTYPE html> | ||
| 74 | <html lang="en"> | ||
| 75 | <head> | ||
| 76 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
| 77 | <title>{{.Title}}</title> | ||
| 78 | <style type="text/css"> | ||
| 79 | * { | ||
| 80 | margin:0; | ||
| 81 | padding:0; | ||
| 82 | } | ||
| 83 | |||
| 84 | body { | ||
| 85 | background-color:#EFEFEF; | ||
| 86 | font: .9em "Lucida Sans Unicode", "Lucida Grande", sans-serif; | ||
| 87 | } | ||
| 88 | |||
| 89 | #wrapper{ | ||
| 90 | width:600px; | ||
| 91 | margin:40px auto 0; | ||
| 92 | text-align:center; | ||
| 93 | -moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.3); | ||
| 94 | -webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.3); | ||
| 95 | box-shadow: 5px 5px 10px rgba(0,0,0,0.3); | ||
| 96 | } | ||
| 97 | |||
| 98 | #wrapper h1{ | ||
| 99 | color:#FFF; | ||
| 100 | text-align:center; | ||
| 101 | margin-bottom:20px; | ||
| 102 | } | ||
| 103 | |||
| 104 | #wrapper a{ | ||
| 105 | display:block; | ||
| 106 | font-size:.9em; | ||
| 107 | padding-top:20px; | ||
| 108 | color:#FFF; | ||
| 109 | text-decoration:none; | ||
| 110 | text-align:center; | ||
| 111 | } | ||
| 112 | |||
| 113 | #container { | ||
| 114 | width:600px; | ||
| 115 | padding-bottom:15px; | ||
| 116 | background-color:#FFFFFF; | ||
| 117 | } | ||
| 118 | |||
| 119 | .navtop{ | ||
| 120 | height:40px; | ||
| 121 | background-color:#24B2EB; | ||
| 122 | padding:13px; | ||
| 123 | } | ||
| 124 | |||
| 125 | .content { | ||
| 126 | padding:10px 10px 25px; | ||
| 127 | background: #FFFFFF; | ||
| 128 | margin:; | ||
| 129 | color:#333; | ||
| 130 | } | ||
| 131 | |||
| 132 | a.button{ | ||
| 133 | color:white; | ||
| 134 | padding:15px 20px; | ||
| 135 | text-shadow:1px 1px 0 #00A5FF; | ||
| 136 | font-weight:bold; | ||
| 137 | text-align:center; | ||
| 138 | border:1px solid #24B2EB; | ||
| 139 | margin:0px 200px; | ||
| 140 | clear:both; | ||
| 141 | background-color: #24B2EB; | ||
| 142 | border-radius:100px; | ||
| 143 | -moz-border-radius:100px; | ||
| 144 | -webkit-border-radius:100px; | ||
| 145 | } | ||
| 146 | |||
| 147 | a.button:hover{ | ||
| 148 | text-decoration:none; | ||
| 149 | background-color: #24B2EB; | ||
| 150 | } | ||
| 151 | |||
| 152 | </style> | ||
| 153 | </head> | ||
| 154 | <body> | ||
| 155 | <div id="wrapper"> | ||
| 156 | <div id="container"> | ||
| 157 | <div class="navtop"> | ||
| 158 | <h1>{{.Title}}</h1> | ||
| 159 | </div> | ||
| 160 | <div id="content"> | ||
| 161 | {{.Content}} | ||
| 162 | <a href="/" title="Home" class="button">Go Home</a><br /> | ||
| 163 | |||
| 164 | <br>power by beego {{.BeegoVersion}} | ||
| 165 | </div> | ||
| 166 | </div> | ||
| 167 | </div> | ||
| 168 | </body> | ||
| 169 | </html> | ||
| 170 | ` | ||
| 171 | |||
| 172 | var ErrorMaps map[string]http.HandlerFunc | ||
| 173 | |||
| 174 | func init() { | ||
| 175 | ErrorMaps = make(map[string]http.HandlerFunc) | ||
| 176 | } | ||
| 177 | |||
| 178 | //404 | ||
| 179 | func NotFound(rw http.ResponseWriter, r *http.Request) { | ||
| 180 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | ||
| 181 | data := make(map[string]interface{}) | ||
| 182 | data["Title"] = "Page Not Found" | ||
| 183 | data["Content"] = template.HTML("<br>The Page You have requested flown the coop." + | ||
| 184 | "<br>Perhaps you are here because:" + | ||
| 185 | "<br><br><ul>" + | ||
| 186 | "<br>The page has moved" + | ||
| 187 | "<br>The page no longer exists" + | ||
| 188 | "<br>You were looking for your puppy and got lost" + | ||
| 189 | "<br>You like 404 pages" + | ||
| 190 | "</ul>") | ||
| 191 | data["BeegoVersion"] = VERSION | ||
| 192 | rw.WriteHeader(http.StatusNotFound) | ||
| 193 | t.Execute(rw, data) | ||
| 194 | } | ||
| 195 | |||
| 196 | //401 | ||
| 197 | func Unauthorized(rw http.ResponseWriter, r *http.Request) { | ||
| 198 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | ||
| 199 | data := make(map[string]interface{}) | ||
| 200 | data["Title"] = "Unauthorized" | ||
| 201 | data["Content"] = template.HTML("<br>The Page You have requested can't authorized." + | ||
| 202 | "<br>Perhaps you are here because:" + | ||
| 203 | "<br><br><ul>" + | ||
| 204 | "<br>Check the credentials that you supplied" + | ||
| 205 | "<br>Check the address for errors" + | ||
| 206 | "</ul>") | ||
| 207 | data["BeegoVersion"] = VERSION | ||
| 208 | rw.WriteHeader(http.StatusUnauthorized) | ||
| 209 | t.Execute(rw, data) | ||
| 210 | } | ||
| 211 | |||
| 212 | //403 | ||
| 213 | func Forbidden(rw http.ResponseWriter, r *http.Request) { | ||
| 214 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | ||
| 215 | data := make(map[string]interface{}) | ||
| 216 | data["Title"] = "Forbidden" | ||
| 217 | data["Content"] = template.HTML("<br>The Page You have requested forbidden." + | ||
| 218 | "<br>Perhaps you are here because:" + | ||
| 219 | "<br><br><ul>" + | ||
| 220 | "<br>Your address may be blocked" + | ||
| 221 | "<br>The site may be disabled" + | ||
| 222 | "<br>You need to log in" + | ||
| 223 | "</ul>") | ||
| 224 | data["BeegoVersion"] = VERSION | ||
| 225 | rw.WriteHeader(http.StatusForbidden) | ||
| 226 | t.Execute(rw, data) | ||
| 227 | } | ||
| 228 | |||
| 229 | //503 | ||
| 230 | func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { | ||
| 231 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | ||
| 232 | data := make(map[string]interface{}) | ||
| 233 | data["Title"] = "Service Unavailable" | ||
| 234 | data["Content"] = template.HTML("<br>The Page You have requested unavailable." + | ||
| 235 | "<br>Perhaps you are here because:" + | ||
| 236 | "<br><br><ul>" + | ||
| 237 | "<br><br>The page is overloaded" + | ||
| 238 | "<br>Please try again later." + | ||
| 239 | "</ul>") | ||
| 240 | data["BeegoVersion"] = VERSION | ||
| 241 | rw.WriteHeader(http.StatusServiceUnavailable) | ||
| 242 | t.Execute(rw, data) | ||
| 243 | } | ||
| 244 | |||
| 245 | //500 | ||
| 246 | func InternalServerError(rw http.ResponseWriter, r *http.Request) { | ||
| 247 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | ||
| 248 | data := make(map[string]interface{}) | ||
| 249 | data["Title"] = "Internal Server Error" | ||
| 250 | data["Content"] = template.HTML("<br>The Page You have requested has down now." + | ||
| 251 | "<br><br><ul>" + | ||
| 252 | "<br>simply try again later" + | ||
| 253 | "<br>you should report the fault to the website administrator" + | ||
| 254 | "</ul>") | ||
| 255 | data["BeegoVersion"] = VERSION | ||
| 256 | rw.WriteHeader(http.StatusInternalServerError) | ||
| 257 | t.Execute(rw, data) | ||
| 258 | } | ||
| 259 | |||
| 260 | func registerErrorHander() { | ||
| 261 | if _, ok := ErrorMaps["404"]; !ok { | ||
| 262 | ErrorMaps["404"] = NotFound | ||
| 263 | } | ||
| 264 | |||
| 265 | if _, ok := ErrorMaps["401"]; !ok { | ||
| 266 | ErrorMaps["401"] = Unauthorized | ||
| 267 | } | ||
| 268 | |||
| 269 | if _, ok := ErrorMaps["403"]; !ok { | ||
| 270 | ErrorMaps["403"] = Forbidden | ||
| 271 | } | ||
| 272 | |||
| 273 | if _, ok := ErrorMaps["503"]; !ok { | ||
| 274 | ErrorMaps["503"] = ServiceUnavailable | ||
| 275 | } | ||
| 276 | |||
| 277 | if _, ok := ErrorMaps["500"]; !ok { | ||
| 278 | ErrorMaps["500"] = InternalServerError | ||
| 279 | } | ||
| 280 | } |
middleware/i18n.go
0 → 100644
| 1 | package middleware | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
middleware/profile.go
0 → 100644
| 1 | package middleware | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "log" | ||
| 6 | "os" | ||
| 7 | "runtime" | ||
| 8 | "runtime/debug" | ||
| 9 | "runtime/pprof" | ||
| 10 | "strconv" | ||
| 11 | "sync/atomic" | ||
| 12 | "time" | ||
| 13 | ) | ||
| 14 | |||
| 15 | var heapProfileCounter int32 | ||
| 16 | var startTime = time.Now() | ||
| 17 | var pid int | ||
| 18 | |||
| 19 | func init() { | ||
| 20 | pid = os.Getpid() | ||
| 21 | } | ||
| 22 | |||
| 23 | func StartCPUProfile() { | ||
| 24 | f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof") | ||
| 25 | if err != nil { | ||
| 26 | log.Fatal(err) | ||
| 27 | } | ||
| 28 | pprof.StartCPUProfile(f) | ||
| 29 | } | ||
| 30 | |||
| 31 | func StopCPUProfile() { | ||
| 32 | pprof.StopCPUProfile() | ||
| 33 | } | ||
| 34 | |||
| 35 | func StartBlockProfile(rate int) { | ||
| 36 | runtime.SetBlockProfileRate(rate) | ||
| 37 | } | ||
| 38 | |||
| 39 | func StopBlockProfile() { | ||
| 40 | filename := "block-" + strconv.Itoa(pid) + ".pprof" | ||
| 41 | f, err := os.Create(filename) | ||
| 42 | if err != nil { | ||
| 43 | log.Fatal(err) | ||
| 44 | } | ||
| 45 | if err = pprof.Lookup("block").WriteTo(f, 0); err != nil { | ||
| 46 | log.Fatalf(" can't write %s: %s", filename, err) | ||
| 47 | } | ||
| 48 | f.Close() | ||
| 49 | } | ||
| 50 | |||
| 51 | func SetMemProfileRate(rate int) { | ||
| 52 | runtime.MemProfileRate = rate | ||
| 53 | } | ||
| 54 | |||
| 55 | func GC() { | ||
| 56 | runtime.GC() | ||
| 57 | } | ||
| 58 | |||
| 59 | func DumpHeap() { | ||
| 60 | filename := "heap-" + strconv.Itoa(pid) + "-" + strconv.Itoa(int(atomic.AddInt32(&heapProfileCounter, 1))) + ".pprof" | ||
| 61 | f, err := os.Create(filename) | ||
| 62 | if err != nil { | ||
| 63 | fmt.Fprintf(os.Stderr, "testing: %s", err) | ||
| 64 | return | ||
| 65 | } | ||
| 66 | if err = pprof.WriteHeapProfile(f); err != nil { | ||
| 67 | fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", filename, err) | ||
| 68 | } | ||
| 69 | f.Close() | ||
| 70 | } | ||
| 71 | |||
| 72 | //func showSystemStat(interval time.Duration, count int) { | ||
| 73 | |||
| 74 | // usage1 := &syscall.Rusage{} | ||
| 75 | // var lastUtime int64 | ||
| 76 | // var lastStime int64 | ||
| 77 | |||
| 78 | // counter := 0 | ||
| 79 | // for { | ||
| 80 | |||
| 81 | // //http://man7.org/linux/man-pages/man3/vtimes.3.html | ||
| 82 | // syscall.Getrusage(syscall.RUSAGE_SELF, usage1) | ||
| 83 | |||
| 84 | // utime := (usage1.Utime.Sec * 1000000000) + int64(usage1.Utime.Usec) | ||
| 85 | // stime := (usage1.Stime.Sec * 1000000000) + int64(usage1.Stime.Usec) | ||
| 86 | // userCPUUtil := float64(utime-lastUtime) * 100 / float64(interval) | ||
| 87 | // sysCPUUtil := float64(stime-lastStime) * 100 / float64(interval) | ||
| 88 | // memUtil := usage1.Maxrss * 1024 | ||
| 89 | |||
| 90 | // lastUtime = utime | ||
| 91 | // lastStime = stime | ||
| 92 | |||
| 93 | // if counter > 0 { | ||
| 94 | // fmt.Printf("cpu: %3.2f%% us %3.2f%% sy, mem:%s \n", userCPUUtil, sysCPUUtil, toH(uint64(memUtil))) | ||
| 95 | // } | ||
| 96 | |||
| 97 | // counter += 1 | ||
| 98 | // if count >= 1 && count < counter { | ||
| 99 | // return | ||
| 100 | // } | ||
| 101 | // time.Sleep(interval) | ||
| 102 | // } | ||
| 103 | |||
| 104 | //} | ||
| 105 | |||
| 106 | //func ShowSystemStat(seconds int) { | ||
| 107 | // go func() { | ||
| 108 | // interval := time.Duration(seconds) * time.Second | ||
| 109 | // showSystemStat(interval, 0) | ||
| 110 | // }() | ||
| 111 | //} | ||
| 112 | |||
| 113 | //func PrintSystemStats() { | ||
| 114 | // interval := time.Duration(1) * time.Second | ||
| 115 | // showSystemStat(interval, 1) | ||
| 116 | //} | ||
| 117 | |||
| 118 | func ShowGCStat() { | ||
| 119 | go func() { | ||
| 120 | var numGC int64 | ||
| 121 | |||
| 122 | interval := time.Duration(100) * time.Millisecond | ||
| 123 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} | ||
| 124 | memStats := &runtime.MemStats{} | ||
| 125 | for { | ||
| 126 | debug.ReadGCStats(gcstats) | ||
| 127 | if gcstats.NumGC > numGC { | ||
| 128 | runtime.ReadMemStats(memStats) | ||
| 129 | |||
| 130 | printGC(memStats, gcstats) | ||
| 131 | numGC = gcstats.NumGC | ||
| 132 | } | ||
| 133 | time.Sleep(interval) | ||
| 134 | } | ||
| 135 | }() | ||
| 136 | } | ||
| 137 | |||
| 138 | func PrintGCSummary() { | ||
| 139 | memStats := &runtime.MemStats{} | ||
| 140 | runtime.ReadMemStats(memStats) | ||
| 141 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} | ||
| 142 | debug.ReadGCStats(gcstats) | ||
| 143 | |||
| 144 | printGC(memStats, gcstats) | ||
| 145 | } | ||
| 146 | |||
| 147 | func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) { | ||
| 148 | |||
| 149 | if gcstats.NumGC > 0 { | ||
| 150 | lastPause := gcstats.Pause[0] | ||
| 151 | elapsed := time.Now().Sub(startTime) | ||
| 152 | overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100 | ||
| 153 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 154 | |||
| 155 | 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", | ||
| 156 | gcstats.NumGC, | ||
| 157 | toS(lastPause), | ||
| 158 | toS(avg(gcstats.Pause)), | ||
| 159 | overhead, | ||
| 160 | toH(memStats.Alloc), | ||
| 161 | toH(memStats.Sys), | ||
| 162 | toH(uint64(allocatedRate)), | ||
| 163 | toS(gcstats.PauseQuantiles[94]), | ||
| 164 | toS(gcstats.PauseQuantiles[98]), | ||
| 165 | toS(gcstats.PauseQuantiles[99])) | ||
| 166 | } else { | ||
| 167 | // while GC has disabled | ||
| 168 | elapsed := time.Now().Sub(startTime) | ||
| 169 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 170 | |||
| 171 | fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n", | ||
| 172 | toH(memStats.Alloc), | ||
| 173 | toH(memStats.Sys), | ||
| 174 | toH(uint64(allocatedRate))) | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | func avg(items []time.Duration) time.Duration { | ||
| 179 | var sum time.Duration | ||
| 180 | for _, item := range items { | ||
| 181 | sum += item | ||
| 182 | } | ||
| 183 | return time.Duration(int64(sum) / int64(len(items))) | ||
| 184 | } | ||
| 185 | |||
| 186 | // human readable format | ||
| 187 | func toH(bytes uint64) string { | ||
| 188 | switch { | ||
| 189 | case bytes < 1024: | ||
| 190 | return fmt.Sprintf("%dB", bytes) | ||
| 191 | case bytes < 1024*1024: | ||
| 192 | return fmt.Sprintf("%.2fK", float64(bytes)/1024) | ||
| 193 | case bytes < 1024*1024*1024: | ||
| 194 | return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) | ||
| 195 | default: | ||
| 196 | return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | // short string format | ||
| 201 | func toS(d time.Duration) string { | ||
| 202 | |||
| 203 | u := uint64(d) | ||
| 204 | if u < uint64(time.Second) { | ||
| 205 | switch { | ||
| 206 | case u == 0: | ||
| 207 | return "0" | ||
| 208 | case u < uint64(time.Microsecond): | ||
| 209 | return fmt.Sprintf("%.2fns", float64(u)) | ||
| 210 | case u < uint64(time.Millisecond): | ||
| 211 | return fmt.Sprintf("%.2fus", float64(u)/1000) | ||
| 212 | default: | ||
| 213 | return fmt.Sprintf("%.2fms", float64(u)/1000/1000) | ||
| 214 | } | ||
| 215 | } else { | ||
| 216 | switch { | ||
| 217 | case u < uint64(time.Minute): | ||
| 218 | return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000) | ||
| 219 | case u < uint64(time.Hour): | ||
| 220 | return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60) | ||
| 221 | default: | ||
| 222 | return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60) | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | } |
middleware/router.go
deleted
100644 → 0
File mode changed
middleware/session.go
0 → 100644
| 1 | package middleware | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "github.com/astaxie/beego/session" | ||
| 5 | ) | ||
| 6 | |||
| 7 | var ( | ||
| 8 | GlobalSessions *session.Manager | ||
| 9 | ) | ||
| 10 | |||
| 11 | func StartSession(provideName, cookieName string, maxlifetime int64, savePath string) { | ||
| 12 | GlobalSessions, _ = session.NewManager(provideName, cookieName, maxlifetime, savePath) | ||
| 13 | go GlobalSessions.GC() | ||
| 14 | } |
pprof.go
deleted
100644 → 0
| 1 | package beego | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "net/http/pprof" | ||
| 5 | ) | ||
| 6 | |||
| 7 | type ProfController struct { | ||
| 8 | Controller | ||
| 9 | } | ||
| 10 | |||
| 11 | func (this *ProfController) Get() { | ||
| 12 | switch this.Ctx.Params[":pp"] { | ||
| 13 | default: | ||
| 14 | pprof.Index(this.Ctx.ResponseWriter, this.Ctx.Request) | ||
| 15 | case "": | ||
| 16 | pprof.Index(this.Ctx.ResponseWriter, this.Ctx.Request) | ||
| 17 | case "cmdline": | ||
| 18 | pprof.Cmdline(this.Ctx.ResponseWriter, this.Ctx.Request) | ||
| 19 | case "profile": | ||
| 20 | pprof.Profile(this.Ctx.ResponseWriter, this.Ctx.Request) | ||
| 21 | case "symbol": | ||
| 22 | pprof.Symbol(this.Ctx.ResponseWriter, this.Ctx.Request) | ||
| 23 | } | ||
| 24 | this.Ctx.ResponseWriter.WriteHeader(200) | ||
| 25 | } |
| 1 | package beego | 1 | package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "bytes" | ||
| 5 | "fmt" | 4 | "fmt" |
| 6 | "io/ioutil" | 5 | beecontext "github.com/astaxie/beego/context" |
| 7 | "net/http" | 6 | "net/http" |
| 8 | "net/url" | 7 | "net/url" |
| 9 | "os" | 8 | "os" |
| ... | @@ -25,31 +24,20 @@ type controllerInfo struct { | ... | @@ -25,31 +24,20 @@ type controllerInfo struct { |
| 25 | hasMethod bool | 24 | hasMethod bool |
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | type userHandler struct { | ||
| 29 | pattern string | ||
| 30 | regex *regexp.Regexp | ||
| 31 | params map[int]string | ||
| 32 | h http.Handler | ||
| 33 | } | ||
| 34 | |||
| 35 | type ControllerRegistor struct { | 27 | type ControllerRegistor struct { |
| 36 | routers []*controllerInfo | 28 | routers []*controllerInfo |
| 37 | fixrouters []*controllerInfo | 29 | fixrouters []*controllerInfo |
| 38 | enableFilter bool | 30 | enableFilter bool |
| 39 | filters []http.HandlerFunc | 31 | filters map[string][]*FilterRouter |
| 40 | enableAfter bool | ||
| 41 | afterFilters []http.HandlerFunc | ||
| 42 | enableUser bool | ||
| 43 | userHandlers map[string]*userHandler | ||
| 44 | enableAuto bool | 32 | enableAuto bool |
| 45 | autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type | 33 | autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type |
| 46 | } | 34 | } |
| 47 | 35 | ||
| 48 | func NewControllerRegistor() *ControllerRegistor { | 36 | func NewControllerRegistor() *ControllerRegistor { |
| 49 | return &ControllerRegistor{ | 37 | return &ControllerRegistor{ |
| 50 | routers: make([]*controllerInfo, 0), | 38 | routers: make([]*controllerInfo, 0), |
| 51 | userHandlers: make(map[string]*userHandler), | 39 | autoRouter: make(map[string]map[string]reflect.Type), |
| 52 | autoRouter: make(map[string]map[string]reflect.Type), | 40 | filters: make(map[string][]*FilterRouter), |
| 53 | } | 41 | } |
| 54 | } | 42 | } |
| 55 | 43 | ||
| ... | @@ -182,35 +170,39 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { | ... | @@ -182,35 +170,39 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { |
| 182 | } | 170 | } |
| 183 | } | 171 | } |
| 184 | 172 | ||
| 185 | func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { | 173 | // Filter adds the middleware filter. |
| 186 | p.enableUser = true | 174 | func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { |
| 187 | parts := strings.Split(pattern, "/") | 175 | p.enableFilter = true |
| 176 | mr := new(FilterRouter) | ||
| 177 | mr.filterFunc = filter | ||
| 188 | 178 | ||
| 179 | parts := strings.Split(pattern, "/") | ||
| 189 | j := 0 | 180 | j := 0 |
| 190 | params := make(map[int]string) | ||
| 191 | for i, part := range parts { | 181 | for i, part := range parts { |
| 192 | if strings.HasPrefix(part, ":") { | 182 | if strings.HasPrefix(part, ":") { |
| 193 | expr := "([^/]+)" | 183 | expr := "(.+)" |
| 194 | //a user may choose to override the defult expression | 184 | //a user may choose to override the defult expression |
| 195 | // similar to expressjs: ‘/user/:id([0-9]+)’ | 185 | // similar to expressjs: ‘/user/:id([0-9]+)’ |
| 196 | if index := strings.Index(part, "("); index != -1 { | 186 | if index := strings.Index(part, "("); index != -1 { |
| 197 | expr = part[index:] | 187 | expr = part[index:] |
| 198 | part = part[:index] | 188 | part = part[:index] |
| 189 | //match /user/:id:int ([0-9]+) | ||
| 190 | //match /post/:username:string ([\w]+) | ||
| 191 | } else if lindex := strings.LastIndex(part, ":"); lindex != 0 { | ||
| 192 | switch part[lindex:] { | ||
| 193 | case ":int": | ||
| 194 | expr = "([0-9]+)" | ||
| 195 | part = part[:lindex] | ||
| 196 | case ":string": | ||
| 197 | expr = `([\w]+)` | ||
| 198 | part = part[:lindex] | ||
| 199 | } | ||
| 199 | } | 200 | } |
| 200 | params[j] = part | ||
| 201 | parts[i] = expr | 201 | parts[i] = expr |
| 202 | j++ | 202 | j++ |
| 203 | } | 203 | } |
| 204 | } | 204 | } |
| 205 | if j == 0 { | 205 | if j != 0 { |
| 206 | //now create the Route | ||
| 207 | uh := &userHandler{} | ||
| 208 | uh.pattern = pattern | ||
| 209 | uh.h = c | ||
| 210 | p.userHandlers[pattern] = uh | ||
| 211 | } else { // add regexp routers | ||
| 212 | //recreate the url pattern, with parameters replaced | ||
| 213 | //by regular expressions. then compile the regex | ||
| 214 | pattern = strings.Join(parts, "/") | 206 | pattern = strings.Join(parts, "/") |
| 215 | regex, regexErr := regexp.Compile(pattern) | 207 | regex, regexErr := regexp.Compile(pattern) |
| 216 | if regexErr != nil { | 208 | if regexErr != nil { |
| ... | @@ -218,73 +210,11 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { | ... | @@ -218,73 +210,11 @@ func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) { |
| 218 | panic(regexErr) | 210 | panic(regexErr) |
| 219 | return | 211 | return |
| 220 | } | 212 | } |
| 221 | 213 | mr.regex = regex | |
| 222 | //now create the Route | 214 | mr.hasregex = true |
| 223 | uh := &userHandler{} | ||
| 224 | uh.regex = regex | ||
| 225 | uh.params = params | ||
| 226 | uh.pattern = pattern | ||
| 227 | uh.h = c | ||
| 228 | p.userHandlers[pattern] = uh | ||
| 229 | } | 215 | } |
| 230 | } | 216 | mr.pattern = pattern |
| 231 | 217 | p.filters[action] = append(p.filters[action], mr) | |
| 232 | // Filter adds the middleware filter. | ||
| 233 | func (p *ControllerRegistor) Filter(filter http.HandlerFunc) { | ||
| 234 | p.enableFilter = true | ||
| 235 | p.filters = append(p.filters, filter) | ||
| 236 | } | ||
| 237 | |||
| 238 | // FilterParam adds the middleware filter if the REST URL parameter exists. | ||
| 239 | func (p *ControllerRegistor) FilterParam(param string, filter http.HandlerFunc) { | ||
| 240 | if !strings.HasPrefix(param, ":") { | ||
| 241 | param = ":" + param | ||
| 242 | } | ||
| 243 | |||
| 244 | p.Filter(func(w http.ResponseWriter, r *http.Request) { | ||
| 245 | p := r.URL.Query().Get(param) | ||
| 246 | if len(p) > 0 { | ||
| 247 | filter(w, r) | ||
| 248 | } | ||
| 249 | }) | ||
| 250 | } | ||
| 251 | |||
| 252 | // FilterPrefixPath adds the middleware filter if the prefix path exists. | ||
| 253 | func (p *ControllerRegistor) FilterPrefixPath(path string, filter http.HandlerFunc) { | ||
| 254 | p.Filter(func(w http.ResponseWriter, r *http.Request) { | ||
| 255 | if strings.HasPrefix(r.URL.Path, path) { | ||
| 256 | filter(w, r) | ||
| 257 | } | ||
| 258 | }) | ||
| 259 | } | ||
| 260 | |||
| 261 | // Filter adds the middleware after filter. | ||
| 262 | func (p *ControllerRegistor) FilterAfter(filter http.HandlerFunc) { | ||
| 263 | p.enableAfter = true | ||
| 264 | p.afterFilters = append(p.afterFilters, filter) | ||
| 265 | } | ||
| 266 | |||
| 267 | // FilterParam adds the middleware filter if the REST URL parameter exists. | ||
| 268 | func (p *ControllerRegistor) FilterParamAfter(param string, filter http.HandlerFunc) { | ||
| 269 | if !strings.HasPrefix(param, ":") { | ||
| 270 | param = ":" + param | ||
| 271 | } | ||
| 272 | |||
| 273 | p.FilterAfter(func(w http.ResponseWriter, r *http.Request) { | ||
| 274 | p := r.URL.Query().Get(param) | ||
| 275 | if len(p) > 0 { | ||
| 276 | filter(w, r) | ||
| 277 | } | ||
| 278 | }) | ||
| 279 | } | ||
| 280 | |||
| 281 | // FilterPrefixPath adds the middleware filter if the prefix path exists. | ||
| 282 | func (p *ControllerRegistor) FilterPrefixPathAfter(path string, filter http.HandlerFunc) { | ||
| 283 | p.FilterAfter(func(w http.ResponseWriter, r *http.Request) { | ||
| 284 | if strings.HasPrefix(r.URL.Path, path) { | ||
| 285 | filter(w, r) | ||
| 286 | } | ||
| 287 | }) | ||
| 288 | } | 218 | } |
| 289 | 219 | ||
| 290 | // AutoRoute | 220 | // AutoRoute |
| ... | @@ -320,13 +250,30 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -320,13 +250,30 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 320 | }() | 250 | }() |
| 321 | 251 | ||
| 322 | w := &responseWriter{writer: rw} | 252 | w := &responseWriter{writer: rw} |
| 323 | |||
| 324 | w.Header().Set("Server", "beegoServer") | 253 | w.Header().Set("Server", "beegoServer") |
| 254 | context := &beecontext.Context{ | ||
| 255 | ResponseWriter: w, | ||
| 256 | Request: r, | ||
| 257 | Input: beecontext.NewInput(r), | ||
| 258 | Output: beecontext.NewOutput(w), | ||
| 259 | } | ||
| 260 | context.Output.Context = context | ||
| 325 | var runrouter *controllerInfo | 261 | var runrouter *controllerInfo |
| 326 | var findrouter bool | 262 | var findrouter bool |
| 327 | 263 | ||
| 328 | params := make(map[string]string) | 264 | params := make(map[string]string) |
| 329 | 265 | ||
| 266 | context.Input.Param = params | ||
| 267 | if p.enableFilter { | ||
| 268 | if l, ok := p.filters["BeforRouter"]; ok { | ||
| 269 | for _, filterR := range l { | ||
| 270 | if filterR.ValidRouter(r.URL.Path) { | ||
| 271 | filterR.filterFunc(context) | ||
| 272 | } | ||
| 273 | } | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 330 | //static file server | 277 | //static file server |
| 331 | for prefix, staticDir := range StaticDir { | 278 | for prefix, staticDir := range StaticDir { |
| 332 | if r.URL.Path == "/favicon.ico" { | 279 | if r.URL.Path == "/favicon.ico" { |
| ... | @@ -359,62 +306,23 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -359,62 +306,23 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 359 | } | 306 | } |
| 360 | } | 307 | } |
| 361 | 308 | ||
| 309 | if p.enableFilter { | ||
| 310 | if l, ok := p.filters["AfterStatic"]; ok { | ||
| 311 | for _, filterR := range l { | ||
| 312 | if filterR.ValidRouter(r.URL.Path) { | ||
| 313 | filterR.filterFunc(context) | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | ||
| 317 | } | ||
| 362 | requestPath := r.URL.Path | 318 | requestPath := r.URL.Path |
| 363 | 319 | ||
| 364 | var requestbody []byte | ||
| 365 | |||
| 366 | if CopyRequestBody { | 320 | if CopyRequestBody { |
| 367 | requestbody, _ = ioutil.ReadAll(r.Body) | 321 | context.Input.Body() |
| 368 | |||
| 369 | r.Body.Close() | ||
| 370 | |||
| 371 | bf := bytes.NewBuffer(requestbody) | ||
| 372 | |||
| 373 | r.Body = ioutil.NopCloser(bf) | ||
| 374 | } | 322 | } |
| 375 | 323 | ||
| 376 | r.ParseMultipartForm(MaxMemory) | 324 | r.ParseMultipartForm(MaxMemory) |
| 377 | 325 | ||
| 378 | //user defined Handler | ||
| 379 | if p.enableUser { | ||
| 380 | for pattern, c := range p.userHandlers { | ||
| 381 | if c.regex == nil && pattern == requestPath { | ||
| 382 | c.h.ServeHTTP(rw, r) | ||
| 383 | return | ||
| 384 | } else if c.regex == nil { | ||
| 385 | continue | ||
| 386 | } | ||
| 387 | |||
| 388 | //check if Route pattern matches url | ||
| 389 | if !c.regex.MatchString(requestPath) { | ||
| 390 | continue | ||
| 391 | } | ||
| 392 | |||
| 393 | //get submatches (params) | ||
| 394 | matches := c.regex.FindStringSubmatch(requestPath) | ||
| 395 | |||
| 396 | //double check that the Route matches the URL pattern. | ||
| 397 | if len(matches[0]) != len(requestPath) { | ||
| 398 | continue | ||
| 399 | } | ||
| 400 | |||
| 401 | if len(c.params) > 0 { | ||
| 402 | //add url parameters to the query param map | ||
| 403 | values := r.URL.Query() | ||
| 404 | for i, match := range matches[1:] { | ||
| 405 | values.Add(c.params[i], match) | ||
| 406 | r.Form.Add(c.params[i], match) | ||
| 407 | params[c.params[i]] = match | ||
| 408 | } | ||
| 409 | //reassemble query params and add to RawQuery | ||
| 410 | r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery | ||
| 411 | //r.URL.RawQuery = url.Values(values).Encode() | ||
| 412 | } | ||
| 413 | c.h.ServeHTTP(rw, r) | ||
| 414 | return | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | //first find path from the fixrouters to Improve Performance | 326 | //first find path from the fixrouters to Improve Performance |
| 419 | for _, route := range p.fixrouters { | 327 | for _, route := range p.fixrouters { |
| 420 | n := len(requestPath) | 328 | n := len(requestPath) |
| ... | @@ -471,23 +379,21 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -471,23 +379,21 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 471 | if runrouter != nil { | 379 | if runrouter != nil { |
| 472 | //execute middleware filters | 380 | //execute middleware filters |
| 473 | if p.enableFilter { | 381 | if p.enableFilter { |
| 474 | for _, filter := range p.filters { | 382 | if l, ok := p.filters["BeforExec"]; ok { |
| 475 | filter(w, r) | 383 | for _, filterR := range l { |
| 476 | if w.started { | 384 | if filterR.ValidRouter(r.URL.Path) { |
| 477 | return | 385 | filterR.filterFunc(context) |
| 386 | } | ||
| 478 | } | 387 | } |
| 479 | } | 388 | } |
| 480 | } | 389 | } |
| 481 | |||
| 482 | //Invoke the request handler | 390 | //Invoke the request handler |
| 483 | vc := reflect.New(runrouter.controllerType) | 391 | vc := reflect.New(runrouter.controllerType) |
| 484 | 392 | ||
| 485 | //call the controller init function | 393 | //call the controller init function |
| 486 | init := vc.MethodByName("Init") | 394 | init := vc.MethodByName("Init") |
| 487 | in := make([]reflect.Value, 2) | 395 | in := make([]reflect.Value, 2) |
| 488 | ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody} | 396 | in[0] = reflect.ValueOf(context) |
| 489 | |||
| 490 | in[0] = reflect.ValueOf(ct) | ||
| 491 | in[1] = reflect.ValueOf(runrouter.controllerType.Name()) | 397 | in[1] = reflect.ValueOf(runrouter.controllerType.Name()) |
| 492 | init.Call(in) | 398 | init.Call(in) |
| 493 | //call prepare function | 399 | //call prepare function |
| ... | @@ -617,14 +523,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -617,14 +523,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 617 | } | 523 | } |
| 618 | } | 524 | } |
| 619 | } | 525 | } |
| 526 | |||
| 620 | method = vc.MethodByName("Finish") | 527 | method = vc.MethodByName("Finish") |
| 621 | method.Call(in) | 528 | method.Call(in) |
| 622 | //execute middleware filters | 529 | //execute middleware filters |
| 623 | if p.enableAfter { | 530 | if p.enableFilter { |
| 624 | for _, filter := range p.afterFilters { | 531 | if l, ok := p.filters["AfterExec"]; ok { |
| 625 | filter(w, r) | 532 | for _, filterR := range l { |
| 626 | if w.started { | 533 | if filterR.ValidRouter(r.URL.Path) { |
| 627 | return | 534 | filterR.filterFunc(context) |
| 535 | } | ||
| 628 | } | 536 | } |
| 629 | } | 537 | } |
| 630 | } | 538 | } |
| ... | @@ -651,10 +559,11 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -651,10 +559,11 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 651 | if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) { | 559 | if strings.HasPrefix(strings.ToLower(requestPath), "/"+cName+"/"+strings.ToLower(mName)) { |
| 652 | //execute middleware filters | 560 | //execute middleware filters |
| 653 | if p.enableFilter { | 561 | if p.enableFilter { |
| 654 | for _, filter := range p.filters { | 562 | if l, ok := p.filters["BeforExec"]; ok { |
| 655 | filter(w, r) | 563 | for _, filterR := range l { |
| 656 | if w.started { | 564 | if filterR.ValidRouter(r.URL.Path) { |
| 657 | return | 565 | filterR.filterFunc(context) |
| 566 | } | ||
| 658 | } | 567 | } |
| 659 | } | 568 | } |
| 660 | } | 569 | } |
| ... | @@ -672,9 +581,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -672,9 +581,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 672 | //call the controller init function | 581 | //call the controller init function |
| 673 | init := vc.MethodByName("Init") | 582 | init := vc.MethodByName("Init") |
| 674 | in := make([]reflect.Value, 2) | 583 | in := make([]reflect.Value, 2) |
| 675 | ct := &Context{ResponseWriter: w, Request: r, Params: params, RequestBody: requestbody} | 584 | in[0] = reflect.ValueOf(context) |
| 676 | |||
| 677 | in[0] = reflect.ValueOf(ct) | ||
| 678 | in[1] = reflect.ValueOf(controllerType.Name()) | 585 | in[1] = reflect.ValueOf(controllerType.Name()) |
| 679 | init.Call(in) | 586 | init.Call(in) |
| 680 | //call prepare function | 587 | //call prepare function |
| ... | @@ -702,11 +609,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -702,11 +609,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 702 | method = vc.MethodByName("Finish") | 609 | method = vc.MethodByName("Finish") |
| 703 | method.Call(in) | 610 | method.Call(in) |
| 704 | //execute middleware filters | 611 | //execute middleware filters |
| 705 | if p.enableAfter { | 612 | if p.enableFilter { |
| 706 | for _, filter := range p.afterFilters { | 613 | if l, ok := p.filters["AfterExec"]; ok { |
| 707 | filter(w, r) | 614 | for _, filterR := range l { |
| 708 | if w.started { | 615 | if filterR.ValidRouter(r.URL.Path) { |
| 709 | return | 616 | filterR.filterFunc(context) |
| 617 | } | ||
| 710 | } | 618 | } |
| 711 | } | 619 | } |
| 712 | } | 620 | } |
| ... | @@ -714,6 +622,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -714,6 +622,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 714 | method.Call(in) | 622 | method.Call(in) |
| 715 | // set find | 623 | // set find |
| 716 | findrouter = true | 624 | findrouter = true |
| 625 | goto Last | ||
| 717 | } | 626 | } |
| 718 | } | 627 | } |
| 719 | } | 628 | } |
| ... | @@ -721,6 +630,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -721,6 +630,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 721 | } | 630 | } |
| 722 | } | 631 | } |
| 723 | 632 | ||
| 633 | Last: | ||
| 724 | //if no matches to url, throw a not found exception | 634 | //if no matches to url, throw a not found exception |
| 725 | if !findrouter { | 635 | if !findrouter { |
| 726 | if h, ok := ErrorMaps["404"]; ok { | 636 | if h, ok := ErrorMaps["404"]; ok { | ... | ... |
-
Please register or sign in to post a comment