You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1303 lines
45KB

  1. package iris
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "os/user"
  7. "path/filepath"
  8. "runtime"
  9. "strings"
  10. "time"
  11. "github.com/kataras/golog"
  12. "github.com/kataras/iris/v12/context"
  13. "github.com/kataras/iris/v12/core/netutil"
  14. "github.com/BurntSushi/toml"
  15. "github.com/kataras/sitemap"
  16. "github.com/kataras/tunnel"
  17. "gopkg.in/yaml.v3"
  18. )
  19. const globalConfigurationKeyword = "~"
  20. // homeConfigurationFilename returns the physical location of the global configuration(yaml or toml) file.
  21. // This is useful when we run multiple iris servers that share the same
  22. // configuration, even with custom values at its "Other" field.
  23. // It will return a file location
  24. // which targets to $HOME or %HOMEDRIVE%+%HOMEPATH% + "iris" + the given "ext".
  25. func homeConfigurationFilename(ext string) string {
  26. return filepath.Join(homeDir(), "iris"+ext)
  27. }
  28. func homeDir() (home string) {
  29. u, err := user.Current()
  30. if u != nil && err == nil {
  31. home = u.HomeDir
  32. }
  33. if home == "" {
  34. home = os.Getenv("HOME")
  35. }
  36. if home == "" {
  37. if runtime.GOOS == "plan9" {
  38. home = os.Getenv("home")
  39. } else if runtime.GOOS == "windows" {
  40. home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
  41. if home == "" {
  42. home = os.Getenv("USERPROFILE")
  43. }
  44. }
  45. }
  46. return
  47. }
  48. func parseYAML(filename string) (Configuration, error) {
  49. c := DefaultConfiguration()
  50. // get the abs
  51. // which will try to find the 'filename' from current workind dir too.
  52. yamlAbsPath, err := filepath.Abs(filename)
  53. if err != nil {
  54. return c, fmt.Errorf("parse yaml: %w", err)
  55. }
  56. // read the raw contents of the file
  57. data, err := ioutil.ReadFile(yamlAbsPath)
  58. if err != nil {
  59. return c, fmt.Errorf("parse yaml: %w", err)
  60. }
  61. // put the file's contents as yaml to the default configuration(c)
  62. if err := yaml.Unmarshal(data, &c); err != nil {
  63. return c, fmt.Errorf("parse yaml: %w", err)
  64. }
  65. return c, nil
  66. }
  67. // YAML reads Configuration from a configuration.yml file.
  68. //
  69. // Accepts the absolute path of the cfg.yml.
  70. // An error will be shown to the user via panic with the error message.
  71. // Error may occur when the cfg.yml does not exist or is not formatted correctly.
  72. //
  73. // Note: if the char '~' passed as "filename" then it tries to load and return
  74. // the configuration from the $home_directory + iris.yml,
  75. // see `WithGlobalConfiguration` for more information.
  76. //
  77. // Usage:
  78. // app.Configure(iris.WithConfiguration(iris.YAML("myconfig.yml"))) or
  79. // app.Run([iris.Runner], iris.WithConfiguration(iris.YAML("myconfig.yml"))).
  80. func YAML(filename string) Configuration {
  81. // check for globe configuration file and use that, otherwise
  82. // return the default configuration if file doesn't exist.
  83. if filename == globalConfigurationKeyword {
  84. filename = homeConfigurationFilename(".yml")
  85. if _, err := os.Stat(filename); os.IsNotExist(err) {
  86. panic("default configuration file '" + filename + "' does not exist")
  87. }
  88. }
  89. c, err := parseYAML(filename)
  90. if err != nil {
  91. panic(err)
  92. }
  93. return c
  94. }
  95. // TOML reads Configuration from a toml-compatible document file.
  96. // Read more about toml's implementation at:
  97. // https://github.com/toml-lang/toml
  98. //
  99. //
  100. // Accepts the absolute path of the configuration file.
  101. // An error will be shown to the user via panic with the error message.
  102. // Error may occur when the file does not exist or is not formatted correctly.
  103. //
  104. // Note: if the char '~' passed as "filename" then it tries to load and return
  105. // the configuration from the $home_directory + iris.tml,
  106. // see `WithGlobalConfiguration` for more information.
  107. //
  108. // Usage:
  109. // app.Configure(iris.WithConfiguration(iris.TOML("myconfig.tml"))) or
  110. // app.Run([iris.Runner], iris.WithConfiguration(iris.TOML("myconfig.tml"))).
  111. func TOML(filename string) Configuration {
  112. c := DefaultConfiguration()
  113. // check for globe configuration file and use that, otherwise
  114. // return the default configuration if file doesn't exist.
  115. if filename == globalConfigurationKeyword {
  116. filename = homeConfigurationFilename(".tml")
  117. if _, err := os.Stat(filename); os.IsNotExist(err) {
  118. panic("default configuration file '" + filename + "' does not exist")
  119. }
  120. }
  121. // get the abs
  122. // which will try to find the 'filename' from current workind dir too.
  123. tomlAbsPath, err := filepath.Abs(filename)
  124. if err != nil {
  125. panic(fmt.Errorf("toml: %w", err))
  126. }
  127. // read the raw contents of the file
  128. data, err := ioutil.ReadFile(tomlAbsPath)
  129. if err != nil {
  130. panic(fmt.Errorf("toml :%w", err))
  131. }
  132. // put the file's contents as toml to the default configuration(c)
  133. if _, err := toml.Decode(string(data), &c); err != nil {
  134. panic(fmt.Errorf("toml :%w", err))
  135. }
  136. // Author's notes:
  137. // The toml's 'usual thing' for key naming is: the_config_key instead of TheConfigKey
  138. // but I am always prefer to use the specific programming language's syntax
  139. // and the original configuration name fields for external configuration files
  140. // so we do 'toml: "TheConfigKeySameAsTheConfigField" instead.
  141. return c
  142. }
  143. // Configurator is just an interface which accepts the framework instance.
  144. //
  145. // It can be used to register a custom configuration with `Configure` in order
  146. // to modify the framework instance.
  147. //
  148. // Currently Configurator is being used to describe the configuration's fields values.
  149. type Configurator func(*Application)
  150. // WithGlobalConfiguration will load the global yaml configuration file
  151. // from the home directory and it will set/override the whole app's configuration
  152. // to that file's contents. The global configuration file can be modified by user
  153. // and be used by multiple iris instances.
  154. //
  155. // This is useful when we run multiple iris servers that share the same
  156. // configuration, even with custom values at its "Other" field.
  157. //
  158. // Usage: `app.Configure(iris.WithGlobalConfiguration)` or `app.Run([iris.Runner], iris.WithGlobalConfiguration)`.
  159. var WithGlobalConfiguration = func(app *Application) {
  160. app.Configure(WithConfiguration(YAML(globalConfigurationKeyword)))
  161. }
  162. // WithLogLevel sets the `Configuration.LogLevel` field.
  163. func WithLogLevel(level string) Configurator {
  164. return func(app *Application) {
  165. if app.logger == nil {
  166. app.logger = golog.Default
  167. }
  168. app.logger.SetLevel(level) // can be fired through app.Configure.
  169. app.config.LogLevel = level
  170. }
  171. }
  172. // WithSocketSharding sets the `Configuration.SocketSharding` field to true.
  173. func WithSocketSharding(app *Application) {
  174. // Note(@kataras): It could be a host Configurator but it's an application setting in order
  175. // to configure it through yaml/toml files as well.
  176. app.config.SocketSharding = true
  177. }
  178. // WithKeepAlive sets the `Configuration.KeepAlive` field to the given duration.
  179. func WithKeepAlive(keepAliveDur time.Duration) Configurator {
  180. return func(app *Application) {
  181. app.config.KeepAlive = keepAliveDur
  182. }
  183. }
  184. // WithoutServerError will cause to ignore the matched "errors"
  185. // from the main application's `Run/Listen` function.
  186. //
  187. // Usage:
  188. // err := app.Listen(":8080", iris.WithoutServerError(iris.ErrServerClosed))
  189. // will return `nil` if the server's error was `http/iris#ErrServerClosed`.
  190. //
  191. // See `Configuration#IgnoreServerErrors []string` too.
  192. //
  193. // Example: https://github.com/kataras/iris/tree/master/_examples/http-server/listen-addr/omit-server-errors
  194. func WithoutServerError(errors ...error) Configurator {
  195. return func(app *Application) {
  196. if len(errors) == 0 {
  197. return
  198. }
  199. errorsAsString := make([]string, len(errors))
  200. for i, e := range errors {
  201. errorsAsString[i] = e.Error()
  202. }
  203. app.config.IgnoreServerErrors = append(app.config.IgnoreServerErrors, errorsAsString...)
  204. }
  205. }
  206. // WithoutStartupLog turns off the information send, once, to the terminal when the main server is open.
  207. var WithoutStartupLog = func(app *Application) {
  208. app.config.DisableStartupLog = true
  209. }
  210. // WithoutBanner is a conversion for the `WithoutStartupLog` option.
  211. //
  212. // Turns off the information send, once, to the terminal when the main server is open.
  213. var WithoutBanner = WithoutStartupLog
  214. // WithoutInterruptHandler disables the automatic graceful server shutdown
  215. // when control/cmd+C pressed.
  216. var WithoutInterruptHandler = func(app *Application) {
  217. app.config.DisableInterruptHandler = true
  218. }
  219. // WithoutPathCorrection disables the PathCorrection setting.
  220. //
  221. // See `Configuration`.
  222. var WithoutPathCorrection = func(app *Application) {
  223. app.config.DisablePathCorrection = true
  224. }
  225. // WithPathIntelligence enables the EnablePathIntelligence setting.
  226. //
  227. // See `Configuration`.
  228. var WithPathIntelligence = func(app *Application) {
  229. app.config.EnablePathIntelligence = true
  230. }
  231. // WithoutPathCorrectionRedirection disables the PathCorrectionRedirection setting.
  232. //
  233. // See `Configuration`.
  234. var WithoutPathCorrectionRedirection = func(app *Application) {
  235. app.config.DisablePathCorrection = false
  236. app.config.DisablePathCorrectionRedirection = true
  237. }
  238. // WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting.
  239. //
  240. // See `Configuration`.
  241. var WithoutBodyConsumptionOnUnmarshal = func(app *Application) {
  242. app.config.DisableBodyConsumptionOnUnmarshal = true
  243. }
  244. // WithEmptyFormError enables the setting `FireEmptyFormError`.
  245. //
  246. // See `Configuration`.
  247. var WithEmptyFormError = func(app *Application) {
  248. app.config.FireEmptyFormError = true
  249. }
  250. // WithPathEscape sets the EnablePathEscape setting to true.
  251. //
  252. // See `Configuration`.
  253. var WithPathEscape = func(app *Application) {
  254. app.config.EnablePathEscape = true
  255. }
  256. // WithLowercaseRouting enables for lowercase routing by
  257. // setting the `ForceLowercaseRoutes` to true.
  258. //
  259. // See `Configuration`.
  260. var WithLowercaseRouting = func(app *Application) {
  261. app.config.ForceLowercaseRouting = true
  262. }
  263. // WithOptimizations can force the application to optimize for the best performance where is possible.
  264. //
  265. // See `Configuration`.
  266. var WithOptimizations = func(app *Application) {
  267. app.config.EnableOptimizations = true
  268. }
  269. // WithFireMethodNotAllowed enables the FireMethodNotAllowed setting.
  270. //
  271. // See `Configuration`.
  272. var WithFireMethodNotAllowed = func(app *Application) {
  273. app.config.FireMethodNotAllowed = true
  274. }
  275. // WithoutAutoFireStatusCode sets the DisableAutoFireStatusCode setting to true.
  276. //
  277. // See `Configuration`.
  278. var WithoutAutoFireStatusCode = func(app *Application) {
  279. app.config.DisableAutoFireStatusCode = true
  280. }
  281. // WithResetOnFireErrorCode sets the ResetOnFireErrorCode setting to true.
  282. //
  283. // See `Configuration`.
  284. var WithResetOnFireErrorCode = func(app *Application) {
  285. app.config.ResetOnFireErrorCode = true
  286. }
  287. // WithTimeFormat sets the TimeFormat setting.
  288. //
  289. // See `Configuration`.
  290. func WithTimeFormat(timeformat string) Configurator {
  291. return func(app *Application) {
  292. app.config.TimeFormat = timeformat
  293. }
  294. }
  295. // WithCharset sets the Charset setting.
  296. //
  297. // See `Configuration`.
  298. func WithCharset(charset string) Configurator {
  299. return func(app *Application) {
  300. app.config.Charset = charset
  301. }
  302. }
  303. // WithPostMaxMemory sets the maximum post data size
  304. // that a client can send to the server, this differs
  305. // from the overall request body size which can be modified
  306. // by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
  307. //
  308. // Defaults to 32MB or 32 << 20 or 32*iris.MB if you prefer.
  309. func WithPostMaxMemory(limit int64) Configurator {
  310. return func(app *Application) {
  311. app.config.PostMaxMemory = limit
  312. }
  313. }
  314. // WithRemoteAddrHeader adds a new request header name
  315. // that can be used to validate the client's real IP.
  316. func WithRemoteAddrHeader(header ...string) Configurator {
  317. return func(app *Application) {
  318. for _, h := range header {
  319. exists := false
  320. for _, v := range app.config.RemoteAddrHeaders {
  321. if v == h {
  322. exists = true
  323. }
  324. }
  325. if !exists {
  326. app.config.RemoteAddrHeaders = append(app.config.RemoteAddrHeaders, h)
  327. }
  328. }
  329. }
  330. }
  331. // WithoutRemoteAddrHeader removes an existing request header name
  332. // that can be used to validate and parse the client's real IP.
  333. //
  334. // Look `context.RemoteAddr()` for more.
  335. func WithoutRemoteAddrHeader(headerName string) Configurator {
  336. return func(app *Application) {
  337. tmp := app.config.RemoteAddrHeaders[:0]
  338. for _, v := range app.config.RemoteAddrHeaders {
  339. if v != headerName {
  340. tmp = append(tmp, v)
  341. }
  342. }
  343. app.config.RemoteAddrHeaders = tmp
  344. }
  345. }
  346. // WithRemoteAddrPrivateSubnet adds a new private sub-net to be excluded from `context.RemoteAddr`.
  347. // See `WithRemoteAddrHeader` too.
  348. func WithRemoteAddrPrivateSubnet(startIP, endIP string) Configurator {
  349. return func(app *Application) {
  350. app.config.RemoteAddrPrivateSubnets = append(app.config.RemoteAddrPrivateSubnets, netutil.IPRange{
  351. Start: startIP,
  352. End: endIP,
  353. })
  354. }
  355. }
  356. // WithSSLProxyHeader sets a SSLProxyHeaders key value pair.
  357. // Example: WithSSLProxyHeader("X-Forwarded-Proto", "https").
  358. // See `Context.IsSSL` for more.
  359. func WithSSLProxyHeader(headerKey, headerValue string) Configurator {
  360. return func(app *Application) {
  361. if app.config.SSLProxyHeaders == nil {
  362. app.config.SSLProxyHeaders = make(map[string]string)
  363. }
  364. app.config.SSLProxyHeaders[headerKey] = headerValue
  365. }
  366. }
  367. // WithHostProxyHeader sets a HostProxyHeaders key value pair.
  368. // Example: WithHostProxyHeader("X-Host").
  369. // See `Context.Host` for more.
  370. func WithHostProxyHeader(headers ...string) Configurator {
  371. return func(app *Application) {
  372. if app.config.HostProxyHeaders == nil {
  373. app.config.HostProxyHeaders = make(map[string]bool)
  374. }
  375. for _, k := range headers {
  376. app.config.HostProxyHeaders[k] = true
  377. }
  378. }
  379. }
  380. // WithOtherValue adds a value based on a key to the Other setting.
  381. //
  382. // See `Configuration.Other`.
  383. func WithOtherValue(key string, val interface{}) Configurator {
  384. return func(app *Application) {
  385. if app.config.Other == nil {
  386. app.config.Other = make(map[string]interface{})
  387. }
  388. app.config.Other[key] = val
  389. }
  390. }
  391. // WithSitemap enables the sitemap generator.
  392. // Use the Route's `SetLastMod`, `SetChangeFreq` and `SetPriority` to modify
  393. // the sitemap's URL child element properties.
  394. // Excluded routes:
  395. // - dynamic
  396. // - subdomain
  397. // - offline
  398. // - ExcludeSitemap method called
  399. //
  400. // It accepts a "startURL" input argument which
  401. // is the prefix for the registered routes that will be included in the sitemap.
  402. //
  403. // If more than 50,000 static routes are registered then sitemaps will be splitted and a sitemap index will be served in
  404. // /sitemap.xml.
  405. //
  406. // If `Application.I18n.Load/LoadAssets` is called then the sitemap will contain translated links for each static route.
  407. //
  408. // If the result does not complete your needs you can take control
  409. // and use the github.com/kataras/sitemap package to generate a customized one instead.
  410. //
  411. // Example: https://github.com/kataras/iris/tree/master/_examples/sitemap.
  412. func WithSitemap(startURL string) Configurator {
  413. sitemaps := sitemap.New(startURL)
  414. return func(app *Application) {
  415. var defaultLang string
  416. if tags := app.I18n.Tags(); len(tags) > 0 {
  417. defaultLang = tags[0].String()
  418. sitemaps.DefaultLang(defaultLang)
  419. }
  420. for _, r := range app.GetRoutes() {
  421. if !r.IsStatic() || r.Subdomain != "" || !r.IsOnline() || r.NoSitemap {
  422. continue
  423. }
  424. loc := r.StaticPath()
  425. var translatedLinks []sitemap.Link
  426. for _, tag := range app.I18n.Tags() {
  427. lang := tag.String()
  428. langPath := lang
  429. href := ""
  430. if lang == defaultLang {
  431. // http://domain.com/en-US/path to just http://domain.com/path if en-US is the default language.
  432. langPath = ""
  433. }
  434. if app.I18n.PathRedirect {
  435. // then use the path prefix.
  436. // e.g. http://domain.com/el-GR/path
  437. if langPath == "" { // fix double slashes http://domain.com// when self-included default language.
  438. href = loc
  439. } else {
  440. href = "/" + langPath + loc
  441. }
  442. } else if app.I18n.Subdomain {
  443. // then use the subdomain.
  444. // e.g. http://el.domain.com/path
  445. scheme := netutil.ResolveSchemeFromVHost(startURL)
  446. host := strings.TrimLeft(startURL, scheme)
  447. if langPath != "" {
  448. href = scheme + strings.Split(langPath, "-")[0] + "." + host + loc
  449. } else {
  450. href = loc
  451. }
  452. } else if p := app.I18n.URLParameter; p != "" {
  453. // then use the URL parameter.
  454. // e.g. http://domain.com/path?lang=el-GR
  455. href = loc + "?" + p + "=" + lang
  456. } else {
  457. // then skip it, we can't generate the link at this state.
  458. continue
  459. }
  460. translatedLinks = append(translatedLinks, sitemap.Link{
  461. Rel: "alternate",
  462. Hreflang: lang,
  463. Href: href,
  464. })
  465. }
  466. sitemaps.URL(sitemap.URL{
  467. Loc: loc,
  468. LastMod: r.LastMod,
  469. ChangeFreq: r.ChangeFreq,
  470. Priority: r.Priority,
  471. Links: translatedLinks,
  472. })
  473. }
  474. for _, s := range sitemaps.Build() {
  475. contentCopy := make([]byte, len(s.Content))
  476. copy(contentCopy, s.Content)
  477. handler := func(ctx Context) {
  478. ctx.ContentType(context.ContentXMLHeaderValue)
  479. ctx.Write(contentCopy) // nolint:errcheck
  480. }
  481. if app.builded {
  482. routes := app.CreateRoutes([]string{MethodGet, MethodHead, MethodOptions}, s.Path, handler)
  483. for _, r := range routes {
  484. if err := app.Router.AddRouteUnsafe(r); err != nil {
  485. app.Logger().Errorf("sitemap route: %v", err)
  486. }
  487. }
  488. } else {
  489. app.HandleMany("GET HEAD OPTIONS", s.Path, handler)
  490. }
  491. }
  492. }
  493. }
  494. // WithTunneling is the `iris.Configurator` for the `iris.Configuration.Tunneling` field.
  495. // It's used to enable http tunneling for an Iris Application, per registered host
  496. //
  497. // Alternatively use the `iris.WithConfiguration(iris.Configuration{Tunneling: iris.TunnelingConfiguration{ ...}}}`.
  498. var WithTunneling = func(app *Application) {
  499. conf := TunnelingConfiguration{
  500. Tunnels: []Tunnel{{}}, // create empty tunnel, its addr and name are set right before host serve.
  501. }
  502. app.config.Tunneling = conf
  503. }
  504. type (
  505. // TunnelingConfiguration contains configuration
  506. // for the optional tunneling through ngrok feature.
  507. // Note that the ngrok should be already installed at the host machine.
  508. TunnelingConfiguration = tunnel.Configuration
  509. // Tunnel is the Tunnels field of the TunnelingConfiguration structure.
  510. Tunnel = tunnel.Tunnel
  511. )
  512. // Configuration holds the necessary settings for an Iris Application instance.
  513. // All fields are optionally, the default values will work for a common web application.
  514. //
  515. // A Configuration value can be passed through `WithConfiguration` Configurator.
  516. // Usage:
  517. // conf := iris.Configuration{ ... }
  518. // app := iris.New()
  519. // app.Configure(iris.WithConfiguration(conf)) OR
  520. // app.Run/Listen(..., iris.WithConfiguration(conf)).
  521. type Configuration struct {
  522. // vhost is private and set only with .Run/Listen methods, it cannot be changed after the first set.
  523. // It can be retrieved by the context if needed (i.e router for subdomains)
  524. vhost string
  525. // LogLevel is the log level the application should use to output messages.
  526. // Logger, by default, is mostly used on Build state but it is also possible
  527. // that debug error messages could be thrown when the app is running, e.g.
  528. // when malformed data structures try to be sent on Client (i.e Context.JSON/JSONP/XML...).
  529. //
  530. // Defaults to "info". Possible values are:
  531. // * "disable"
  532. // * "fatal"
  533. // * "error"
  534. // * "warn"
  535. // * "info"
  536. // * "debug"
  537. LogLevel string `ini:"log_level" json:"logLevel" yaml:"LogLevel" toml:"LogLevel" env:"LOG_LEVEL"`
  538. // SocketSharding enables SO_REUSEPORT (or SO_REUSEADDR for windows)
  539. // on all registered Hosts.
  540. // This option allows linear scaling server performance on multi-CPU servers.
  541. //
  542. // Please read the following:
  543. // 1. https://stackoverflow.com/a/14388707
  544. // 2. https://stackoverflow.com/a/59692868
  545. // 3. https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
  546. // 4. (BOOK) Learning HTTP/2: A Practical Guide for Beginners:
  547. // Page 37, To Shard or Not to Shard?
  548. //
  549. // Defaults to false.
  550. SocketSharding bool `ini:"socket_sharding" json:"socketSharding" yaml:"SocketSharding" toml:"SocketSharding" env:"SOCKET_SHARDING"`
  551. // KeepAlive sets the TCP connection's keep-alive duration.
  552. // If set to greater than zero then a tcp listener featured keep alive
  553. // will be used instead of the simple tcp one.
  554. //
  555. // Defaults to 0.
  556. KeepAlive time.Duration `ini:"keepalive" json:"keepAlive" yaml:"KeepAlive" toml:"KeepAlive" env:"KEEP_ALIVE"`
  557. // Tunneling can be optionally set to enable ngrok http(s) tunneling for this Iris app instance.
  558. // See the `WithTunneling` Configurator too.
  559. Tunneling TunnelingConfiguration `ini:"tunneling" json:"tunneling,omitempty" yaml:"Tunneling" toml:"Tunneling"`
  560. // IgnoreServerErrors will cause to ignore the matched "errors"
  561. // from the main application's `Run` function.
  562. // This is a slice of string, not a slice of error
  563. // users can register these errors using yaml or toml configuration file
  564. // like the rest of the configuration fields.
  565. //
  566. // See `WithoutServerError(...)` function too.
  567. //
  568. // Example: https://github.com/kataras/iris/tree/master/_examples/http-server/listen-addr/omit-server-errors
  569. //
  570. // Defaults to an empty slice.
  571. IgnoreServerErrors []string `ini:"ignore_server_errors" json:"ignoreServerErrors,omitempty" yaml:"IgnoreServerErrors" toml:"IgnoreServerErrors"`
  572. // DisableStartupLog if set to true then it turns off the write banner on server startup.
  573. //
  574. // Defaults to false.
  575. DisableStartupLog bool `ini:"disable_startup_log" json:"disableStartupLog,omitempty" yaml:"DisableStartupLog" toml:"DisableStartupLog"`
  576. // DisableInterruptHandler if set to true then it disables the automatic graceful server shutdown
  577. // when control/cmd+C pressed.
  578. // Turn this to true if you're planning to handle this by your own via a custom host.Task.
  579. //
  580. // Defaults to false.
  581. DisableInterruptHandler bool `ini:"disable_interrupt_handler" json:"disableInterruptHandler,omitempty" yaml:"DisableInterruptHandler" toml:"DisableInterruptHandler"`
  582. // DisablePathCorrection disables the correcting
  583. // and redirecting or executing directly the handler of
  584. // the requested path to the registered path
  585. // for example, if /home/ path is requested but no handler for this Route found,
  586. // then the Router checks if /home handler exists, if yes,
  587. // (permanent)redirects the client to the correct path /home.
  588. //
  589. // See `DisablePathCorrectionRedirection` to enable direct handler execution instead of redirection.
  590. //
  591. // Defaults to false.
  592. DisablePathCorrection bool `ini:"disable_path_correction" json:"disablePathCorrection,omitempty" yaml:"DisablePathCorrection" toml:"DisablePathCorrection"`
  593. // DisablePathCorrectionRedirection works whenever configuration.DisablePathCorrection is set to false
  594. // and if DisablePathCorrectionRedirection set to true then it will fire the handler of the matching route without
  595. // the trailing slash ("/") instead of send a redirection status.
  596. //
  597. // Defaults to false.
  598. DisablePathCorrectionRedirection bool `ini:"disable_path_correction_redirection" json:"disablePathCorrectionRedirection,omitempty" yaml:"DisablePathCorrectionRedirection" toml:"DisablePathCorrectionRedirection"`
  599. // EnablePathIntelligence if set to true,
  600. // the router will redirect HTTP "GET" not found pages to the most closest one path(if any). For example
  601. // you register a route at "/contact" path -
  602. // a client tries to reach it by "/cont", the path will be automatic fixed
  603. // and the client will be redirected to the "/contact" path
  604. // instead of getting a 404 not found response back.
  605. //
  606. // Defaults to false.
  607. EnablePathIntelligence bool `ini:"enable_path_intelligence" json:"enablePathIntelligence,omitempty" yaml:"EnablePathIntelligence" toml:"EnablePathIntelligence"`
  608. // EnablePathEscape when is true then its escapes the path and the named parameters (if any).
  609. // When do you need to Disable(false) it:
  610. // accepts parameters with slash '/'
  611. // Request: http://localhost:8080/details/Project%2FDelta
  612. // ctx.Param("project") returns the raw named parameter: Project%2FDelta
  613. // which you can escape it manually with net/url:
  614. // projectName, _ := url.QueryUnescape(c.Param("project").
  615. //
  616. // Defaults to false.
  617. EnablePathEscape bool `ini:"enable_path_escape" json:"enablePathEscape,omitempty" yaml:"EnablePathEscape" toml:"EnablePathEscape"`
  618. // ForceLowercaseRouting if enabled, converts all registered routes paths to lowercase
  619. // and it does lowercase the request path too for matching.
  620. //
  621. // Defaults to false.
  622. ForceLowercaseRouting bool `ini:"force_lowercase_routing" json:"forceLowercaseRouting,omitempty" yaml:"ForceLowercaseRouting" toml:"ForceLowercaseRouting"`
  623. // FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
  624. // fires the 405 error instead of 404
  625. // Defaults to false.
  626. FireMethodNotAllowed bool `ini:"fire_method_not_allowed" json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`
  627. // DisableAutoFireStatusCode if true then it turns off the http error status code
  628. // handler automatic execution on error code from a `Context.StatusCode` call.
  629. // By-default a custom http error handler will be fired when "Context.StatusCode(errorCode)" called.
  630. //
  631. // Defaults to false.
  632. DisableAutoFireStatusCode bool `ini:"disable_auto_fire_status_code" json:"disableAutoFireStatusCode,omitempty" yaml:"DisableAutoFireStatusCode" toml:"DisableAutoFireStatusCode"`
  633. // ResetOnFireErrorCode if true then any previously response body or headers through
  634. // response recorder will be ignored and the router
  635. // will fire the registered (or default) HTTP error handler instead.
  636. // See `core/router/handler#FireErrorCode` and `Context.EndRequest` for more details.
  637. //
  638. // Read more at: https://github.com/kataras/iris/issues/1531
  639. //
  640. // Defaults to false.
  641. ResetOnFireErrorCode bool `ini:"reset_on_fire_error_code" json:"resetOnFireErrorCode,omitempty" yaml:"ResetOnFireErrorCode" toml:"ResetOnFireErrorCode"`
  642. // EnableOptimization when this field is true
  643. // then the application tries to optimize for the best performance where is possible.
  644. //
  645. // Defaults to false.
  646. EnableOptimizations bool `ini:"enable_optimizations" json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"`
  647. // DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
  648. // If set to true then it
  649. // disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
  650. //
  651. // By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
  652. // if this field set to true then a new buffer will be created to read from and the request body.
  653. // The body will not be changed and existing data before the
  654. // context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
  655. //
  656. // See `Context.RecordRequestBody` method for the same feature, per-request.
  657. DisableBodyConsumptionOnUnmarshal bool `ini:"disable_body_consumption" json:"disableBodyConsumptionOnUnmarshal,omitempty" yaml:"DisableBodyConsumptionOnUnmarshal" toml:"DisableBodyConsumptionOnUnmarshal"`
  658. // FireEmptyFormError returns if set to tue true then the `context.ReadForm/ReadQuery/ReadBody`
  659. // will return an `iris.ErrEmptyForm` on empty request form data.
  660. FireEmptyFormError bool `ini:"fire_empty_form_error" json:"fireEmptyFormError,omitempty" yaml:"FireEmptyFormError" toml:"FireEmptyFormError"`
  661. // TimeFormat time format for any kind of datetime parsing
  662. // Defaults to "Mon, 02 Jan 2006 15:04:05 GMT".
  663. TimeFormat string `ini:"time_format" json:"timeFormat,omitempty" yaml:"TimeFormat" toml:"TimeFormat"`
  664. // Charset character encoding for various rendering
  665. // used for templates and the rest of the responses
  666. // Defaults to "utf-8".
  667. Charset string `ini:"charset" json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
  668. // PostMaxMemory sets the maximum post data size
  669. // that a client can send to the server, this differs
  670. // from the overall request body size which can be modified
  671. // by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
  672. //
  673. // Defaults to 32MB or 32 << 20 if you prefer.
  674. PostMaxMemory int64 `ini:"post_max_memory" json:"postMaxMemory" yaml:"PostMaxMemory" toml:"PostMaxMemory"`
  675. // +----------------------------------------------------+
  676. // | Context's keys for values used on various featuers |
  677. // +----------------------------------------------------+
  678. // Context values' keys for various features.
  679. //
  680. // LocaleContextKey is used by i18n to get the current request's locale, which contains a translate function too.
  681. //
  682. // Defaults to "iris.locale".
  683. LocaleContextKey string `ini:"locale_context_key" json:"localeContextKey,omitempty" yaml:"LocaleContextKey" toml:"LocaleContextKey"`
  684. // LanguageContextKey is the context key which a language can be modified by a middleware.
  685. // It has the highest priority over the rest and if it is empty then it is ignored,
  686. // if it set to a static string of "default" or to the default language's code
  687. // then the rest of the language extractors will not be called at all and
  688. // the default language will be set instead.
  689. //
  690. // Use with `Context.SetLanguage("el-GR")`.
  691. //
  692. // See `i18n.ExtractFunc` for a more organised way of the same feature.
  693. // Defaults to "iris.locale.language".
  694. LanguageContextKey string `ini:"language_context_key" json:"languageContextKey,omitempty" yaml:"LanguageContextKey" toml:"LanguageContextKey"`
  695. // LanguageInputContextKey is the context key of a language that is given by the end-user.
  696. // It's the real user input of the language string, matched or not.
  697. //
  698. // Defaults to "iris.locale.language.input".
  699. LanguageInputContextKey string `ini:"language_input_context_key" json:"languageInputContextKey,omitempty" yaml:"LanguageInputContextKey" toml:"LanguageInputContextKey"`
  700. // VersionContextKey is the context key which an API Version can be modified
  701. // via a middleware through `SetVersion` method, e.g. `versioning.SetVersion(ctx, ">=1.0.0 <2.0.0")`.
  702. // Defaults to "iris.api.version".
  703. VersionContextKey string `ini:"version_context_key" json:"versionContextKey" yaml:"VersionContextKey" toml:"VersionContextKey"`
  704. // VersionAliasesContextKey is the context key which the versioning feature
  705. // can look up for alternative values of a version and fallback to that.
  706. // Head over to the versioning package for more.
  707. // Defaults to "iris.api.version.aliases"
  708. VersionAliasesContextKey string `ini:"version_aliases_context_key" json:"versionAliasesContextKey" yaml:"VersionAliasesContextKey" toml:"VersionAliasesContextKey"`
  709. // ViewEngineContextKey is the context's values key
  710. // responsible to store and retrieve(view.Engine) the current view engine.
  711. // A middleware or a Party can modify its associated value to change
  712. // a view engine that `ctx.View` will render through.
  713. // If not an engine is registered by the end-developer
  714. // then its associated value is always nil,
  715. // meaning that the default value is nil.
  716. // See `Party.RegisterView` and `Context.ViewEngine` methods as well.
  717. //
  718. // Defaults to "iris.view.engine".
  719. ViewEngineContextKey string `ini:"view_engine_context_key" json:"viewEngineContextKey,omitempty" yaml:"ViewEngineContextKey" toml:"ViewEngineContextKey"`
  720. // ViewLayoutContextKey is the context's values key
  721. // responsible to store and retrieve(string) the current view layout.
  722. // A middleware can modify its associated value to change
  723. // the layout that `ctx.View` will use to render a template.
  724. //
  725. // Defaults to "iris.view.layout".
  726. ViewLayoutContextKey string `ini:"view_layout_context_key" json:"viewLayoutContextKey,omitempty" yaml:"ViewLayoutContextKey" toml:"ViewLayoutContextKey"`
  727. // ViewDataContextKey is the context's values key
  728. // responsible to store and retrieve(interface{}) the current view binding data.
  729. // A middleware can modify its associated value to change
  730. // the template's data on-fly.
  731. //
  732. // Defaults to "iris.view.data".
  733. ViewDataContextKey string `ini:"view_data_context_key" json:"viewDataContextKey,omitempty" yaml:"ViewDataContextKey" toml:"ViewDataContextKey"`
  734. // FallbackViewContextKey is the context's values key
  735. // responsible to store the view fallback information.
  736. //
  737. // Defaults to "iris.view.fallback".
  738. FallbackViewContextKey string `ini:"fallback_view_context_key" json:"fallbackViewContextKey,omitempty" yaml:"FallbackViewContextKey" toml:"FallbackViewContextKey"`
  739. // RemoteAddrHeaders are the allowed request headers names
  740. // that can be valid to parse the client's IP based on.
  741. // By-default no "X-" header is consired safe to be used for retrieving the
  742. // client's IP address, because those headers can manually change by
  743. // the client. But sometimes are useful e.g. when behind a proxy
  744. // you want to enable the "X-Forwarded-For" or when cloudflare
  745. // you want to enable the "CF-Connecting-IP", indeed you
  746. // can allow the `ctx.RemoteAddr()` to use any header
  747. // that the client may sent.
  748. //
  749. // Defaults to an empty slice but an example usage is:
  750. // RemoteAddrHeaders {
  751. // "X-Real-Ip",
  752. // "X-Forwarded-For",
  753. // "CF-Connecting-IP",
  754. // "True-Client-Ip",
  755. // }
  756. //
  757. // Look `context.RemoteAddr()` for more.
  758. RemoteAddrHeaders []string `ini:"remote_addr_headers" json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
  759. // RemoteAddrHeadersForce forces the `Context.RemoteAddr()` method
  760. // to return the first entry of a request header as a fallback,
  761. // even if that IP is a part of the `RemoteAddrPrivateSubnets` list.
  762. // The default behavior, if a remote address is part of the `RemoteAddrPrivateSubnets`,
  763. // is to retrieve the IP from the `Request.RemoteAddr` field instead.
  764. RemoteAddrHeadersForce bool `ini:"remote_addr_headers_force" json:"remoteAddrHeadersForce,omitempty" yaml:"RemoteAddrHeadersForce" toml:"RemoteAddrHeadersForce"`
  765. // RemoteAddrPrivateSubnets defines the private sub-networks.
  766. // They are used to be compared against
  767. // IP Addresses fetched through `RemoteAddrHeaders` or `Context.Request.RemoteAddr`.
  768. // For details please navigate through: https://github.com/kataras/iris/issues/1453
  769. // Defaults to:
  770. // {
  771. // Start: "10.0.0.0",
  772. // End: "10.255.255.255",
  773. // },
  774. // {
  775. // Start: "100.64.0.0",
  776. // End: "100.127.255.255",
  777. // },
  778. // {
  779. // Start: "172.16.0.0",
  780. // End: "172.31.255.255",
  781. // },
  782. // {
  783. // Start: "192.0.0.0",
  784. // End: "192.0.0.255",
  785. // },
  786. // {
  787. // Start: "192.168.0.0",
  788. // End: "192.168.255.255",
  789. // },
  790. // {
  791. // Start: "198.18.0.0",
  792. // End: "198.19.255.255",
  793. // }
  794. //
  795. // Look `Context.RemoteAddr()` for more.
  796. RemoteAddrPrivateSubnets []netutil.IPRange `ini:"remote_addr_private_subnets" json:"remoteAddrPrivateSubnets" yaml:"RemoteAddrPrivateSubnets" toml:"RemoteAddrPrivateSubnets"`
  797. // SSLProxyHeaders defines the set of header key values
  798. // that would indicate a valid https Request (look `Context.IsSSL()`).
  799. // Example: `map[string]string{"X-Forwarded-Proto": "https"}`.
  800. //
  801. // Defaults to empty map.
  802. SSLProxyHeaders map[string]string `ini:"ssl_proxy_headers" json:"sslProxyHeaders" yaml:"SSLProxyHeaders" toml:"SSLProxyHeaders"`
  803. // HostProxyHeaders defines the set of headers that may hold a proxied hostname value for the clients.
  804. // Look `Context.Host()` for more.
  805. // Defaults to empty map.
  806. HostProxyHeaders map[string]bool `ini:"host_proxy_headers" json:"hostProxyHeaders" yaml:"HostProxyHeaders" toml:"HostProxyHeaders"`
  807. // Other are the custom, dynamic options, can be empty.
  808. // This field used only by you to set any app's options you want.
  809. //
  810. // Defaults to empty map.
  811. Other map[string]interface{} `ini:"other" json:"other,omitempty" yaml:"Other" toml:"Other"`
  812. }
  813. var _ context.ConfigurationReadOnly = &Configuration{}
  814. // GetVHost returns the non-exported vhost config field.
  815. func (c Configuration) GetVHost() string {
  816. return c.vhost
  817. }
  818. // GetLogLevel returns the LogLevel field.
  819. func (c Configuration) GetLogLevel() string {
  820. return c.vhost
  821. }
  822. // GetSocketSharding returns the SocketSharding field.
  823. func (c Configuration) GetSocketSharding() bool {
  824. return c.SocketSharding
  825. }
  826. // GetKeepAlive returns the KeepAlive field.
  827. func (c Configuration) GetKeepAlive() time.Duration {
  828. return c.KeepAlive
  829. }
  830. // GetDisablePathCorrection returns the DisablePathCorrection field.
  831. func (c Configuration) GetDisablePathCorrection() bool {
  832. return c.DisablePathCorrection
  833. }
  834. // GetDisablePathCorrectionRedirection returns the DisablePathCorrectionRedirection field.
  835. func (c Configuration) GetDisablePathCorrectionRedirection() bool {
  836. return c.DisablePathCorrectionRedirection
  837. }
  838. // GetEnablePathIntelligence returns the EnablePathIntelligence field.
  839. func (c Configuration) GetEnablePathIntelligence() bool {
  840. return c.EnablePathIntelligence
  841. }
  842. // GetEnablePathEscape returns the EnablePathEscape field.
  843. func (c Configuration) GetEnablePathEscape() bool {
  844. return c.EnablePathEscape
  845. }
  846. // GetForceLowercaseRouting returns the ForceLowercaseRouting field.
  847. func (c Configuration) GetForceLowercaseRouting() bool {
  848. return c.ForceLowercaseRouting
  849. }
  850. // GetFireMethodNotAllowed returns the FireMethodNotAllowed field.
  851. func (c Configuration) GetFireMethodNotAllowed() bool {
  852. return c.FireMethodNotAllowed
  853. }
  854. // GetEnableOptimizations returns the EnableOptimizations.
  855. func (c Configuration) GetEnableOptimizations() bool {
  856. return c.EnableOptimizations
  857. }
  858. // GetDisableBodyConsumptionOnUnmarshal returns the DisableBodyConsumptionOnUnmarshal field.
  859. func (c Configuration) GetDisableBodyConsumptionOnUnmarshal() bool {
  860. return c.DisableBodyConsumptionOnUnmarshal
  861. }
  862. // GetFireEmptyFormError returns the DisableBodyConsumptionOnUnmarshal field.
  863. func (c Configuration) GetFireEmptyFormError() bool {
  864. return c.FireEmptyFormError
  865. }
  866. // GetDisableAutoFireStatusCode returns the DisableAutoFireStatusCode field.
  867. func (c Configuration) GetDisableAutoFireStatusCode() bool {
  868. return c.DisableAutoFireStatusCode
  869. }
  870. // GetResetOnFireErrorCode returns ResetOnFireErrorCode field.
  871. func (c Configuration) GetResetOnFireErrorCode() bool {
  872. return c.ResetOnFireErrorCode
  873. }
  874. // GetTimeFormat returns the TimeFormat field.
  875. func (c Configuration) GetTimeFormat() string {
  876. return c.TimeFormat
  877. }
  878. // GetCharset returns the Charset field.
  879. func (c Configuration) GetCharset() string {
  880. return c.Charset
  881. }
  882. // GetPostMaxMemory returns the PostMaxMemory field.
  883. func (c Configuration) GetPostMaxMemory() int64 {
  884. return c.PostMaxMemory
  885. }
  886. // GetLocaleContextKey returns the LocaleContextKey field.
  887. func (c Configuration) GetLocaleContextKey() string {
  888. return c.LocaleContextKey
  889. }
  890. // GetLanguageContextKey returns the LanguageContextKey field.
  891. func (c Configuration) GetLanguageContextKey() string {
  892. return c.LanguageContextKey
  893. }
  894. // GetLanguageInputContextKey returns the LanguageInputContextKey field.
  895. func (c Configuration) GetLanguageInputContextKey() string {
  896. return c.LanguageInputContextKey
  897. }
  898. // GetVersionContextKey returns the VersionContextKey field.
  899. func (c Configuration) GetVersionContextKey() string {
  900. return c.VersionContextKey
  901. }
  902. // GetVersionAliasesContextKey returns the VersionAliasesContextKey field.
  903. func (c Configuration) GetVersionAliasesContextKey() string {
  904. return c.VersionAliasesContextKey
  905. }
  906. // GetViewEngineContextKey returns the ViewEngineContextKey field.
  907. func (c Configuration) GetViewEngineContextKey() string {
  908. return c.ViewEngineContextKey
  909. }
  910. // GetViewLayoutContextKey returns the ViewLayoutContextKey field.
  911. func (c Configuration) GetViewLayoutContextKey() string {
  912. return c.ViewLayoutContextKey
  913. }
  914. // GetViewDataContextKey returns the ViewDataContextKey field.
  915. func (c Configuration) GetViewDataContextKey() string {
  916. return c.ViewDataContextKey
  917. }
  918. // GetFallbackViewContextKey returns the FallbackViewContextKey field.
  919. func (c Configuration) GetFallbackViewContextKey() string {
  920. return c.FallbackViewContextKey
  921. }
  922. // GetRemoteAddrHeaders returns the RemoteAddrHeaders field.
  923. func (c Configuration) GetRemoteAddrHeaders() []string {
  924. return c.RemoteAddrHeaders
  925. }
  926. // GetRemoteAddrHeadersForce returns RemoteAddrHeadersForce field.
  927. func (c Configuration) GetRemoteAddrHeadersForce() bool {
  928. return c.RemoteAddrHeadersForce
  929. }
  930. // GetSSLProxyHeaders returns the SSLProxyHeaders field.
  931. func (c Configuration) GetSSLProxyHeaders() map[string]string {
  932. return c.SSLProxyHeaders
  933. }
  934. // GetRemoteAddrPrivateSubnets returns the RemoteAddrPrivateSubnets field.
  935. func (c Configuration) GetRemoteAddrPrivateSubnets() []netutil.IPRange {
  936. return c.RemoteAddrPrivateSubnets
  937. }
  938. // GetHostProxyHeaders returns the HostProxyHeaders field.
  939. func (c Configuration) GetHostProxyHeaders() map[string]bool {
  940. return c.HostProxyHeaders
  941. }
  942. // GetOther returns the Other field.
  943. func (c Configuration) GetOther() map[string]interface{} {
  944. return c.Other
  945. }
  946. // WithConfiguration sets the "c" values to the framework's configurations.
  947. //
  948. // Usage:
  949. // app.Listen(":8080", iris.WithConfiguration(iris.Configuration{/* fields here */ }))
  950. // or
  951. // iris.WithConfiguration(iris.YAML("./cfg/iris.yml"))
  952. // or
  953. // iris.WithConfiguration(iris.TOML("./cfg/iris.tml"))
  954. func WithConfiguration(c Configuration) Configurator {
  955. return func(app *Application) {
  956. main := app.config
  957. if main == nil {
  958. app.config = &c
  959. return
  960. }
  961. if v := c.LogLevel; v != "" {
  962. main.LogLevel = v
  963. }
  964. if v := c.SocketSharding; v {
  965. main.SocketSharding = v
  966. }
  967. if v := c.KeepAlive; v > 0 {
  968. main.KeepAlive = v
  969. }
  970. if len(c.Tunneling.Tunnels) > 0 {
  971. main.Tunneling = c.Tunneling
  972. }
  973. if v := c.IgnoreServerErrors; len(v) > 0 {
  974. main.IgnoreServerErrors = append(main.IgnoreServerErrors, v...)
  975. }
  976. if v := c.DisableStartupLog; v {
  977. main.DisableStartupLog = v
  978. }
  979. if v := c.DisableInterruptHandler; v {
  980. main.DisableInterruptHandler = v
  981. }
  982. if v := c.DisablePathCorrection; v {
  983. main.DisablePathCorrection = v
  984. }
  985. if v := c.DisablePathCorrectionRedirection; v {
  986. main.DisablePathCorrectionRedirection = v
  987. }
  988. if v := c.EnablePathIntelligence; v {
  989. main.EnablePathIntelligence = v
  990. }
  991. if v := c.EnablePathEscape; v {
  992. main.EnablePathEscape = v
  993. }
  994. if v := c.ForceLowercaseRouting; v {
  995. main.ForceLowercaseRouting = v
  996. }
  997. if v := c.EnableOptimizations; v {
  998. main.EnableOptimizations = v
  999. }
  1000. if v := c.FireMethodNotAllowed; v {
  1001. main.FireMethodNotAllowed = v
  1002. }
  1003. if v := c.DisableAutoFireStatusCode; v {
  1004. main.DisableAutoFireStatusCode = v
  1005. }
  1006. if v := c.ResetOnFireErrorCode; v {
  1007. main.ResetOnFireErrorCode = v
  1008. }
  1009. if v := c.DisableBodyConsumptionOnUnmarshal; v {
  1010. main.DisableBodyConsumptionOnUnmarshal = v
  1011. }
  1012. if v := c.FireEmptyFormError; v {
  1013. main.FireEmptyFormError = v
  1014. }
  1015. if v := c.TimeFormat; v != "" {
  1016. main.TimeFormat = v
  1017. }
  1018. if v := c.Charset; v != "" {
  1019. main.Charset = v
  1020. }
  1021. if v := c.PostMaxMemory; v > 0 {
  1022. main.PostMaxMemory = v
  1023. }
  1024. if v := c.LocaleContextKey; v != "" {
  1025. main.LocaleContextKey = v
  1026. }
  1027. if v := c.LanguageContextKey; v != "" {
  1028. main.LanguageContextKey = v
  1029. }
  1030. if v := c.LanguageInputContextKey; v != "" {
  1031. main.LanguageInputContextKey = v
  1032. }
  1033. if v := c.VersionContextKey; v != "" {
  1034. main.VersionContextKey = v
  1035. }
  1036. if v := c.VersionAliasesContextKey; v != "" {
  1037. main.VersionAliasesContextKey = v
  1038. }
  1039. if v := c.ViewEngineContextKey; v != "" {
  1040. main.ViewEngineContextKey = v
  1041. }
  1042. if v := c.ViewLayoutContextKey; v != "" {
  1043. main.ViewLayoutContextKey = v
  1044. }
  1045. if v := c.ViewDataContextKey; v != "" {
  1046. main.ViewDataContextKey = v
  1047. }
  1048. if v := c.FallbackViewContextKey; v != "" {
  1049. main.FallbackViewContextKey = v
  1050. }
  1051. if v := c.RemoteAddrHeaders; len(v) > 0 {
  1052. main.RemoteAddrHeaders = v
  1053. }
  1054. if v := c.RemoteAddrHeadersForce; v {
  1055. main.RemoteAddrHeadersForce = v
  1056. }
  1057. if v := c.RemoteAddrPrivateSubnets; len(v) > 0 {
  1058. main.RemoteAddrPrivateSubnets = v
  1059. }
  1060. if v := c.SSLProxyHeaders; len(v) > 0 {
  1061. if main.SSLProxyHeaders == nil {
  1062. main.SSLProxyHeaders = make(map[string]string, len(v))
  1063. }
  1064. for key, value := range v {
  1065. main.SSLProxyHeaders[key] = value
  1066. }
  1067. }
  1068. if v := c.HostProxyHeaders; len(v) > 0 {
  1069. if main.HostProxyHeaders == nil {
  1070. main.HostProxyHeaders = make(map[string]bool, len(v))
  1071. }
  1072. for key, value := range v {
  1073. main.HostProxyHeaders[key] = value
  1074. }
  1075. }
  1076. if v := c.Other; len(v) > 0 {
  1077. if main.Other == nil {
  1078. main.Other = make(map[string]interface{}, len(v))
  1079. }
  1080. for key, value := range v {
  1081. main.Other[key] = value
  1082. }
  1083. }
  1084. }
  1085. }
  1086. // DefaultConfiguration returns the default configuration for an iris station, fills the main Configuration
  1087. func DefaultConfiguration() Configuration {
  1088. return Configuration{
  1089. LogLevel: "info",
  1090. SocketSharding: false,
  1091. KeepAlive: 0,
  1092. DisableStartupLog: false,
  1093. DisableInterruptHandler: false,
  1094. DisablePathCorrection: false,
  1095. EnablePathEscape: false,
  1096. ForceLowercaseRouting: false,
  1097. FireMethodNotAllowed: false,
  1098. DisableBodyConsumptionOnUnmarshal: false,
  1099. FireEmptyFormError: false,
  1100. DisableAutoFireStatusCode: false,
  1101. TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
  1102. Charset: "utf-8",
  1103. // PostMaxMemory is for post body max memory.
  1104. //
  1105. // The request body the size limit
  1106. // can be set by the middleware `LimitRequestBodySize`
  1107. // or `context#SetMaxRequestBodySize`.
  1108. PostMaxMemory: 32 << 20, // 32MB
  1109. LocaleContextKey: "iris.locale",
  1110. LanguageContextKey: "iris.locale.language",
  1111. LanguageInputContextKey: "iris.locale.language.input",
  1112. VersionContextKey: "iris.api.version",
  1113. VersionAliasesContextKey: "iris.api.version.aliases",
  1114. ViewEngineContextKey: "iris.view.engine",
  1115. ViewLayoutContextKey: "iris.view.layout",
  1116. ViewDataContextKey: "iris.view.data",
  1117. FallbackViewContextKey: "iris.view.fallback",
  1118. RemoteAddrHeaders: nil,
  1119. RemoteAddrHeadersForce: false,
  1120. RemoteAddrPrivateSubnets: []netutil.IPRange{
  1121. {
  1122. Start: "10.0.0.0",
  1123. End: "10.255.255.255",
  1124. },
  1125. {
  1126. Start: "100.64.0.0",
  1127. End: "100.127.255.255",
  1128. },
  1129. {
  1130. Start: "172.16.0.0",
  1131. End: "172.31.255.255",
  1132. },
  1133. {
  1134. Start: "192.0.0.0",
  1135. End: "192.0.0.255",
  1136. },
  1137. {
  1138. Start: "192.168.0.0",
  1139. End: "192.168.255.255",
  1140. },
  1141. {
  1142. Start: "198.18.0.0",
  1143. End: "198.19.255.255",
  1144. },
  1145. },
  1146. SSLProxyHeaders: make(map[string]string),
  1147. HostProxyHeaders: make(map[string]bool),
  1148. EnableOptimizations: false,
  1149. Other: make(map[string]interface{}),
  1150. }
  1151. }