configuration.go 42 KB

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