gin.Default() ⬇️
func Default() *Engine { debugPrintWARNINGDefault() engine := New() engine.Use(Logger(), Recovery()) return engine } ⬇️
func New() *Engine { debugPrintWARNINGNew() engine := &Engine{ RouterGroup: RouterGroup{ Handlers: nil, basePath: "/", root: true, }, FuncMap: template.FuncMap{}, RedirectTrailingSlash: true, RedirectFixedPath: false, HandleMethodNotAllowed: false, ForwardedByClientIP: true, AppEngine: defaultAppEngine, UseRawPath: false, UnescapePathValues: true, MaxMultipartMemory: defaultMultipartMemory, trees: make(methodTrees, 0, 9), delims: render.Delims{Left: "{{", Right: "}}"}, secureJsonPrefix: "while(1);", } engine.RouterGroup.engine = engine engine.pool.New = func() interface{} { return engine.allocateContext() } return engine } ⬇️
engine.Use(Logger(), Recovery()) ⬇️
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes { engine.RouterGroup.Use(middleware...) engine.rebuild404Handlers() engine.rebuild405Handlers() return engine }
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("GET", relativePath, handlers) } ⬇️ func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes { absolutePath := group.calculateAbsolutePath(relativePath) handlers = group.combineHandlers(handlers) group.engine.addRoute(httpMethod, absolutePath, handlers) return group.returnObj() } ⬇️ func (engine *Engine) addRoute(method, path string, handlers HandlersChain) { assert1(path[0] == '/', "path must begin with '/'") assert1(method != "", "HTTP method can not be empty") assert1(len(handlers) > 0, "there must be at least one handler")
debugPrintRoute(method, path, handlers) root := engine.trees.get(method) if root == nil { root = new(node) engine.trees = append(engine.trees, methodTree{method: method, root: root}) } root.addRoute(path, handlers) } ⬇️
type node struct { path string indices string children []*node handlers HandlersChain priority uint32 nType nodeType maxParams uint8 wildChild bool }
func (engine *Engine) Run(addr ...string) (err error) { defer func() { debugPrintError(err) }()
address := resolveAddress(addr) debugPrint("Listening and serving HTTP on %s\n", address) err = http.ListenAndServe(address, engine) return } ⬇️
type Handler interface { ServeHTTP(ResponseWriter, *Request) } ⬇️
ln, err := net.Listen("tcp", addr) ⬇️
srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) ⬇️
rw, e := l.Accept() ⬇️
go c.serve(ctx)
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { c := engine.pool.Get().(*Context) c.writermem.reset(w) c.Request = req c.reset()
engine.handleHTTPRequest(c)
engine.pool.Put(c) } ⬇️
engine.handleHTTPRequest(c) ⬇️ t := engine.trees for i, tl := 0, len(t); i < tl; i++ { if t[i].method != httpMethod { continue } root := t[i].root handlers, params, tsr := root.getValue(path, c.Params, unescape) if handlers != nil { c.handlers = handlers c.Params = params c.Next() c.writermem.WriteHeaderNow() return } ... }
type methodTree struct { method string root *node }
type methodTrees []methodTree ⬇️
func (c *Context) Next() { c.index++ for s := int8(len(c.handlers)); c.index < s; c.index++ { c.handlers[c.index](c) } }
func (c *Context) reset() { c.Writer = &c.writermem c.Params = c.Params[0:0] c.handlers = nil c.index = -1 c.Keys = nil c.Errors = c.Errors[0:0] c.Accepted = nil }
|