github.com/gogf/gf@v1.16.9/net/ghttp/ghttp_server_config.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package ghttp 8 9 import ( 10 "context" 11 "crypto/tls" 12 "fmt" 13 "github.com/gogf/gf/internal/intlog" 14 "github.com/gogf/gf/os/gres" 15 "github.com/gogf/gf/util/gutil" 16 "net/http" 17 "strconv" 18 "time" 19 20 "github.com/gogf/gf/util/gconv" 21 22 "github.com/gogf/gf/os/gsession" 23 24 "github.com/gogf/gf/os/gview" 25 26 "github.com/gogf/gf/os/gfile" 27 "github.com/gogf/gf/os/glog" 28 ) 29 30 const ( 31 defaultHttpAddr = ":80" // Default listening port for HTTP. 32 defaultHttpsAddr = ":443" // Default listening port for HTTPS. 33 URI_TYPE_DEFAULT = 0 // Deprecated, please use UriTypeDefault instead. 34 URI_TYPE_FULLNAME = 1 // Deprecated, please use UriTypeFullName instead. 35 URI_TYPE_ALLLOWER = 2 // Deprecated, please use UriTypeAllLower instead. 36 URI_TYPE_CAMEL = 3 // Deprecated, please use UriTypeCamel instead. 37 UriTypeDefault = 0 // Method name to URI converting type, which converts name to its lower case and joins the words using char '-'. 38 UriTypeFullName = 1 // Method name to URI converting type, which does no converting to the method name. 39 UriTypeAllLower = 2 // Method name to URI converting type, which converts name to its lower case. 40 UriTypeCamel = 3 // Method name to URI converting type, which converts name to its camel case. 41 ) 42 43 // ServerConfig is the HTTP Server configuration manager. 44 type ServerConfig struct { 45 // ================================== 46 // Basic. 47 // ================================== 48 49 // Address specifies the server listening address like "port" or ":port", 50 // multiple addresses joined using ','. 51 Address string `json:"address"` 52 53 // HTTPSAddr specifies the HTTPS addresses, multiple addresses joined using char ','. 54 HTTPSAddr string `json:"httpsAddr"` 55 56 // HTTPSCertPath specifies certification file path for HTTPS service. 57 HTTPSCertPath string `json:"httpsCertPath"` 58 59 // HTTPSKeyPath specifies the key file path for HTTPS service. 60 HTTPSKeyPath string `json:"httpsKeyPath"` 61 62 // TLSConfig optionally provides a TLS configuration for use 63 // by ServeTLS and ListenAndServeTLS. Note that this value is 64 // cloned by ServeTLS and ListenAndServeTLS, so it's not 65 // possible to modify the configuration with methods like 66 // tls.Config.SetSessionTicketKeys. To use 67 // SetSessionTicketKeys, use Server.Serve with a TLS Listener 68 // instead. 69 TLSConfig *tls.Config `json:"tlsConfig"` 70 71 // Handler the handler for HTTP request. 72 Handler http.Handler `json:"-"` 73 74 // ReadTimeout is the maximum duration for reading the entire 75 // request, including the body. 76 // 77 // Because ReadTimeout does not let Handlers make per-request 78 // decisions on each request body's acceptable deadline or 79 // upload rate, most users will prefer to use 80 // ReadHeaderTimeout. It is valid to use them both. 81 ReadTimeout time.Duration `json:"readTimeout"` 82 83 // WriteTimeout is the maximum duration before timing out 84 // writes of the response. It is reset whenever a new 85 // request's header is read. Like ReadTimeout, it does not 86 // let Handlers make decisions on a per-request basis. 87 WriteTimeout time.Duration `json:"writeTimeout"` 88 89 // IdleTimeout is the maximum amount of time to wait for the 90 // next request when keep-alives are enabled. If IdleTimeout 91 // is zero, the value of ReadTimeout is used. If both are 92 // zero, there is no timeout. 93 IdleTimeout time.Duration `json:"idleTimeout"` 94 95 // MaxHeaderBytes controls the maximum number of bytes the 96 // server will read parsing the request header's keys and 97 // values, including the request line. It does not limit the 98 // size of the request body. 99 // 100 // It can be configured in configuration file using string like: 1m, 10m, 500kb etc. 101 // It's 10240 bytes in default. 102 MaxHeaderBytes int `json:"maxHeaderBytes"` 103 104 // KeepAlive enables HTTP keep-alive. 105 KeepAlive bool `json:"keepAlive"` 106 107 // ServerAgent specifies the server agent information, which is wrote to 108 // HTTP response header as "Server". 109 ServerAgent string `json:"serverAgent"` 110 111 // View specifies the default template view object for the server. 112 View *gview.View `json:"view"` 113 114 // ================================== 115 // Static. 116 // ================================== 117 118 // Rewrites specifies the URI rewrite rules map. 119 Rewrites map[string]string `json:"rewrites"` 120 121 // IndexFiles specifies the index files for static folder. 122 IndexFiles []string `json:"indexFiles"` 123 124 // IndexFolder specifies if listing sub-files when requesting folder. 125 // The server responses HTTP status code 403 if it is false. 126 IndexFolder bool `json:"indexFolder"` 127 128 // ServerRoot specifies the root directory for static service. 129 ServerRoot string `json:"serverRoot"` 130 131 // SearchPaths specifies additional searching directories for static service. 132 SearchPaths []string `json:"searchPaths"` 133 134 // StaticPaths specifies URI to directory mapping array. 135 StaticPaths []staticPathItem `json:"staticPaths"` 136 137 // FileServerEnabled is the global switch for static service. 138 // It is automatically set enabled if any static path is set. 139 FileServerEnabled bool `json:"fileServerEnabled"` 140 141 // ================================== 142 // Cookie. 143 // ================================== 144 145 // CookieMaxAge specifies the max TTL for cookie items. 146 CookieMaxAge time.Duration `json:"cookieMaxAge"` 147 148 // CookiePath specifies cookie path. 149 // It also affects the default storage for session id. 150 CookiePath string `json:"cookiePath"` 151 152 // CookieDomain specifies cookie domain. 153 // It also affects the default storage for session id. 154 CookieDomain string `json:"cookieDomain"` 155 156 // ================================== 157 // Session. 158 // ================================== 159 160 // SessionIdName specifies the session id name. 161 SessionIdName string `json:"sessionIdName"` 162 163 // SessionMaxAge specifies max TTL for session items. 164 SessionMaxAge time.Duration `json:"sessionMaxAge"` 165 166 // SessionPath specifies the session storage directory path for storing session files. 167 // It only makes sense if the session storage is type of file storage. 168 SessionPath string `json:"sessionPath"` 169 170 // SessionStorage specifies the session storage. 171 SessionStorage gsession.Storage `json:"sessionStorage"` 172 173 // SessionCookieMaxAge specifies the cookie ttl for session id. 174 // It it is set 0, it means it expires along with browser session. 175 SessionCookieMaxAge time.Duration `json:"sessionCookieMaxAge"` 176 177 // SessionCookieOutput specifies whether automatic outputting session id to cookie. 178 SessionCookieOutput bool `json:"sessionCookieOutput"` 179 180 // ================================== 181 // Logging. 182 // ================================== 183 Logger *glog.Logger `json:"logger"` // Logger specifies the logger for server. 184 LogPath string `json:"logPath"` // LogPath specifies the directory for storing logging files. 185 LogLevel string `json:"logLevel"` // LogLevel specifies the logging level for logger. 186 LogStdout bool `json:"logStdout"` // LogStdout specifies whether printing logging content to stdout. 187 ErrorStack bool `json:"errorStack"` // ErrorStack specifies whether logging stack information when error. 188 ErrorLogEnabled bool `json:"errorLogEnabled"` // ErrorLogEnabled enables error logging content to files. 189 ErrorLogPattern string `json:"errorLogPattern"` // ErrorLogPattern specifies the error log file pattern like: error-{Ymd}.log 190 AccessLogEnabled bool `json:"accessLogEnabled"` // AccessLogEnabled enables access logging content to files. 191 AccessLogPattern string `json:"accessLogPattern"` // AccessLogPattern specifies the error log file pattern like: access-{Ymd}.log 192 193 // ================================== 194 // PProf. 195 // ================================== 196 PProfEnabled bool `json:"pprofEnabled"` // PProfEnabled enables PProf feature. 197 PProfPattern string `json:"pprofPattern"` // PProfPattern specifies the PProf service pattern for router. 198 199 // ================================== 200 // Other. 201 // ================================== 202 203 // ClientMaxBodySize specifies the max body size limit in bytes for client request. 204 // It can be configured in configuration file using string like: 1m, 10m, 500kb etc. 205 // It's 8MB in default. 206 ClientMaxBodySize int64 `json:"clientMaxBodySize"` 207 208 // FormParsingMemory specifies max memory buffer size in bytes which can be used for 209 // parsing multimedia form. 210 // It can be configured in configuration file using string like: 1m, 10m, 500kb etc. 211 // It's 1MB in default. 212 FormParsingMemory int64 `json:"formParsingMemory"` 213 214 // NameToUriType specifies the type for converting struct method name to URI when 215 // registering routes. 216 NameToUriType int `json:"nameToUriType"` 217 218 // RouteOverWrite allows overwrite the route if duplicated. 219 RouteOverWrite bool `json:"routeOverWrite"` 220 221 // DumpRouterMap specifies whether automatically dumps router map when server starts. 222 DumpRouterMap bool `json:"dumpRouterMap"` 223 224 // Graceful enables graceful reload feature for all servers of the process. 225 Graceful bool `json:"graceful"` 226 227 // GracefulTimeout set the maximum survival time (seconds) of the parent process. 228 GracefulTimeout uint8 `json:"gracefulTimeout"` 229 } 230 231 // Config creates and returns a ServerConfig object with default configurations. 232 // Deprecated. Use NewConfig instead. 233 func Config() ServerConfig { 234 return NewConfig() 235 } 236 237 // NewConfig creates and returns a ServerConfig object with default configurations. 238 // Note that, do not define this default configuration to local package variable, as there are 239 // some pointer attributes that may be shared in different servers. 240 func NewConfig() ServerConfig { 241 return ServerConfig{ 242 Address: "", 243 HTTPSAddr: "", 244 Handler: nil, 245 ReadTimeout: 60 * time.Second, 246 WriteTimeout: 0, // No timeout. 247 IdleTimeout: 60 * time.Second, 248 MaxHeaderBytes: 10240, // 10KB 249 KeepAlive: true, 250 IndexFiles: []string{"index.html", "index.htm"}, 251 IndexFolder: false, 252 ServerAgent: "GF HTTP Server", 253 ServerRoot: "", 254 StaticPaths: make([]staticPathItem, 0), 255 FileServerEnabled: false, 256 CookieMaxAge: time.Hour * 24 * 365, 257 CookiePath: "/", 258 CookieDomain: "", 259 SessionIdName: "gfsessionid", 260 SessionPath: gsession.DefaultStorageFilePath, 261 SessionMaxAge: time.Hour * 24, 262 SessionCookieOutput: true, 263 SessionCookieMaxAge: time.Hour * 24, 264 Logger: glog.New(), 265 LogLevel: "all", 266 LogStdout: true, 267 ErrorStack: true, 268 ErrorLogEnabled: true, 269 ErrorLogPattern: "error-{Ymd}.log", 270 AccessLogEnabled: false, 271 AccessLogPattern: "access-{Ymd}.log", 272 DumpRouterMap: true, 273 ClientMaxBodySize: 8 * 1024 * 1024, // 8MB 274 FormParsingMemory: 1024 * 1024, // 1MB 275 Rewrites: make(map[string]string), 276 Graceful: false, 277 GracefulTimeout: 2, // seconds 278 } 279 } 280 281 // ConfigFromMap creates and returns a ServerConfig object with given map and 282 // default configuration object. 283 func ConfigFromMap(m map[string]interface{}) (ServerConfig, error) { 284 config := NewConfig() 285 if err := gconv.Struct(m, &config); err != nil { 286 return config, err 287 } 288 return config, nil 289 } 290 291 // SetConfigWithMap sets the configuration for the server using map. 292 func (s *Server) SetConfigWithMap(m map[string]interface{}) error { 293 // The m now is a shallow copy of m. 294 // Any changes to m does not affect the original one. 295 // A little tricky, isn't it? 296 m = gutil.MapCopy(m) 297 // Allow setting the size configuration items using string size like: 298 // 1m, 100mb, 512kb, etc. 299 if k, v := gutil.MapPossibleItemByKey(m, "MaxHeaderBytes"); k != "" { 300 m[k] = gfile.StrToSize(gconv.String(v)) 301 } 302 if k, v := gutil.MapPossibleItemByKey(m, "ClientMaxBodySize"); k != "" { 303 m[k] = gfile.StrToSize(gconv.String(v)) 304 } 305 if k, v := gutil.MapPossibleItemByKey(m, "FormParsingMemory"); k != "" { 306 m[k] = gfile.StrToSize(gconv.String(v)) 307 } 308 // Update the current configuration object. 309 // It only updates the configured keys not all the object. 310 if err := gconv.Struct(m, &s.config); err != nil { 311 return err 312 } 313 return s.SetConfig(s.config) 314 } 315 316 // SetConfig sets the configuration for the server. 317 func (s *Server) SetConfig(c ServerConfig) error { 318 s.config = c 319 // Static. 320 if c.ServerRoot != "" { 321 s.SetServerRoot(c.ServerRoot) 322 } 323 if len(c.SearchPaths) > 0 { 324 paths := c.SearchPaths 325 c.SearchPaths = []string{} 326 for _, v := range paths { 327 s.AddSearchPath(v) 328 } 329 } 330 // HTTPS. 331 if c.TLSConfig == nil && c.HTTPSCertPath != "" { 332 s.EnableHTTPS(c.HTTPSCertPath, c.HTTPSKeyPath) 333 } 334 // Logging. 335 if s.config.LogPath != "" && s.config.LogPath != s.config.Logger.GetPath() { 336 if err := s.config.Logger.SetPath(s.config.LogPath); err != nil { 337 return err 338 } 339 } 340 if err := s.config.Logger.SetLevelStr(s.config.LogLevel); err != nil { 341 intlog.Error(context.TODO(), err) 342 } 343 344 SetGraceful(c.Graceful) 345 intlog.Printf(context.TODO(), "SetConfig: %+v", s.config) 346 return nil 347 } 348 349 // SetAddr sets the listening address for the server. 350 // The address is like ':80', '0.0.0.0:80', '127.0.0.1:80', '180.18.99.10:80', etc. 351 func (s *Server) SetAddr(address string) { 352 s.config.Address = address 353 } 354 355 // SetPort sets the listening ports for the server. 356 // The listening ports can be multiple like: SetPort(80, 8080). 357 func (s *Server) SetPort(port ...int) { 358 if len(port) > 0 { 359 s.config.Address = "" 360 for _, v := range port { 361 if len(s.config.Address) > 0 { 362 s.config.Address += "," 363 } 364 s.config.Address += ":" + strconv.Itoa(v) 365 } 366 } 367 } 368 369 // SetHTTPSAddr sets the HTTPS listening ports for the server. 370 func (s *Server) SetHTTPSAddr(address string) { 371 s.config.HTTPSAddr = address 372 } 373 374 // SetHTTPSPort sets the HTTPS listening ports for the server. 375 // The listening ports can be multiple like: SetHTTPSPort(443, 500). 376 func (s *Server) SetHTTPSPort(port ...int) { 377 if len(port) > 0 { 378 s.config.HTTPSAddr = "" 379 for _, v := range port { 380 if len(s.config.HTTPSAddr) > 0 { 381 s.config.HTTPSAddr += "," 382 } 383 s.config.HTTPSAddr += ":" + strconv.Itoa(v) 384 } 385 } 386 } 387 388 // EnableHTTPS enables HTTPS with given certification and key files for the server. 389 // The optional parameter <tlsConfig> specifies custom TLS configuration. 390 func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config) { 391 certFileRealPath := gfile.RealPath(certFile) 392 if certFileRealPath == "" { 393 certFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + certFile) 394 if certFileRealPath == "" { 395 certFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + certFile) 396 } 397 } 398 // Resource. 399 if certFileRealPath == "" && gres.Contains(certFile) { 400 certFileRealPath = certFile 401 } 402 if certFileRealPath == "" { 403 s.Logger().Fatal(fmt.Sprintf(`EnableHTTPS failed: certFile "%s" does not exist`, certFile)) 404 } 405 keyFileRealPath := gfile.RealPath(keyFile) 406 if keyFileRealPath == "" { 407 keyFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + keyFile) 408 if keyFileRealPath == "" { 409 keyFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + keyFile) 410 } 411 } 412 // Resource. 413 if keyFileRealPath == "" && gres.Contains(keyFile) { 414 keyFileRealPath = keyFile 415 } 416 if keyFileRealPath == "" { 417 s.Logger().Fatal(fmt.Sprintf(`EnableHTTPS failed: keyFile "%s" does not exist`, keyFile)) 418 } 419 s.config.HTTPSCertPath = certFileRealPath 420 s.config.HTTPSKeyPath = keyFileRealPath 421 if len(tlsConfig) > 0 { 422 s.config.TLSConfig = tlsConfig[0] 423 } 424 } 425 426 // SetTLSConfig sets custom TLS configuration and enables HTTPS feature for the server. 427 func (s *Server) SetTLSConfig(tlsConfig *tls.Config) { 428 s.config.TLSConfig = tlsConfig 429 } 430 431 // SetReadTimeout sets the ReadTimeout for the server. 432 func (s *Server) SetReadTimeout(t time.Duration) { 433 s.config.ReadTimeout = t 434 } 435 436 // SetWriteTimeout sets the WriteTimeout for the server. 437 func (s *Server) SetWriteTimeout(t time.Duration) { 438 s.config.WriteTimeout = t 439 } 440 441 // SetIdleTimeout sets the IdleTimeout for the server. 442 func (s *Server) SetIdleTimeout(t time.Duration) { 443 s.config.IdleTimeout = t 444 } 445 446 // SetMaxHeaderBytes sets the MaxHeaderBytes for the server. 447 func (s *Server) SetMaxHeaderBytes(b int) { 448 s.config.MaxHeaderBytes = b 449 } 450 451 // SetServerAgent sets the ServerAgent for the server. 452 func (s *Server) SetServerAgent(agent string) { 453 s.config.ServerAgent = agent 454 } 455 456 // SetKeepAlive sets the KeepAlive for the server. 457 func (s *Server) SetKeepAlive(enabled bool) { 458 s.config.KeepAlive = enabled 459 } 460 461 // SetView sets the View for the server. 462 func (s *Server) SetView(view *gview.View) { 463 s.config.View = view 464 } 465 466 // GetName returns the name of the server. 467 func (s *Server) GetName() string { 468 return s.name 469 } 470 471 // Handler returns the request handler of the server. 472 func (s *Server) Handler() http.Handler { 473 if s.config.Handler == nil { 474 return s 475 } 476 return s.config.Handler 477 }