support profile & statistics in another port
Showing
9 changed files
with
364 additions
and
27 deletions
admin.go
0 → 100644
| 1 | package beego | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "net/http" | ||
| 6 | ) | ||
| 7 | |||
| 8 | var BeeAdminApp *AdminApp | ||
| 9 | |||
| 10 | func init() { | ||
| 11 | BeeAdminApp = &AdminApp{ | ||
| 12 | routers: make(map[string]http.HandlerFunc), | ||
| 13 | } | ||
| 14 | BeeAdminApp.Route("/", AdminIndex) | ||
| 15 | } | ||
| 16 | |||
| 17 | func AdminIndex(rw http.ResponseWriter, r *http.Request) { | ||
| 18 | rw.Write([]byte("Welcome to Admin Dashboard")) | ||
| 19 | } | ||
| 20 | |||
| 21 | type AdminApp struct { | ||
| 22 | routers map[string]http.HandlerFunc | ||
| 23 | } | ||
| 24 | |||
| 25 | func (admin *AdminApp) Route(pattern string, f http.HandlerFunc) { | ||
| 26 | admin.routers[pattern] = f | ||
| 27 | } | ||
| 28 | |||
| 29 | func (admin *AdminApp) Run() { | ||
| 30 | addr := AdminHttpAddr | ||
| 31 | |||
| 32 | if AdminHttpPort != 0 { | ||
| 33 | addr = fmt.Sprintf("%s:%d", AdminHttpAddr, AdminHttpPort) | ||
| 34 | } | ||
| 35 | for p, f := range admin.routers { | ||
| 36 | http.Handle(p, f) | ||
| 37 | } | ||
| 38 | err := http.ListenAndServe(addr, nil) | ||
| 39 | if err != nil { | ||
| 40 | BeeLogger.Critical("Admin ListenAndServe: ", err) | ||
| 41 | } | ||
| 42 | } |
admin/profile.go
0 → 100644
| 1 | package admin | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "log" | ||
| 6 | "os" | ||
| 7 | "runtime" | ||
| 8 | "runtime/debug" | ||
| 9 | "runtime/pprof" | ||
| 10 | "strconv" | ||
| 11 | "time" | ||
| 12 | ) | ||
| 13 | |||
| 14 | var heapProfileCounter int32 | ||
| 15 | var startTime = time.Now() | ||
| 16 | var pid int | ||
| 17 | |||
| 18 | func init() { | ||
| 19 | pid = os.Getpid() | ||
| 20 | } | ||
| 21 | |||
| 22 | func ProcessInput(input string) { | ||
| 23 | switch input { | ||
| 24 | case "lookup goroutine": | ||
| 25 | p := pprof.Lookup("goroutine") | ||
| 26 | p.WriteTo(os.Stdout, 2) | ||
| 27 | case "lookup heap": | ||
| 28 | p := pprof.Lookup("heap") | ||
| 29 | p.WriteTo(os.Stdout, 2) | ||
| 30 | case "lookup threadcreate": | ||
| 31 | p := pprof.Lookup("threadcreate") | ||
| 32 | p.WriteTo(os.Stdout, 2) | ||
| 33 | case "lookup block": | ||
| 34 | p := pprof.Lookup("block") | ||
| 35 | p.WriteTo(os.Stdout, 2) | ||
| 36 | case "start cpuprof": | ||
| 37 | StartCPUProfile() | ||
| 38 | case "stop cpuprof": | ||
| 39 | StopCPUProfile() | ||
| 40 | case "get memprof": | ||
| 41 | MemProf() | ||
| 42 | case "gc summary": | ||
| 43 | PrintGCSummary() | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | func MemProf() { | ||
| 48 | if f, err := os.Create("mem-" + strconv.Itoa(pid) + ".memprof"); err != nil { | ||
| 49 | log.Fatal("record memory profile failed: %v", err) | ||
| 50 | } else { | ||
| 51 | runtime.GC() | ||
| 52 | pprof.WriteHeapProfile(f) | ||
| 53 | f.Close() | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | func StartCPUProfile() { | ||
| 58 | f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof") | ||
| 59 | if err != nil { | ||
| 60 | log.Fatal(err) | ||
| 61 | } | ||
| 62 | pprof.StartCPUProfile(f) | ||
| 63 | } | ||
| 64 | |||
| 65 | func StopCPUProfile() { | ||
| 66 | pprof.StopCPUProfile() | ||
| 67 | } | ||
| 68 | |||
| 69 | func PrintGCSummary() { | ||
| 70 | memStats := &runtime.MemStats{} | ||
| 71 | runtime.ReadMemStats(memStats) | ||
| 72 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} | ||
| 73 | debug.ReadGCStats(gcstats) | ||
| 74 | |||
| 75 | printGC(memStats, gcstats) | ||
| 76 | } | ||
| 77 | |||
| 78 | func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) { | ||
| 79 | |||
| 80 | if gcstats.NumGC > 0 { | ||
| 81 | lastPause := gcstats.Pause[0] | ||
| 82 | elapsed := time.Now().Sub(startTime) | ||
| 83 | overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100 | ||
| 84 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 85 | |||
| 86 | 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", | ||
| 87 | gcstats.NumGC, | ||
| 88 | toS(lastPause), | ||
| 89 | toS(avg(gcstats.Pause)), | ||
| 90 | overhead, | ||
| 91 | toH(memStats.Alloc), | ||
| 92 | toH(memStats.Sys), | ||
| 93 | toH(uint64(allocatedRate)), | ||
| 94 | toS(gcstats.PauseQuantiles[94]), | ||
| 95 | toS(gcstats.PauseQuantiles[98]), | ||
| 96 | toS(gcstats.PauseQuantiles[99])) | ||
| 97 | } else { | ||
| 98 | // while GC has disabled | ||
| 99 | elapsed := time.Now().Sub(startTime) | ||
| 100 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() | ||
| 101 | |||
| 102 | fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n", | ||
| 103 | toH(memStats.Alloc), | ||
| 104 | toH(memStats.Sys), | ||
| 105 | toH(uint64(allocatedRate))) | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | func avg(items []time.Duration) time.Duration { | ||
| 110 | var sum time.Duration | ||
| 111 | for _, item := range items { | ||
| 112 | sum += item | ||
| 113 | } | ||
| 114 | return time.Duration(int64(sum) / int64(len(items))) | ||
| 115 | } | ||
| 116 | |||
| 117 | // human readable format | ||
| 118 | func toH(bytes uint64) string { | ||
| 119 | switch { | ||
| 120 | case bytes < 1024: | ||
| 121 | return fmt.Sprintf("%dB", bytes) | ||
| 122 | case bytes < 1024*1024: | ||
| 123 | return fmt.Sprintf("%.2fK", float64(bytes)/1024) | ||
| 124 | case bytes < 1024*1024*1024: | ||
| 125 | return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) | ||
| 126 | default: | ||
| 127 | return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | // short string format | ||
| 132 | func toS(d time.Duration) string { | ||
| 133 | |||
| 134 | u := uint64(d) | ||
| 135 | if u < uint64(time.Second) { | ||
| 136 | switch { | ||
| 137 | case u == 0: | ||
| 138 | return "0" | ||
| 139 | case u < uint64(time.Microsecond): | ||
| 140 | return fmt.Sprintf("%.2fns", float64(u)) | ||
| 141 | case u < uint64(time.Millisecond): | ||
| 142 | return fmt.Sprintf("%.2fus", float64(u)/1000) | ||
| 143 | default: | ||
| 144 | return fmt.Sprintf("%.2fms", float64(u)/1000/1000) | ||
| 145 | } | ||
| 146 | } else { | ||
| 147 | switch { | ||
| 148 | case u < uint64(time.Minute): | ||
| 149 | return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000) | ||
| 150 | case u < uint64(time.Hour): | ||
| 151 | return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60) | ||
| 152 | default: | ||
| 153 | return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60) | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | } |
admin/statistics.go
0 → 100644
| 1 | package admin | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "encoding/json" | ||
| 5 | "sync" | ||
| 6 | "time" | ||
| 7 | ) | ||
| 8 | |||
| 9 | type Statistics struct { | ||
| 10 | RequestUrl string | ||
| 11 | RequestController string | ||
| 12 | RequestNum int64 | ||
| 13 | MinTime time.Duration | ||
| 14 | MaxTime time.Duration | ||
| 15 | TotalTime time.Duration | ||
| 16 | } | ||
| 17 | |||
| 18 | type UrlMap struct { | ||
| 19 | lock sync.RWMutex | ||
| 20 | urlmap map[string]map[string]*Statistics | ||
| 21 | } | ||
| 22 | |||
| 23 | func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController string, requesttime time.Duration) { | ||
| 24 | m.lock.Lock() | ||
| 25 | defer m.lock.Unlock() | ||
| 26 | if method, ok := m.urlmap[requestUrl]; ok { | ||
| 27 | if s, ok := method[requestMethod]; ok { | ||
| 28 | s.RequestNum += 1 | ||
| 29 | if s.MaxTime < requesttime { | ||
| 30 | s.MaxTime = requesttime | ||
| 31 | } | ||
| 32 | if s.MinTime > requesttime { | ||
| 33 | s.MinTime = requesttime | ||
| 34 | } | ||
| 35 | s.TotalTime += requesttime | ||
| 36 | } else { | ||
| 37 | nb := &Statistics{ | ||
| 38 | RequestUrl: requestUrl, | ||
| 39 | RequestController: requestController, | ||
| 40 | RequestNum: 1, | ||
| 41 | MinTime: requesttime, | ||
| 42 | MaxTime: requesttime, | ||
| 43 | TotalTime: requesttime, | ||
| 44 | } | ||
| 45 | m.urlmap[requestUrl][requestMethod] = nb | ||
| 46 | } | ||
| 47 | |||
| 48 | } else { | ||
| 49 | methodmap := make(map[string]*Statistics) | ||
| 50 | nb := &Statistics{ | ||
| 51 | RequestUrl: requestUrl, | ||
| 52 | RequestController: requestController, | ||
| 53 | RequestNum: 1, | ||
| 54 | MinTime: requesttime, | ||
| 55 | MaxTime: requesttime, | ||
| 56 | TotalTime: requesttime, | ||
| 57 | } | ||
| 58 | methodmap[requestMethod] = nb | ||
| 59 | m.urlmap[requestUrl] = methodmap | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | func (m *UrlMap) GetMap() []byte { | ||
| 64 | m.lock.RLock() | ||
| 65 | defer m.lock.RUnlock() | ||
| 66 | r, err := json.Marshal(m.urlmap) | ||
| 67 | if err != nil { | ||
| 68 | return []byte("") | ||
| 69 | } | ||
| 70 | return r | ||
| 71 | } | ||
| 72 | |||
| 73 | var StatisticsMap *UrlMap | ||
| 74 | |||
| 75 | func init() { | ||
| 76 | StatisticsMap = &UrlMap{ | ||
| 77 | urlmap: make(map[string]map[string]*Statistics), | ||
| 78 | } | ||
| 79 | } |
admin/statistics_test.go
0 → 100644
| 1 | package admin | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "testing" | ||
| 5 | "time" | ||
| 6 | ) | ||
| 7 | |||
| 8 | func TestStatics(t *testing.T) { | ||
| 9 | StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(1000000)) | ||
| 10 | StatisticsMap.AddStatistics("POST", "/api/user", "&admin.user", time.Duration(1200000)) | ||
| 11 | StatisticsMap.AddStatistics("GET", "/api/user", "&admin.user", time.Duration(1300000)) | ||
| 12 | StatisticsMap.AddStatistics("POST", "/api/admin", "&admin.user", time.Duration(1400000)) | ||
| 13 | StatisticsMap.AddStatistics("POST", "/api/user/astaxie", "&admin.user", time.Duration(1200000)) | ||
| 14 | StatisticsMap.AddStatistics("POST", "/api/user/xiemengjun", "&admin.user", time.Duration(1300000)) | ||
| 15 | StatisticsMap.AddStatistics("DELETE", "/api/user", "&admin.user", time.Duration(1400000)) | ||
| 16 | s := StatisticsMap.GetMap() | ||
| 17 | } |
admin/task.go
0 → 100644
| 1 | package admin | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -93,5 +93,9 @@ func Run() { | ... | @@ -93,5 +93,9 @@ func Run() { |
| 93 | middleware.AppName = AppName | 93 | middleware.AppName = AppName |
| 94 | middleware.RegisterErrorHander() | 94 | middleware.RegisterErrorHander() |
| 95 | 95 | ||
| 96 | if EnableAdmin { | ||
| 97 | go BeeAdminApp.Run() | ||
| 98 | } | ||
| 99 | |||
| 96 | BeeApp.Run() | 100 | BeeApp.Run() |
| 97 | } | 101 | } | ... | ... |
| ... | @@ -53,6 +53,9 @@ var ( | ... | @@ -53,6 +53,9 @@ var ( |
| 53 | TemplateLeft string | 53 | TemplateLeft string |
| 54 | TemplateRight string | 54 | TemplateRight string |
| 55 | BeegoServerName string | 55 | BeegoServerName string |
| 56 | EnableAdmin bool //enable admin module to log api time | ||
| 57 | AdminHttpAddr string //admin module http addr | ||
| 58 | AdminHttpPort int | ||
| 56 | ) | 59 | ) |
| 57 | 60 | ||
| 58 | func init() { | 61 | func init() { |
| ... | @@ -89,6 +92,9 @@ func init() { | ... | @@ -89,6 +92,9 @@ func init() { |
| 89 | TemplateLeft = "{{" | 92 | TemplateLeft = "{{" |
| 90 | TemplateRight = "}}" | 93 | TemplateRight = "}}" |
| 91 | BeegoServerName = "beegoServer" | 94 | BeegoServerName = "beegoServer" |
| 95 | EnableAdmin = true | ||
| 96 | AdminHttpAddr = "localhost" | ||
| 97 | AdminHttpPort = 8088 | ||
| 92 | ParseConfig() | 98 | ParseConfig() |
| 93 | runtime.GOMAXPROCS(runtime.NumCPU()) | 99 | runtime.GOMAXPROCS(runtime.NumCPU()) |
| 94 | } | 100 | } |
| ... | @@ -311,6 +317,24 @@ func ParseConfig() (err error) { | ... | @@ -311,6 +317,24 @@ func ParseConfig() (err error) { |
| 311 | } | 317 | } |
| 312 | } | 318 | } |
| 313 | } | 319 | } |
| 320 | if enableadmin, err := AppConfig.Bool("enableadmin"); err == nil { | ||
| 321 | EnableAdmin = enableadmin | ||
| 322 | } | ||
| 323 | if enableadmin, err := AppConfig.Bool("EnableAdmin"); err == nil { | ||
| 324 | EnableAdmin = enableadmin | ||
| 325 | } | ||
| 326 | if adminhttpaddr := AppConfig.String("admintttpaddr"); adminhttpaddr != "" { | ||
| 327 | AdminHttpAddr = adminhttpaddr | ||
| 328 | } | ||
| 329 | if adminhttpaddr := AppConfig.String("AdminHttpAddr"); adminhttpaddr != "" { | ||
| 330 | AdminHttpAddr = adminhttpaddr | ||
| 331 | } | ||
| 332 | if adminhttpport, err := AppConfig.Int("adminhttpport"); err == nil { | ||
| 333 | AdminHttpPort = adminhttpport | ||
| 334 | } | ||
| 335 | if adminhttpport, err := AppConfig.Int("AdminHttpPort"); err == nil { | ||
| 336 | AdminHttpPort = adminhttpport | ||
| 337 | } | ||
| 314 | } | 338 | } |
| 315 | return nil | 339 | return nil |
| 316 | } | 340 | } | ... | ... |
| ... | @@ -258,3 +258,7 @@ func stringsToJson(str string) string { | ... | @@ -258,3 +258,7 @@ func stringsToJson(str string) string { |
| 258 | } | 258 | } |
| 259 | return jsons | 259 | return jsons |
| 260 | } | 260 | } |
| 261 | |||
| 262 | func (output *BeegoOutput) Session(name interface{}, value interface{}) { | ||
| 263 | output.Context.Input.CruSession.Set(name, value) | ||
| 264 | } | ... | ... |
| ... | @@ -2,6 +2,7 @@ package beego | ... | @@ -2,6 +2,7 @@ package beego |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "fmt" | 4 | "fmt" |
| 5 | "github.com/astaxie/beego/admin" | ||
| 5 | beecontext "github.com/astaxie/beego/context" | 6 | beecontext "github.com/astaxie/beego/context" |
| 6 | "github.com/astaxie/beego/middleware" | 7 | "github.com/astaxie/beego/middleware" |
| 7 | "net/http" | 8 | "net/http" |
| ... | @@ -12,6 +13,7 @@ import ( | ... | @@ -12,6 +13,7 @@ import ( |
| 12 | "runtime" | 13 | "runtime" |
| 13 | "strconv" | 14 | "strconv" |
| 14 | "strings" | 15 | "strings" |
| 16 | "time" | ||
| 15 | ) | 17 | ) |
| 16 | 18 | ||
| 17 | var HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"} | 19 | var HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"} |
| ... | @@ -406,6 +408,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -406,6 +408,12 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 406 | } | 408 | } |
| 407 | }() | 409 | }() |
| 408 | 410 | ||
| 411 | starttime := time.Now() | ||
| 412 | requestPath := r.URL.Path | ||
| 413 | var runrouter *controllerInfo | ||
| 414 | var findrouter bool | ||
| 415 | params := make(map[string]string) | ||
| 416 | |||
| 409 | w := &responseWriter{writer: rw} | 417 | w := &responseWriter{writer: rw} |
| 410 | w.Header().Set("Server", BeegoServerName) | 418 | w.Header().Set("Server", BeegoServerName) |
| 411 | context := &beecontext.Context{ | 419 | context := &beecontext.Context{ |
| ... | @@ -422,27 +430,18 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -422,27 +430,18 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 422 | context.Output = beecontext.NewOutput(rw) | 430 | context.Output = beecontext.NewOutput(rw) |
| 423 | } | 431 | } |
| 424 | 432 | ||
| 425 | if SessionOn { | ||
| 426 | context.Input.CruSession = GlobalSessions.SessionStart(w, r) | ||
| 427 | } | ||
| 428 | |||
| 429 | if !inSlice(strings.ToLower(r.Method), HTTPMETHOD) { | 433 | if !inSlice(strings.ToLower(r.Method), HTTPMETHOD) { |
| 430 | http.Error(w, "Method Not Allowed", 405) | 434 | http.Error(w, "Method Not Allowed", 405) |
| 431 | return | 435 | goto Admin |
| 432 | } | 436 | } |
| 433 | 437 | ||
| 434 | var runrouter *controllerInfo | ||
| 435 | var findrouter bool | ||
| 436 | |||
| 437 | params := make(map[string]string) | ||
| 438 | |||
| 439 | if p.enableFilter { | 438 | if p.enableFilter { |
| 440 | if l, ok := p.filters["BeforRouter"]; ok { | 439 | if l, ok := p.filters["BeforRouter"]; ok { |
| 441 | for _, filterR := range l { | 440 | for _, filterR := range l { |
| 442 | if filterR.ValidRouter(r.URL.Path) { | 441 | if filterR.ValidRouter(r.URL.Path) { |
| 443 | filterR.filterFunc(context) | 442 | filterR.filterFunc(context) |
| 444 | if w.started { | 443 | if w.started { |
| 445 | return | 444 | goto Admin |
| 446 | } | 445 | } |
| 447 | } | 446 | } |
| 448 | } | 447 | } |
| ... | @@ -455,7 +454,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -455,7 +454,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 455 | file := staticDir + r.URL.Path | 454 | file := staticDir + r.URL.Path |
| 456 | http.ServeFile(w, r, file) | 455 | http.ServeFile(w, r, file) |
| 457 | w.started = true | 456 | w.started = true |
| 458 | return | 457 | goto Admin |
| 459 | } | 458 | } |
| 460 | if strings.HasPrefix(r.URL.Path, prefix) { | 459 | if strings.HasPrefix(r.URL.Path, prefix) { |
| 461 | file := staticDir + r.URL.Path[len(prefix):] | 460 | file := staticDir + r.URL.Path[len(prefix):] |
| ... | @@ -465,32 +464,36 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -465,32 +464,36 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 465 | Warn(err) | 464 | Warn(err) |
| 466 | } | 465 | } |
| 467 | http.NotFound(w, r) | 466 | http.NotFound(w, r) |
| 468 | return | 467 | goto Admin |
| 469 | } | 468 | } |
| 470 | //if the request is dir and DirectoryIndex is false then | 469 | //if the request is dir and DirectoryIndex is false then |
| 471 | if finfo.IsDir() && !DirectoryIndex { | 470 | if finfo.IsDir() && !DirectoryIndex { |
| 472 | middleware.Exception("403", rw, r, "403 Forbidden") | 471 | middleware.Exception("403", rw, r, "403 Forbidden") |
| 473 | return | 472 | goto Admin |
| 474 | } | 473 | } |
| 475 | http.ServeFile(w, r, file) | 474 | http.ServeFile(w, r, file) |
| 476 | w.started = true | 475 | w.started = true |
| 477 | return | 476 | goto Admin |
| 478 | } | 477 | } |
| 479 | } | 478 | } |
| 480 | 479 | ||
| 480 | // session init after static file | ||
| 481 | if SessionOn { | ||
| 482 | context.Input.CruSession = GlobalSessions.SessionStart(w, r) | ||
| 483 | } | ||
| 484 | |||
| 481 | if p.enableFilter { | 485 | if p.enableFilter { |
| 482 | if l, ok := p.filters["AfterStatic"]; ok { | 486 | if l, ok := p.filters["AfterStatic"]; ok { |
| 483 | for _, filterR := range l { | 487 | for _, filterR := range l { |
| 484 | if filterR.ValidRouter(r.URL.Path) { | 488 | if filterR.ValidRouter(r.URL.Path) { |
| 485 | filterR.filterFunc(context) | 489 | filterR.filterFunc(context) |
| 486 | if w.started { | 490 | if w.started { |
| 487 | return | 491 | goto Admin |
| 488 | } | 492 | } |
| 489 | } | 493 | } |
| 490 | } | 494 | } |
| 491 | } | 495 | } |
| 492 | } | 496 | } |
| 493 | requestPath := r.URL.Path | ||
| 494 | 497 | ||
| 495 | if CopyRequestBody { | 498 | if CopyRequestBody { |
| 496 | context.Input.Body() | 499 | context.Input.Body() |
| ... | @@ -509,7 +512,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -509,7 +512,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 509 | if requestPath[n-1] != '/' && len(route.pattern) == n+1 && | 512 | if requestPath[n-1] != '/' && len(route.pattern) == n+1 && |
| 510 | route.pattern[n] == '/' && route.pattern[:n] == requestPath { | 513 | route.pattern[n] == '/' && route.pattern[:n] == requestPath { |
| 511 | http.Redirect(w, r, requestPath+"/", 301) | 514 | http.Redirect(w, r, requestPath+"/", 301) |
| 512 | return | 515 | goto Admin |
| 513 | } | 516 | } |
| 514 | } | 517 | } |
| 515 | 518 | ||
| ... | @@ -546,6 +549,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -546,6 +549,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 546 | break | 549 | break |
| 547 | } | 550 | } |
| 548 | } | 551 | } |
| 552 | |||
| 549 | context.Input.Param = params | 553 | context.Input.Param = params |
| 550 | 554 | ||
| 551 | if runrouter != nil { | 555 | if runrouter != nil { |
| ... | @@ -559,7 +563,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -559,7 +563,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 559 | if filterR.ValidRouter(r.URL.Path) { | 563 | if filterR.ValidRouter(r.URL.Path) { |
| 560 | filterR.filterFunc(context) | 564 | filterR.filterFunc(context) |
| 561 | if w.started { | 565 | if w.started { |
| 562 | return | 566 | goto Admin |
| 563 | } | 567 | } |
| 564 | } | 568 | } |
| 565 | } | 569 | } |
| ... | @@ -714,7 +718,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -714,7 +718,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 714 | if filterR.ValidRouter(r.URL.Path) { | 718 | if filterR.ValidRouter(r.URL.Path) { |
| 715 | filterR.filterFunc(context) | 719 | filterR.filterFunc(context) |
| 716 | if w.started { | 720 | if w.started { |
| 717 | return | 721 | goto Admin |
| 718 | } | 722 | } |
| 719 | } | 723 | } |
| 720 | } | 724 | } |
| ... | @@ -740,7 +744,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -740,7 +744,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 740 | 744 | ||
| 741 | if strings.ToLower(requestPath) == "/"+cName { | 745 | if strings.ToLower(requestPath) == "/"+cName { |
| 742 | http.Redirect(w, r, requestPath+"/", 301) | 746 | http.Redirect(w, r, requestPath+"/", 301) |
| 743 | return | 747 | goto Admin |
| 744 | } | 748 | } |
| 745 | 749 | ||
| 746 | if strings.ToLower(requestPath) == "/"+cName+"/" { | 750 | if strings.ToLower(requestPath) == "/"+cName+"/" { |
| ... | @@ -754,6 +758,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -754,6 +758,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 754 | if r.Method == "POST" { | 758 | if r.Method == "POST" { |
| 755 | r.ParseMultipartForm(MaxMemory) | 759 | r.ParseMultipartForm(MaxMemory) |
| 756 | } | 760 | } |
| 761 | // set find | ||
| 762 | findrouter = true | ||
| 757 | //execute middleware filters | 763 | //execute middleware filters |
| 758 | if p.enableFilter { | 764 | if p.enableFilter { |
| 759 | if l, ok := p.filters["BeforExec"]; ok { | 765 | if l, ok := p.filters["BeforExec"]; ok { |
| ... | @@ -761,7 +767,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -761,7 +767,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 761 | if filterR.ValidRouter(r.URL.Path) { | 767 | if filterR.ValidRouter(r.URL.Path) { |
| 762 | filterR.filterFunc(context) | 768 | filterR.filterFunc(context) |
| 763 | if w.started { | 769 | if w.started { |
| 764 | return | 770 | goto Admin |
| 765 | } | 771 | } |
| 766 | } | 772 | } |
| 767 | } | 773 | } |
| ... | @@ -816,7 +822,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -816,7 +822,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 816 | if filterR.ValidRouter(r.URL.Path) { | 822 | if filterR.ValidRouter(r.URL.Path) { |
| 817 | filterR.filterFunc(context) | 823 | filterR.filterFunc(context) |
| 818 | if w.started { | 824 | if w.started { |
| 819 | return | 825 | goto Admin |
| 820 | } | 826 | } |
| 821 | } | 827 | } |
| 822 | } | 828 | } |
| ... | @@ -824,9 +830,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -824,9 +830,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 824 | } | 830 | } |
| 825 | method = vc.MethodByName("Destructor") | 831 | method = vc.MethodByName("Destructor") |
| 826 | method.Call(in) | 832 | method.Call(in) |
| 827 | // set find | 833 | goto Admin |
| 828 | findrouter = true | ||
| 829 | goto Last | ||
| 830 | } | 834 | } |
| 831 | } | 835 | } |
| 832 | } | 836 | } |
| ... | @@ -834,11 +838,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -834,11 +838,16 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 834 | } | 838 | } |
| 835 | } | 839 | } |
| 836 | 840 | ||
| 837 | Last: | ||
| 838 | //if no matches to url, throw a not found exception | 841 | //if no matches to url, throw a not found exception |
| 839 | if !findrouter { | 842 | if !findrouter { |
| 840 | middleware.Exception("404", rw, r, "") | 843 | middleware.Exception("404", rw, r, "") |
| 841 | } | 844 | } |
| 845 | |||
| 846 | Admin: | ||
| 847 | //admin module record QPS | ||
| 848 | if EnableAdmin { | ||
| 849 | go admin.StatisticsMap.AddStatistics(r.Method, requestPath, runrouter.controllerType.Name(), time.Since(starttime)) | ||
| 850 | } | ||
| 842 | } | 851 | } |
| 843 | 852 | ||
| 844 | //responseWriter is a wrapper for the http.ResponseWriter | 853 | //responseWriter is a wrapper for the http.ResponseWriter | ... | ... |
-
Please register or sign in to post a comment