github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/transports/standard/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 standard 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 "net" 30 "net/http" 31 "strings" 32 "time" 33 ) 34 35 func newServer(log logs.Logger, port int, tlsConfig ssl.Config, config *Config, handler transports.Handler) (srv *Server, err error) { 36 var srvTLS *tls.Config 37 var lnf ssl.ListenerFunc 38 if tlsConfig != nil { 39 srvTLS, lnf = tlsConfig.Server() 40 } 41 42 maxRequestHeaderSize := uint64(0) 43 if config.MaxRequestHeaderSize != "" { 44 maxRequestHeaderSize, err = bytex.ParseBytes(strings.TrimSpace(config.MaxRequestHeaderSize)) 45 if err != nil { 46 err = errors.Warning("http: build server failed").WithCause(errors.Warning("maxRequestHeaderSize is invalid").WithCause(err).WithMeta("hit", "format must be bytes")) 47 return 48 } 49 } 50 maxRequestBodySize := uint64(0) 51 if config.MaxRequestBodySize != "" { 52 maxRequestBodySize, err = bytex.ParseBytes(strings.TrimSpace(config.MaxRequestBodySize)) 53 if err != nil { 54 err = errors.Warning("http: build server failed").WithCause(errors.Warning("maxRequestBodySize is invalid").WithCause(err).WithMeta("hit", "format must be bytes")) 55 return 56 } 57 } 58 if maxRequestBodySize == 0 { 59 maxRequestBodySize = 4 * bytex.MEGABYTE 60 } 61 readTimeout := 10 * time.Second 62 if config.ReadTimeout != "" { 63 readTimeout, err = time.ParseDuration(strings.TrimSpace(config.ReadTimeout)) 64 if err != nil { 65 err = errors.Warning("http: build server failed").WithCause(errors.Warning("readTimeout is invalid").WithCause(err).WithMeta("hit", "format must time.Duration")) 66 return 67 } 68 } 69 readHeaderTimeout := 5 * time.Second 70 if config.ReadHeaderTimeout != "" { 71 readHeaderTimeout, err = time.ParseDuration(strings.TrimSpace(config.ReadHeaderTimeout)) 72 if err != nil { 73 err = errors.Warning("http: build server failed").WithCause(errors.Warning("readHeaderTimeout is invalid").WithCause(err).WithMeta("hit", "format must time.Duration")) 74 return 75 } 76 } 77 writeTimeout := 10 * time.Second 78 if config.WriteTimeout != "" { 79 writeTimeout, err = time.ParseDuration(strings.TrimSpace(config.WriteTimeout)) 80 if err != nil { 81 err = errors.Warning("http: build server failed").WithCause(errors.Warning("writeTimeout is invalid").WithCause(err).WithMeta("hit", "format must time.Duration")) 82 return 83 } 84 } 85 idleTimeout := 30 * time.Second 86 if config.IdleTimeout != "" { 87 idleTimeout, err = time.ParseDuration(strings.TrimSpace(config.IdleTimeout)) 88 if err != nil { 89 err = errors.Warning("http: build server failed").WithCause(errors.Warning("idleTimeout is invalid").WithCause(err).WithMeta("hit", "format must time.Duration")) 90 return 91 } 92 } 93 94 server := &http.Server{ 95 Addr: fmt.Sprintf(":%d", port), 96 Handler: HttpTransportHandlerAdaptor(handler, int(maxRequestBodySize), writeTimeout), 97 DisableGeneralOptionsHandler: false, 98 TLSConfig: srvTLS, 99 ReadTimeout: readTimeout, 100 ReadHeaderTimeout: readHeaderTimeout, 101 WriteTimeout: writeTimeout, 102 IdleTimeout: idleTimeout, 103 MaxHeaderBytes: int(maxRequestHeaderSize), 104 ErrorLog: logs.ConvertToStandardLogger(log, logs.DebugLevel, false), 105 } 106 107 srv = &Server{ 108 port: port, 109 lnf: lnf, 110 srv: server, 111 } 112 return 113 } 114 115 type Server struct { 116 port int 117 lnf ssl.ListenerFunc 118 srv *http.Server 119 } 120 121 func (srv *Server) ListenAndServe() (err error) { 122 ln, lnErr := net.Listen("tcp", fmt.Sprintf(":%d", srv.port)) 123 if lnErr != nil { 124 err = errors.Warning("fns: transport listen and serve failed").WithCause(lnErr) 125 return 126 } 127 if srv.lnf != nil { 128 ln = srv.lnf(ln) 129 } 130 if srv.srv.TLSConfig == nil { 131 err = srv.srv.Serve(ln) 132 } else { 133 err = srv.srv.ServeTLS(ln, "", "") 134 } 135 if err != nil { 136 err = errors.Warning("fns: transport listen and serve failed").WithCause(err).WithMeta("transport", transportName) 137 return 138 } 139 return 140 } 141 142 func (srv *Server) Shutdown(ctx context.Context) (err error) { 143 err = srv.srv.Shutdown(ctx) 144 if err != nil { 145 err = errors.Warning("fns: transport shutdown failed").WithCause(err).WithMeta("transport", transportName) 146 } 147 return 148 }