github.com/erda-project/erda-infra@v1.0.10-0.20240327085753-f3a249292aeb/providers/httpserver/server/server.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 "crypto/tls" 19 "net" 20 "net/http" 21 "time" 22 23 "github.com/labstack/echo" 24 ) 25 26 type ( 27 // Server . 28 Server interface { 29 Use(middleware ...MiddlewareFunc) 30 NewRouter() RouterTx 31 Router() Router 32 Start(addr string) error 33 Close() error 34 } 35 // RouterTx . 36 RouterTx interface { 37 Router 38 Commit() 39 } 40 ) 41 42 var ( 43 // NotFoundHandler . 44 NotFoundHandler = echo.NotFoundHandler 45 ) 46 47 type ( 48 routerManager interface { 49 GetRouter() Router 50 NewRouter() RouterTx 51 } 52 server struct { 53 e *echo.Echo 54 reloadable bool 55 router routerManager 56 middleware []MiddlewareFunc 57 } 58 ) 59 60 // New . 61 func New(reloadable bool, binder echo.Binder, validator echo.Validator) Server { 62 s := &server{ 63 e: echo.New(), 64 reloadable: reloadable, 65 } 66 s.e.HideBanner, s.e.HidePort = true, true 67 s.e.Binder, s.e.Validator = binder, validator 68 s.e.Server.Handler, s.e.TLSServer.Handler = s, s 69 if reloadable { 70 s.router = newReloadableRouterManager(s.e) 71 } else { 72 s.router = newFixedRouterManager(s.e) 73 } 74 return s 75 } 76 77 // Start . 78 func (s *server) Start(addr string) error { 79 err := s.startHTTP(addr) 80 if err != nil && err != http.ErrServerClosed { 81 return err 82 } 83 return nil 84 } 85 86 // Close . 87 func (s *server) Close() error { 88 err := s.e.Server.Close() 89 if err != nil && err != http.ErrServerClosed { 90 return err 91 } 92 return nil 93 } 94 95 // ServeHTTP . 96 func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 97 router := s.router.GetRouter() 98 99 // Acquire context 100 c := router.NewContext() 101 // Release context 102 defer router.ReleaseContext(c) 103 c.Reset(r, w) 104 105 // Find handler 106 router.Find(r.Method, getPath(r), c) 107 h := c.Handler() 108 if h == nil { 109 h = NotFoundHandler 110 } 111 for i := len(s.middleware) - 1; i >= 0; i-- { 112 h = s.middleware[i](h) 113 } 114 115 // Execute chain 116 if err := h(c); err != nil { 117 s.e.HTTPErrorHandler(err, c) 118 } 119 } 120 121 func getPath(r *http.Request) string { 122 path := r.URL.RawPath 123 if path == "" { 124 path = r.URL.Path 125 } 126 return path 127 } 128 129 // NewRouter . 130 func (s *server) NewRouter() RouterTx { return s.router.NewRouter() } 131 132 // Router . 133 func (s *server) Router() Router { return s.router.GetRouter() } 134 135 // Use . 136 func (s *server) Use(middleware ...MiddlewareFunc) { 137 s.middleware = append(s.middleware, middleware...) 138 } 139 140 // Start starts an HTTP server. 141 func (s *server) startHTTP(address string) error { 142 s.e.Server.Addr = address 143 return s.startServer(s.e.Server) 144 } 145 146 // StartServer starts a custom http server. 147 func (s *server) startServer(svr *http.Server) (err error) { 148 if svr.TLSConfig == nil { 149 if s.e.Listener == nil { 150 s.e.Listener, err = newListener(svr.Addr) 151 if err != nil { 152 return err 153 } 154 } 155 return svr.Serve(s.e.Listener) 156 } 157 if s.e.TLSListener == nil { 158 l, err := newListener(svr.Addr) 159 if err != nil { 160 return err 161 } 162 s.e.TLSListener = tls.NewListener(l, svr.TLSConfig) 163 } 164 return svr.Serve(s.e.TLSListener) 165 } 166 167 // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted 168 // connections. It's used by ListenAndServe and ListenAndServeTLS so 169 // dead TCP connections (e.g. closing laptop mid-download) eventually 170 // go away. 171 type tcpKeepAliveListener struct { 172 *net.TCPListener 173 } 174 175 func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { 176 tc, err := ln.AcceptTCP() 177 if err != nil { 178 return 179 } 180 tc.SetKeepAlive(true) 181 tc.SetKeepAlivePeriod(3 * time.Minute) 182 return tc, nil 183 } 184 185 func newListener(address string) (*tcpKeepAliveListener, error) { 186 l, err := net.Listen("tcp", address) 187 if err != nil { 188 return nil, err 189 } 190 return &tcpKeepAliveListener{l.(*net.TCPListener)}, nil 191 }