github.com/gogf/gf@v1.16.9/net/ghttp/ghttp_server_router_hook.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package ghttp 8 9 import ( 10 "github.com/gogf/gf/debug/gdebug" 11 "net/http" 12 "reflect" 13 ) 14 15 // BindHookHandler registers handler for specified hook. 16 func (s *Server) BindHookHandler(pattern string, hook string, handler HandlerFunc) { 17 s.doBindHookHandler(pattern, hook, handler, "") 18 } 19 20 func (s *Server) doBindHookHandler(pattern string, hook string, handler HandlerFunc, source string) { 21 s.setHandler(pattern, &handlerItem{ 22 Type: handlerTypeHook, 23 Name: gdebug.FuncPath(handler), 24 Info: handlerFuncInfo{ 25 Func: handler, 26 Type: reflect.TypeOf(handler), 27 }, 28 HookName: hook, 29 Source: source, 30 }) 31 } 32 33 func (s *Server) BindHookHandlerByMap(pattern string, hookMap map[string]HandlerFunc) { 34 for k, v := range hookMap { 35 s.BindHookHandler(pattern, k, v) 36 } 37 } 38 39 // callHookHandler calls the hook handler by their registered sequences. 40 func (s *Server) callHookHandler(hook string, r *Request) { 41 hookItems := r.getHookHandlers(hook) 42 if len(hookItems) > 0 { 43 // Backup the old router variable map. 44 oldRouterMap := r.routerMap 45 for _, item := range hookItems { 46 r.routerMap = item.Values 47 // DO NOT USE the router of the hook handler, 48 // which can overwrite the router of serving handler. 49 // r.Router = item.handler.router 50 if err := s.niceCallHookHandler(item.Handler.Info.Func, r); err != nil { 51 switch err { 52 case exceptionExit: 53 break 54 case exceptionExitAll: 55 fallthrough 56 case exceptionExitHook: 57 return 58 default: 59 r.Response.WriteStatus(http.StatusInternalServerError, err) 60 panic(err) 61 } 62 } 63 } 64 // Restore the old router variable map. 65 r.routerMap = oldRouterMap 66 } 67 } 68 69 // getHookHandlers retrieves and returns the hook handlers of specified hook. 70 func (r *Request) getHookHandlers(hook string) []*handlerParsedItem { 71 if !r.hasHookHandler { 72 return nil 73 } 74 parsedItems := make([]*handlerParsedItem, 0, 4) 75 for _, v := range r.handlers { 76 if v.Handler.HookName != hook { 77 continue 78 } 79 item := v 80 parsedItems = append(parsedItems, item) 81 } 82 return parsedItems 83 } 84 85 // niceCallHookHandler nicely calls the hook handler function, 86 // which means it automatically catches and returns the possible panic error to 87 // avoid goroutine crash. 88 func (s *Server) niceCallHookHandler(f HandlerFunc, r *Request) (err interface{}) { 89 defer func() { 90 err = recover() 91 }() 92 f(r) 93 return 94 }