configuration.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. package iris
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "os/user"
  6. "path/filepath"
  7. "runtime"
  8. "github.com/BurntSushi/toml"
  9. "gopkg.in/yaml.v2"
  10. "github.com/kataras/iris/context"
  11. "github.com/kataras/iris/core/errors"
  12. )
  13. const globalConfigurationKeyword = "~"
  14. // homeConfigurationFilename returns the physical location of the global configuration(yaml or toml) file.
  15. // This is useful when we run multiple iris servers that share the same
  16. // configuration, even with custom values at its "Other" field.
  17. // It will return a file location
  18. // which targets to $HOME or %HOMEDRIVE%+%HOMEPATH% + "iris" + the given "ext".
  19. func homeConfigurationFilename(ext string) string {
  20. return filepath.Join(homeDir(), "iris"+ext)
  21. }
  22. func homeDir() (home string) {
  23. u, err := user.Current()
  24. if u != nil && err == nil {
  25. home = u.HomeDir
  26. }
  27. if home == "" {
  28. home = os.Getenv("HOME")
  29. }
  30. if home == "" {
  31. if runtime.GOOS == "plan9" {
  32. home = os.Getenv("home")
  33. } else if runtime.GOOS == "windows" {
  34. home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
  35. if home == "" {
  36. home = os.Getenv("USERPROFILE")
  37. }
  38. }
  39. }
  40. return
  41. }
  42. var errConfigurationDecode = errors.New("error while trying to decode configuration")
  43. func parseYAML(filename string) (Configuration, error) {
  44. c := DefaultConfiguration()
  45. // get the abs
  46. // which will try to find the 'filename' from current workind dir too.
  47. yamlAbsPath, err := filepath.Abs(filename)
  48. if err != nil {
  49. return c, errConfigurationDecode.AppendErr(err)
  50. }
  51. // read the raw contents of the file
  52. data, err := ioutil.ReadFile(yamlAbsPath)
  53. if err != nil {
  54. return c, errConfigurationDecode.AppendErr(err)
  55. }
  56. // put the file's contents as yaml to the default configuration(c)
  57. if err := yaml.Unmarshal(data, &c); err != nil {
  58. return c, errConfigurationDecode.AppendErr(err)
  59. }
  60. return c, nil
  61. }
  62. // YAML reads Configuration from a configuration.yml file.
  63. //
  64. // Accepts the absolute path of the cfg.yml.
  65. // An error will be shown to the user via panic with the error message.
  66. // Error may occur when the cfg.yml doesn't exists or is not formatted correctly.
  67. //
  68. // Note: if the char '~' passed as "filename" then it tries to load and return
  69. // the configuration from the $home_directory + iris.yml,
  70. // see `WithGlobalConfiguration` for more information.
  71. //
  72. // Usage:
  73. // app.Configure(iris.WithConfiguration(iris.YAML("myconfig.yml"))) or
  74. // app.Run([iris.Runner], iris.WithConfiguration(iris.YAML("myconfig.yml"))).
  75. func YAML(filename string) Configuration {
  76. // check for globe configuration file and use that, otherwise
  77. // return the default configuration if file doesn't exist.
  78. if filename == globalConfigurationKeyword {
  79. filename = homeConfigurationFilename(".yml")
  80. if _, err := os.Stat(filename); os.IsNotExist(err) {
  81. panic("default configuration file '" + filename + "' does not exist")
  82. }
  83. }
  84. c, err := parseYAML(filename)
  85. if err != nil {
  86. panic(err)
  87. }
  88. return c
  89. }
  90. // TOML reads Configuration from a toml-compatible document file.
  91. // Read more about toml's implementation at:
  92. // https://github.com/toml-lang/toml
  93. //
  94. //
  95. // Accepts the absolute path of the configuration file.
  96. // An error will be shown to the user via panic with the error message.
  97. // Error may occur when the file doesn't exists or is not formatted correctly.
  98. //
  99. // Note: if the char '~' passed as "filename" then it tries to load and return
  100. // the configuration from the $home_directory + iris.tml,
  101. // see `WithGlobalConfiguration` for more information.
  102. //
  103. // Usage:
  104. // app.Configure(iris.WithConfiguration(iris.YAML("myconfig.tml"))) or
  105. // app.Run([iris.Runner], iris.WithConfiguration(iris.YAML("myconfig.tml"))).
  106. func TOML(filename string) Configuration {
  107. c := DefaultConfiguration()
  108. // check for globe configuration file and use that, otherwise
  109. // return the default configuration if file doesn't exist.
  110. if filename == globalConfigurationKeyword {
  111. filename = homeConfigurationFilename(".tml")
  112. if _, err := os.Stat(filename); os.IsNotExist(err) {
  113. panic("default configuration file '" + filename + "' does not exist")
  114. }
  115. }
  116. // get the abs
  117. // which will try to find the 'filename' from current workind dir too.
  118. tomlAbsPath, err := filepath.Abs(filename)
  119. if err != nil {
  120. panic(errConfigurationDecode.AppendErr(err))
  121. }
  122. // read the raw contents of the file
  123. data, err := ioutil.ReadFile(tomlAbsPath)
  124. if err != nil {
  125. panic(errConfigurationDecode.AppendErr(err))
  126. }
  127. // put the file's contents as toml to the default configuration(c)
  128. if _, err := toml.Decode(string(data), &c); err != nil {
  129. panic(errConfigurationDecode.AppendErr(err))
  130. }
  131. // Author's notes:
  132. // The toml's 'usual thing' for key naming is: the_config_key instead of TheConfigKey
  133. // but I am always prefer to use the specific programming language's syntax
  134. // and the original configuration name fields for external configuration files
  135. // so we do 'toml: "TheConfigKeySameAsTheConfigField" instead.
  136. return c
  137. }
  138. // Configurator is just an interface which accepts the framework instance.
  139. //
  140. // It can be used to register a custom configuration with `Configure` in order
  141. // to modify the framework instance.
  142. //
  143. // Currently Configurator is being used to describe the configuration's fields values.
  144. type Configurator func(*Application)
  145. // WithGlobalConfiguration will load the global yaml configuration file
  146. // from the home directory and it will set/override the whole app's configuration
  147. // to that file's contents. The global configuration file can be modified by user
  148. // and be used by multiple iris instances.
  149. //
  150. // This is useful when we run multiple iris servers that share the same
  151. // configuration, even with custom values at its "Other" field.
  152. //
  153. // Usage: `app.Configure(iris.WithGlobalConfiguration)` or `app.Run([iris.Runner], iris.WithGlobalConfiguration)`.
  154. var WithGlobalConfiguration = func(app *Application) {
  155. app.Configure(WithConfiguration(YAML(globalConfigurationKeyword)))
  156. }
  157. // variables for configurators don't need any receivers, functions
  158. // for them that need (helps code editors to recognise as variables without parenthesis completion).
  159. // WithoutServerError will cause to ignore the matched "errors"
  160. // from the main application's `Run` function.
  161. //
  162. // Usage:
  163. // err := app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
  164. // will return `nil` if the server's error was `http/iris#ErrServerClosed`.
  165. //
  166. // See `Configuration#IgnoreServerErrors []string` too.
  167. //
  168. // Example: https://github.com/kataras/iris/tree/master/_examples/http-listening/listen-addr/omit-server-errors
  169. func WithoutServerError(errors ...error) Configurator {
  170. return func(app *Application) {
  171. if len(errors) == 0 {
  172. return
  173. }
  174. errorsAsString := make([]string, len(errors))
  175. for i, e := range errors {
  176. errorsAsString[i] = e.Error()
  177. }
  178. app.config.IgnoreServerErrors = append(app.config.IgnoreServerErrors, errorsAsString...)
  179. }
  180. }
  181. // WithoutStartupLog turns off the information send, once, to the terminal when the main server is open.
  182. var WithoutStartupLog = func(app *Application) {
  183. app.config.DisableStartupLog = true
  184. }
  185. // WithoutBanner is a conversion for the `WithoutStartupLog` option.
  186. //
  187. // Turns off the information send, once, to the terminal when the main server is open.
  188. var WithoutBanner = WithoutStartupLog
  189. // WithoutInterruptHandler disables the automatic graceful server shutdown
  190. // when control/cmd+C pressed.
  191. var WithoutInterruptHandler = func(app *Application) {
  192. app.config.DisableInterruptHandler = true
  193. }
  194. // WithoutVersionChecker will disable the version checker and updater.
  195. // The Iris server will be not
  196. // receive automatic updates if you pass this
  197. // to the `Run` function. Use it only while you're ready for Production environment.
  198. var WithoutVersionChecker = func(app *Application) {
  199. app.config.DisableVersionChecker = true
  200. }
  201. // WithoutPathCorrection disables the PathCorrection setting.
  202. //
  203. // See `Configuration`.
  204. var WithoutPathCorrection = func(app *Application) {
  205. app.config.DisablePathCorrection = true
  206. }
  207. // WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting.
  208. //
  209. // See `Configuration`.
  210. var WithoutBodyConsumptionOnUnmarshal = func(app *Application) {
  211. app.config.DisableBodyConsumptionOnUnmarshal = true
  212. }
  213. // WithoutAutoFireStatusCode disables the AutoFireStatusCode setting.
  214. //
  215. // See `Configuration`.
  216. var WithoutAutoFireStatusCode = func(app *Application) {
  217. app.config.DisableAutoFireStatusCode = true
  218. }
  219. // WithPathEscape enanbles the PathEscape setting.
  220. //
  221. // See `Configuration`.
  222. var WithPathEscape = func(app *Application) {
  223. app.config.EnablePathEscape = true
  224. }
  225. // WithOptimizations can force the application to optimize for the best performance where is possible.
  226. //
  227. // See `Configuration`.
  228. var WithOptimizations = func(app *Application) {
  229. app.config.EnableOptimizations = true
  230. }
  231. // WithFireMethodNotAllowed enanbles the FireMethodNotAllowed setting.
  232. //
  233. // See `Configuration`.
  234. var WithFireMethodNotAllowed = func(app *Application) {
  235. app.config.FireMethodNotAllowed = true
  236. }
  237. // WithTimeFormat sets the TimeFormat setting.
  238. //
  239. // See `Configuration`.
  240. func WithTimeFormat(timeformat string) Configurator {
  241. return func(app *Application) {
  242. app.config.TimeFormat = timeformat
  243. }
  244. }
  245. // WithCharset sets the Charset setting.
  246. //
  247. // See `Configuration`.
  248. func WithCharset(charset string) Configurator {
  249. return func(app *Application) {
  250. app.config.Charset = charset
  251. }
  252. }
  253. // WithPostMaxMemory sets the maximum post data size
  254. // that a client can send to the server, this differs
  255. // from the overral request body size which can be modified
  256. // by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
  257. //
  258. // Defaults to 32MB or 32 << 20 if you prefer.
  259. func WithPostMaxMemory(limit int64) Configurator {
  260. return func(app *Application) {
  261. app.config.PostMaxMemory = limit
  262. }
  263. }
  264. // WithRemoteAddrHeader enables or adds a new or existing request header name
  265. // that can be used to validate the client's real IP.
  266. //
  267. // By-default no "X-" header is consired safe to be used for retrieving the
  268. // client's IP address, because those headers can manually change by
  269. // the client. But sometimes are useful e.g., when behind a proxy
  270. // you want to enable the "X-Forwarded-For" or when cloudflare
  271. // you want to enable the "CF-Connecting-IP", inneed you
  272. // can allow the `ctx.RemoteAddr()` to use any header
  273. // that the client may sent.
  274. //
  275. // Defaults to an empty map but an example usage is:
  276. // WithRemoteAddrHeader("X-Forwarded-For")
  277. //
  278. // Look `context.RemoteAddr()` for more.
  279. func WithRemoteAddrHeader(headerName string) Configurator {
  280. return func(app *Application) {
  281. if app.config.RemoteAddrHeaders == nil {
  282. app.config.RemoteAddrHeaders = make(map[string]bool)
  283. }
  284. app.config.RemoteAddrHeaders[headerName] = true
  285. }
  286. }
  287. // WithoutRemoteAddrHeader disables an existing request header name
  288. // that can be used to validate and parse the client's real IP.
  289. //
  290. //
  291. // Keep note that RemoteAddrHeaders is already defaults to an empty map
  292. // so you don't have to call this Configurator if you didn't
  293. // add allowed headers via configuration or via `WithRemoteAddrHeader` before.
  294. //
  295. // Look `context.RemoteAddr()` for more.
  296. func WithoutRemoteAddrHeader(headerName string) Configurator {
  297. return func(app *Application) {
  298. if app.config.RemoteAddrHeaders == nil {
  299. app.config.RemoteAddrHeaders = make(map[string]bool)
  300. }
  301. app.config.RemoteAddrHeaders[headerName] = false
  302. }
  303. }
  304. // WithOtherValue adds a value based on a key to the Other setting.
  305. //
  306. // See `Configuration`.
  307. func WithOtherValue(key string, val interface{}) Configurator {
  308. return func(app *Application) {
  309. if app.config.Other == nil {
  310. app.config.Other = make(map[string]interface{})
  311. }
  312. app.config.Other[key] = val
  313. }
  314. }
  315. // Configuration the whole configuration for an iris instance
  316. // these can be passed via options also, look at the top of this file(configuration.go).
  317. // Configuration is a valid OptionSetter.
  318. type Configuration struct {
  319. // vhost is private and setted only with .Run method, it cannot be changed after the first set.
  320. // It can be retrieved by the context if needed (i.e router for subdomains)
  321. vhost string
  322. // IgnoreServerErrors will cause to ignore the matched "errors"
  323. // from the main application's `Run` function.
  324. // This is a slice of string, not a slice of error
  325. // users can register these errors using yaml or toml configuration file
  326. // like the rest of the configuration fields.
  327. //
  328. // See `WithoutServerError(...)` function too.
  329. //
  330. // Example: https://github.com/kataras/iris/tree/master/_examples/http-listening/listen-addr/omit-server-errors
  331. //
  332. // Defaults to an empty slice.
  333. IgnoreServerErrors []string `json:"ignoreServerErrors,omitempty" yaml:"IgnoreServerErrors" toml:"IgnoreServerErrors"`
  334. // DisableStartupLog if setted to true then it turns off the write banner on server startup.
  335. //
  336. // Defaults to false.
  337. DisableStartupLog bool `json:"disableStartupLog,omitempty" yaml:"DisableStartupLog" toml:"DisableStartupLog"`
  338. // DisableInterruptHandler if setted to true then it disables the automatic graceful server shutdown
  339. // when control/cmd+C pressed.
  340. // Turn this to true if you're planning to handle this by your own via a custom host.Task.
  341. //
  342. // Defaults to false.
  343. DisableInterruptHandler bool `json:"disableInterruptHandler,omitempty" yaml:"DisableInterruptHandler" toml:"DisableInterruptHandler"`
  344. // DisableVersionChecker if true then process will be not be notified for any available updates.
  345. //
  346. // Defaults to false.
  347. DisableVersionChecker bool `json:"disableVersionChecker,omitempty" yaml:"DisableVersionChecker" toml:"DisableVersionChecker"`
  348. // DisablePathCorrection corrects and redirects the requested path to the registered path
  349. // for example, if /home/ path is requested but no handler for this Route found,
  350. // then the Router checks if /home handler exists, if yes,
  351. // (permant)redirects the client to the correct path /home
  352. //
  353. // Defaults to false.
  354. DisablePathCorrection bool `json:"disablePathCorrection,omitempty" yaml:"DisablePathCorrection" toml:"DisablePathCorrection"`
  355. // EnablePathEscape when is true then its escapes the path, the named parameters (if any).
  356. // Change to false it if you want something like this https://github.com/kataras/iris/issues/135 to work
  357. //
  358. // When do you need to Disable(false) it:
  359. // accepts parameters with slash '/'
  360. // Request: http://localhost:8080/details/Project%2FDelta
  361. // ctx.Param("project") returns the raw named parameter: Project%2FDelta
  362. // which you can escape it manually with net/url:
  363. // projectName, _ := url.QueryUnescape(c.Param("project").
  364. //
  365. // Defaults to false.
  366. EnablePathEscape bool `json:"enablePathEscape,omitempty" yaml:"EnablePathEscape" toml:"EnablePathEscape"`
  367. // EnableOptimization when this field is true
  368. // then the application tries to optimize for the best performance where is possible.
  369. //
  370. // Defaults to false.
  371. EnableOptimizations bool `json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"`
  372. // FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
  373. // fires the 405 error instead of 404
  374. // Defaults to false.
  375. FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`
  376. // DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
  377. // If setted to true then it
  378. // disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
  379. //
  380. // By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
  381. // if this field setted to true then a new buffer will be created to read from and the request body.
  382. // The body will not be changed and existing data before the
  383. // context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
  384. DisableBodyConsumptionOnUnmarshal bool `json:"disableBodyConsumptionOnUnmarshal,omitempty" yaml:"DisableBodyConsumptionOnUnmarshal" toml:"DisableBodyConsumptionOnUnmarshal"`
  385. // DisableAutoFireStatusCode if true then it turns off the http error status code handler automatic execution
  386. // from (`context.StatusCodeNotSuccessful`, defaults to < 200 || >= 400).
  387. // If that is false then for a direct error firing, then call the "context#FireStatusCode(statusCode)" manually.
  388. //
  389. // By-default a custom http error handler will be fired when "context.StatusCode(code)" called,
  390. // code should be equal with the result of the the `context.StatusCodeNotSuccessful` in order to be received as an "http error handler".
  391. //
  392. // Developer may want this option to setted as true in order to manually call the
  393. // error handlers when needed via "context#FireStatusCode(< 200 || >= 400)".
  394. // HTTP Custom error handlers are being registered via app.OnErrorCode(code, handler)".
  395. //
  396. // Defaults to false.
  397. DisableAutoFireStatusCode bool `json:"disableAutoFireStatusCode,omitempty" yaml:"DisableAutoFireStatusCode" toml:"DisableAutoFireStatusCode"`
  398. // TimeFormat time format for any kind of datetime parsing
  399. // Defaults to "Mon, 02 Jan 2006 15:04:05 GMT".
  400. TimeFormat string `json:"timeFormat,omitempty" yaml:"TimeFormat" toml:"TimeFormat"`
  401. // Charset character encoding for various rendering
  402. // used for templates and the rest of the responses
  403. // Defaults to "UTF-8".
  404. Charset string `json:"charset,omitempty" yaml:"Charset" toml:"Charset"`
  405. // PostMaxMemory sets the maximum post data size
  406. // that a client can send to the server, this differs
  407. // from the overral request body size which can be modified
  408. // by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
  409. //
  410. // Defaults to 32MB or 32 << 20 if you prefer.
  411. PostMaxMemory int64 `json:"postMaxMemory" yaml:"PostMaxMemory" toml:"PostMaxMemory"`
  412. // +----------------------------------------------------+
  413. // | Context's keys for values used on various featuers |
  414. // +----------------------------------------------------+
  415. // Context values' keys for various features.
  416. //
  417. // TranslateLanguageContextKey & TranslateFunctionContextKey are used by i18n handlers/middleware
  418. // currently we have only one: https://github.com/kataras/iris/tree/master/middleware/i18n.
  419. //
  420. // Defaults to "iris.translate" and "iris.language"
  421. TranslateFunctionContextKey string `json:"translateFunctionContextKey,omitempty" yaml:"TranslateFunctionContextKey" toml:"TranslateFunctionContextKey"`
  422. // TranslateLanguageContextKey used for i18n.
  423. //
  424. // Defaults to "iris.language"
  425. TranslateLanguageContextKey string `json:"translateLanguageContextKey,omitempty" yaml:"TranslateLanguageContextKey" toml:"TranslateLanguageContextKey"`
  426. // GetViewLayoutContextKey is the key of the context's user values' key
  427. // which is being used to set the template
  428. // layout from a middleware or the main handler.
  429. // Overrides the parent's or the configuration's.
  430. //
  431. // Defaults to "iris.ViewLayout"
  432. ViewLayoutContextKey string `json:"viewLayoutContextKey,omitempty" yaml:"ViewLayoutContextKey" toml:"ViewLayoutContextKey"`
  433. // GetViewDataContextKey is the key of the context's user values' key
  434. // which is being used to set the template
  435. // binding data from a middleware or the main handler.
  436. //
  437. // Defaults to "iris.viewData"
  438. ViewDataContextKey string `json:"viewDataContextKey,omitempty" yaml:"ViewDataContextKey" toml:"ViewDataContextKey"`
  439. // RemoteAddrHeaders are the allowed request headers names
  440. // that can be valid to parse the client's IP based on.
  441. // By-default no "X-" header is consired safe to be used for retrieving the
  442. // client's IP address, because those headers can manually change by
  443. // the client. But sometimes are useful e.g., when behind a proxy
  444. // you want to enable the "X-Forwarded-For" or when cloudflare
  445. // you want to enable the "CF-Connecting-IP", inneed you
  446. // can allow the `ctx.RemoteAddr()` to use any header
  447. // that the client may sent.
  448. //
  449. // Defaults to an empty map but an example usage is:
  450. // RemoteAddrHeaders {
  451. // "X-Real-Ip": true,
  452. // "X-Forwarded-For": true,
  453. // "CF-Connecting-IP": true,
  454. // }
  455. //
  456. // Look `context.RemoteAddr()` for more.
  457. RemoteAddrHeaders map[string]bool `json:"remoteAddrHeaders,omitempty" yaml:"RemoteAddrHeaders" toml:"RemoteAddrHeaders"`
  458. // Other are the custom, dynamic options, can be empty.
  459. // This field used only by you to set any app's options you want.
  460. //
  461. // Defaults to a non-nil empty map.
  462. Other map[string]interface{} `json:"other,omitempty" yaml:"Other" toml:"Other"`
  463. }
  464. var _ context.ConfigurationReadOnly = &Configuration{}
  465. // GetVHost returns the non-exported vhost config field.
  466. //
  467. // If original addr ended with :443 or :80, it will return the host without the port.
  468. // If original addr was :https or :http, it will return localhost.
  469. // If original addr was 0.0.0.0, it will return localhost.
  470. func (c Configuration) GetVHost() string {
  471. return c.vhost
  472. }
  473. // GetDisablePathCorrection returns the Configuration#DisablePathCorrection,
  474. // DisablePathCorrection corrects and redirects the requested path to the registered path
  475. // for example, if /home/ path is requested but no handler for this Route found,
  476. // then the Router checks if /home handler exists, if yes,
  477. // (permant)redirects the client to the correct path /home.
  478. func (c Configuration) GetDisablePathCorrection() bool {
  479. return c.DisablePathCorrection
  480. }
  481. // GetEnablePathEscape is the Configuration#EnablePathEscape,
  482. // returns true when its escapes the path, the named parameters (if any).
  483. func (c Configuration) GetEnablePathEscape() bool {
  484. return c.EnablePathEscape
  485. }
  486. // GetEnableOptimizations returns whether
  487. // the application has performance optimizations enabled.
  488. func (c Configuration) GetEnableOptimizations() bool {
  489. return c.EnableOptimizations
  490. }
  491. // GetFireMethodNotAllowed returns the Configuration#FireMethodNotAllowed.
  492. func (c Configuration) GetFireMethodNotAllowed() bool {
  493. return c.FireMethodNotAllowed
  494. }
  495. // GetDisableBodyConsumptionOnUnmarshal returns the Configuration#GetDisableBodyConsumptionOnUnmarshal,
  496. // manages the reading behavior of the context's body readers/binders.
  497. // If returns true then the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`
  498. // is disabled.
  499. //
  500. // By-default io.ReadAll` is used to read the body from the `context.Request.Body which is an `io.ReadCloser`,
  501. // if this field setted to true then a new buffer will be created to read from and the request body.
  502. // The body will not be changed and existing data before the
  503. // context.UnmarshalBody/ReadJSON/ReadXML will be not consumed.
  504. func (c Configuration) GetDisableBodyConsumptionOnUnmarshal() bool {
  505. return c.DisableBodyConsumptionOnUnmarshal
  506. }
  507. // GetDisableAutoFireStatusCode returns the Configuration#DisableAutoFireStatusCode.
  508. // Returns true when the http error status code handler automatic execution turned off.
  509. func (c Configuration) GetDisableAutoFireStatusCode() bool {
  510. return c.DisableAutoFireStatusCode
  511. }
  512. // GetTimeFormat returns the Configuration#TimeFormat,
  513. // format for any kind of datetime parsing.
  514. func (c Configuration) GetTimeFormat() string {
  515. return c.TimeFormat
  516. }
  517. // GetCharset returns the Configuration#Charset,
  518. // the character encoding for various rendering
  519. // used for templates and the rest of the responses.
  520. func (c Configuration) GetCharset() string {
  521. return c.Charset
  522. }
  523. // GetPostMaxMemory returns the maximum configured post data size
  524. // that a client can send to the server, this differs
  525. // from the overral request body size which can be modified
  526. // by the `context#SetMaxRequestBodySize` or `iris#LimitRequestBodySize`.
  527. //
  528. // Defaults to 32MB or 32 << 20 if you prefer.
  529. func (c Configuration) GetPostMaxMemory() int64 {
  530. return c.PostMaxMemory
  531. }
  532. // GetTranslateFunctionContextKey returns the configuration's TranslateFunctionContextKey value,
  533. // used for i18n.
  534. func (c Configuration) GetTranslateFunctionContextKey() string {
  535. return c.TranslateFunctionContextKey
  536. }
  537. // GetTranslateLanguageContextKey returns the configuration's TranslateLanguageContextKey value,
  538. // used for i18n.
  539. func (c Configuration) GetTranslateLanguageContextKey() string {
  540. return c.TranslateLanguageContextKey
  541. }
  542. // GetViewLayoutContextKey returns the key of the context's user values' key
  543. // which is being used to set the template
  544. // layout from a middleware or the main handler.
  545. // Overrides the parent's or the configuration's.
  546. func (c Configuration) GetViewLayoutContextKey() string {
  547. return c.ViewLayoutContextKey
  548. }
  549. // GetViewDataContextKey returns the key of the context's user values' key
  550. // which is being used to set the template
  551. // binding data from a middleware or the main handler.
  552. func (c Configuration) GetViewDataContextKey() string {
  553. return c.ViewDataContextKey
  554. }
  555. // GetRemoteAddrHeaders returns the allowed request headers names
  556. // that can be valid to parse the client's IP based on.
  557. // By-default no "X-" header is consired safe to be used for retrieving the
  558. // client's IP address, because those headers can manually change by
  559. // the client. But sometimes are useful e.g., when behind a proxy
  560. // you want to enable the "X-Forwarded-For" or when cloudflare
  561. // you want to enable the "CF-Connecting-IP", inneed you
  562. // can allow the `ctx.RemoteAddr()` to use any header
  563. // that the client may sent.
  564. //
  565. // Defaults to an empty map but an example usage is:
  566. // RemoteAddrHeaders {
  567. // "X-Real-Ip": true,
  568. // "X-Forwarded-For": true,
  569. // "CF-Connecting-IP": true,
  570. // }
  571. //
  572. // Look `context.RemoteAddr()` for more.
  573. func (c Configuration) GetRemoteAddrHeaders() map[string]bool {
  574. return c.RemoteAddrHeaders
  575. }
  576. // GetOther returns the Configuration#Other map.
  577. func (c Configuration) GetOther() map[string]interface{} {
  578. return c.Other
  579. }
  580. // WithConfiguration sets the "c" values to the framework's configurations.
  581. //
  582. // Usage:
  583. // app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{/* fields here */ }))
  584. // or
  585. // iris.WithConfiguration(iris.YAML("./cfg/iris.yml"))
  586. // or
  587. // iris.WithConfiguration(iris.TOML("./cfg/iris.tml"))
  588. func WithConfiguration(c Configuration) Configurator {
  589. return func(app *Application) {
  590. main := app.config
  591. if v := c.IgnoreServerErrors; len(v) > 0 {
  592. main.IgnoreServerErrors = append(main.IgnoreServerErrors, v...)
  593. }
  594. if v := c.DisableStartupLog; v {
  595. main.DisableStartupLog = v
  596. }
  597. if v := c.DisableInterruptHandler; v {
  598. main.DisableInterruptHandler = v
  599. }
  600. if v := c.DisableVersionChecker; v {
  601. main.DisableVersionChecker = v
  602. }
  603. if v := c.DisablePathCorrection; v {
  604. main.DisablePathCorrection = v
  605. }
  606. if v := c.EnablePathEscape; v {
  607. main.EnablePathEscape = v
  608. }
  609. if v := c.EnableOptimizations; v {
  610. main.EnableOptimizations = v
  611. }
  612. if v := c.FireMethodNotAllowed; v {
  613. main.FireMethodNotAllowed = v
  614. }
  615. if v := c.DisableBodyConsumptionOnUnmarshal; v {
  616. main.DisableBodyConsumptionOnUnmarshal = v
  617. }
  618. if v := c.DisableAutoFireStatusCode; v {
  619. main.DisableAutoFireStatusCode = v
  620. }
  621. if v := c.TimeFormat; v != "" {
  622. main.TimeFormat = v
  623. }
  624. if v := c.Charset; v != "" {
  625. main.Charset = v
  626. }
  627. if v := c.PostMaxMemory; v > 0 {
  628. main.PostMaxMemory = v
  629. }
  630. if v := c.TranslateFunctionContextKey; v != "" {
  631. main.TranslateFunctionContextKey = v
  632. }
  633. if v := c.TranslateLanguageContextKey; v != "" {
  634. main.TranslateLanguageContextKey = v
  635. }
  636. if v := c.ViewLayoutContextKey; v != "" {
  637. main.ViewLayoutContextKey = v
  638. }
  639. if v := c.ViewDataContextKey; v != "" {
  640. main.ViewDataContextKey = v
  641. }
  642. if v := c.RemoteAddrHeaders; len(v) > 0 {
  643. if main.RemoteAddrHeaders == nil {
  644. main.RemoteAddrHeaders = make(map[string]bool, len(v))
  645. }
  646. for key, value := range v {
  647. main.RemoteAddrHeaders[key] = value
  648. }
  649. }
  650. if v := c.Other; len(v) > 0 {
  651. if main.Other == nil {
  652. main.Other = make(map[string]interface{}, len(v))
  653. }
  654. for key, value := range v {
  655. main.Other[key] = value
  656. }
  657. }
  658. }
  659. }
  660. // DefaultConfiguration returns the default configuration for an iris station, fills the main Configuration
  661. func DefaultConfiguration() Configuration {
  662. return Configuration{
  663. DisableStartupLog: false,
  664. DisableInterruptHandler: false,
  665. DisableVersionChecker: false,
  666. DisablePathCorrection: false,
  667. EnablePathEscape: false,
  668. FireMethodNotAllowed: false,
  669. DisableBodyConsumptionOnUnmarshal: false,
  670. DisableAutoFireStatusCode: false,
  671. TimeFormat: "Mon, Jan 02 2006 15:04:05 GMT",
  672. Charset: "UTF-8",
  673. // PostMaxMemory is for post body max memory.
  674. //
  675. // The request body the size limit
  676. // can be set by the middleware `LimitRequestBodySize`
  677. // or `context#SetMaxRequestBodySize`.
  678. PostMaxMemory: 32 << 20, // 32MB
  679. TranslateFunctionContextKey: "iris.translate",
  680. TranslateLanguageContextKey: "iris.language",
  681. ViewLayoutContextKey: "iris.viewLayout",
  682. ViewDataContextKey: "iris.viewData",
  683. RemoteAddrHeaders: make(map[string]bool),
  684. EnableOptimizations: false,
  685. Other: make(map[string]interface{}),
  686. }
  687. }