github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/transports/fast/server.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package fast 19 20 import ( 21 "crypto/tls" 22 "fmt" 23 "github.com/aacfactory/errors" 24 "github.com/aacfactory/fns/commons/bytex" 25 "github.com/aacfactory/fns/context" 26 "github.com/aacfactory/fns/transports" 27 "github.com/aacfactory/fns/transports/ssl" 28 "github.com/aacfactory/logs" 29 "github.com/dgrr/http2" 30 "github.com/valyala/fasthttp" 31 "github.com/valyala/fasthttp/prefork" 32 "net" 33 "strings" 34 "time" 35 ) 36 37 func newServer(log logs.Logger, port int, tlsConfig ssl.Config, config *Config, handler transports.Handler) (srv *Server, err error) { 38 var srvTLS *tls.Config 39 var lnf ssl.ListenerFunc 40 if tlsConfig != nil { 41 srvTLS, lnf = tlsConfig.Server() 42 } 43 44 readBufferSize := uint64(0) 45 if config.ReadBufferSize != "" { 46 readBufferSize, err = bytex.ParseBytes(strings.TrimSpace(config.ReadBufferSize)) 47 if err != nil { 48 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("readBufferSize must be bytes format")).WithCause(err).WithMeta("transport", transportName) 49 return 50 } 51 } 52 readTimeout := 10 * time.Second 53 if config.ReadTimeout != "" { 54 readTimeout, err = time.ParseDuration(strings.TrimSpace(config.ReadTimeout)) 55 if err != nil { 56 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("readTimeout must be time.Duration format")).WithCause(err).WithMeta("transport", transportName) 57 return 58 } 59 } 60 writeBufferSize := uint64(0) 61 if config.WriteBufferSize != "" { 62 writeBufferSize, err = bytex.ParseBytes(strings.TrimSpace(config.WriteBufferSize)) 63 if err != nil { 64 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("writeBufferSize must be bytes format")).WithCause(err).WithMeta("transport", transportName) 65 return 66 } 67 } 68 writeTimeout := 10 * time.Second 69 if config.WriteTimeout != "" { 70 writeTimeout, err = time.ParseDuration(strings.TrimSpace(config.WriteTimeout)) 71 if err != nil { 72 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("writeTimeout must be time.Duration format")).WithCause(err).WithMeta("transport", transportName) 73 return 74 } 75 } 76 maxIdleWorkerDuration := time.Duration(0) 77 if config.MaxIdleWorkerDuration != "" { 78 maxIdleWorkerDuration, err = time.ParseDuration(strings.TrimSpace(config.MaxIdleWorkerDuration)) 79 if err != nil { 80 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("maxIdleWorkerDuration must be time.Duration format")).WithCause(err).WithMeta("transport", transportName) 81 return 82 } 83 } 84 tcpKeepalivePeriod := time.Duration(0) 85 if config.TCPKeepalivePeriod != "" { 86 tcpKeepalivePeriod, err = time.ParseDuration(strings.TrimSpace(config.TCPKeepalivePeriod)) 87 if err != nil { 88 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("tcpKeepalivePeriod must be time.Duration format")).WithCause(err).WithMeta("transport", transportName) 89 return 90 } 91 } 92 93 maxRequestBodySize := uint64(4 * bytex.MEGABYTE) 94 if config.MaxRequestBodySize != "" { 95 maxRequestBodySize, err = bytex.ParseBytes(strings.TrimSpace(config.MaxRequestBodySize)) 96 if err != nil { 97 err = errors.Warning("fns: build server failed").WithCause(errors.Warning("maxRequestBodySize must be bytes format")).WithCause(err).WithMeta("transport", transportName) 98 return 99 } 100 } 101 102 reduceMemoryUsage := config.ReduceMemoryUsage 103 104 server := &fasthttp.Server{ 105 Handler: handlerAdaptor(handler, writeTimeout), 106 ErrorHandler: errorHandler, 107 Name: "", 108 Concurrency: 0, 109 ReadBufferSize: int(readBufferSize), 110 WriteBufferSize: int(writeBufferSize), 111 ReadTimeout: readTimeout, 112 WriteTimeout: writeTimeout, 113 MaxRequestsPerConn: config.MaxRequestsPerConn, 114 MaxIdleWorkerDuration: maxIdleWorkerDuration, 115 TCPKeepalivePeriod: tcpKeepalivePeriod, 116 MaxRequestBodySize: int(maxRequestBodySize), 117 DisableKeepalive: false, 118 TCPKeepalive: config.TCPKeepalive, 119 ReduceMemoryUsage: reduceMemoryUsage, 120 GetOnly: false, 121 DisablePreParseMultipartForm: true, 122 LogAllErrors: false, 123 SecureErrorLogMessage: false, 124 DisableHeaderNamesNormalizing: false, 125 SleepWhenConcurrencyLimitsExceeded: 10 * time.Second, 126 NoDefaultServerHeader: true, 127 NoDefaultDate: false, 128 NoDefaultContentType: false, 129 KeepHijackedConns: config.KeepHijackedConns, 130 CloseOnShutdown: true, 131 StreamRequestBody: config.StreamRequestBody, 132 ConnState: nil, 133 Logger: logs.ConvertToStandardLogger(log, logs.DebugLevel, false), 134 TLSConfig: srvTLS, 135 } 136 // http2 137 if config.Http2.Enable && srvTLS != nil { 138 http2.ConfigureServer(server, http2.ServerConfig{ 139 PingInterval: time.Duration(config.Http2.PingSeconds) * time.Second, 140 MaxConcurrentStreams: config.Http2.MaxConcurrentStreams, 141 Debug: false, 142 }) 143 } 144 145 srv = &Server{ 146 port: port, 147 preFork: config.Prefork, 148 lnf: lnf, 149 srv: server, 150 } 151 return 152 } 153 154 type Server struct { 155 port int 156 preFork bool 157 lnf ssl.ListenerFunc 158 srv *fasthttp.Server 159 } 160 161 func (srv *Server) preforkServe(ln net.Listener) (err error) { 162 if srv.lnf != nil { 163 ln = srv.lnf(ln) 164 } 165 err = srv.srv.Serve(ln) 166 return 167 } 168 169 func (srv *Server) ListenAndServe() (err error) { 170 if srv.preFork { 171 pf := prefork.New(srv.srv) 172 pf.ServeFunc = srv.preforkServe 173 err = pf.ListenAndServe(fmt.Sprintf(":%d", srv.port)) 174 if err != nil { 175 err = errors.Warning("fns: transport perfork listen and serve failed").WithCause(err) 176 return 177 } 178 return 179 } 180 ln, lnErr := net.Listen("tcp", fmt.Sprintf(":%d", srv.port)) 181 if lnErr != nil { 182 err = errors.Warning("fns: transport listen and serve failed").WithCause(lnErr) 183 return 184 } 185 if srv.lnf != nil { 186 ln = srv.lnf(ln) 187 } 188 err = srv.srv.Serve(ln) 189 if err != nil { 190 err = errors.Warning("fns: transport listen and serve failed").WithCause(err).WithMeta("transport", transportName) 191 return 192 } 193 return 194 } 195 196 func (srv *Server) Shutdown(ctx context.Context) (err error) { 197 err = srv.srv.ShutdownWithContext(ctx) 198 if err != nil { 199 err = errors.Warning("fns: transport shutdown failed").WithCause(err).WithMeta("transport", transportName) 200 } 201 return 202 }