ghttp_server_config.go 15 KB

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