github.com/erda-project/erda-infra@v1.0.9/providers/httpserver/server/router.go (about) 1 // Copyright (c) 2021 Terminus, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package server 16 17 import ( 18 "sync" 19 "sync/atomic" 20 21 "github.com/labstack/echo" 22 ) 23 24 type ( 25 // Context . 26 Context = echo.Context 27 // HandlerFunc . 28 HandlerFunc = echo.HandlerFunc 29 // MiddlewareFunc . 30 MiddlewareFunc = echo.MiddlewareFunc 31 32 // Router . 33 Router interface { 34 Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) 35 Find(method, path string, c Context) 36 NewContext() Context 37 ReleaseContext(c Context) 38 } 39 ) 40 41 type router struct { 42 *echo.Router 43 e *echo.Echo 44 pool sync.Pool 45 } 46 47 func newRouter(e *echo.Echo, binder echo.Binder, validator echo.Validator) Router { 48 if e == nil { 49 e = echo.New() 50 e.Binder, e.Validator = binder, validator 51 } 52 r := &router{ 53 Router: e.Router(), 54 e: e, 55 } 56 r.pool.New = func() interface{} { 57 return r.e.NewContext(nil, nil) 58 } 59 return r 60 } 61 62 // Add registers a new route for an HTTP method and path with matching handler 63 // in the router with optional route-level middleware. 64 func (rt *router) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { 65 h := handler 66 // Chain middleware 67 for i := len(middleware) - 1; i >= 0; i-- { 68 h = middleware[i](h) 69 } 70 rt.Router.Add(method, path, h) 71 } 72 73 // NewContext . 74 func (rt *router) NewContext() Context { 75 return rt.pool.Get().(Context) 76 } 77 78 func (rt *router) ReleaseContext(c Context) { 79 rt.pool.Put(c) 80 } 81 82 type fixedRouterManager struct{ Router } 83 84 func (r *fixedRouterManager) GetRouter() Router { return r.Router } 85 func (r *fixedRouterManager) NewRouter() RouterTx { return r } 86 func (r *fixedRouterManager) Commit() {} 87 88 func newFixedRouterManager(e *echo.Echo) routerManager { 89 return &fixedRouterManager{ 90 Router: newRouter(e, e.Binder, e.Validator), 91 } 92 } 93 94 type reloadableRouterManager struct { 95 v atomic.Value 96 binder echo.Binder 97 validator echo.Validator 98 } 99 100 func (r *reloadableRouterManager) GetRouter() Router { return r.v.Load().(Router) } 101 func (r *reloadableRouterManager) NewRouter() RouterTx { 102 return &reloadableRouterTx{ 103 Router: newRouter(nil, r.binder, r.validator), 104 rr: r, 105 } 106 } 107 108 type reloadableRouterTx struct { 109 Router 110 rr *reloadableRouterManager 111 } 112 113 func (r *reloadableRouterTx) Commit() { r.rr.v.Store(r.Router) } 114 115 func newReloadableRouterManager(e *echo.Echo) routerManager { 116 r := &reloadableRouterManager{ 117 binder: e.Binder, 118 validator: e.Validator, 119 } 120 r.NewRouter().Commit() 121 return r 122 }