diff --git a/HISTORY.md b/HISTORY.md
index 2ed273f6..b7b71028 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,6 +2,27 @@
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris`.
+## 4.2.3 -> 4.2.4
+
+- **NEW Experimental feature**: Updater with a `CheckForUpdates` [configuration](https://github.com/kataras/iris/blob/master/configuration.go) field, as requested [here](https://github.com/kataras/iris/issues/401)
+```go
+// CheckForUpdates will try to search for newer version of Iris based on the https://github.com/kataras/iris/releases
+// If a newer version found then the app will ask the he dev/user if want to update the 'x' version
+// if 'y' is pressed then the updater will try to install the latest version
+// the updater, will notify the dev/user that the update is finished and should restart the App manually.
+// Notes:
+// 1. Experimental feature
+// 2. If setted to true, the app will have a little startup delay
+// 3. If you as developer edited the $GOPATH/src/github/kataras or any other Iris' Go dependencies at the past
+// then the update process will fail.
+//
+// Usage: iris.Set(iris.OptionCheckForUpdates(true)) or
+// iris.Config.CheckForUpdates = true or
+// app := iris.New(iris.OptionCheckForUpdates(true))
+// Default is false
+CheckForUpdates bool
+```
+
## 4.2.2 -> 4.2.3
- [Add IsAjax() convenience method](https://github.com/kataras/iris/issues/423)
diff --git a/README.md b/README.md
index 452d5131..dc182b76 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
-
+
@@ -181,7 +181,7 @@ I recommend writing your API tests using this new library, [httpexpect](https://
Versioning
------------
-Current: **v4.2.3**
+Current: **v4.2.4**
> Iris is an active project
@@ -224,7 +224,7 @@ License can be found [here](LICENSE).
[Travis]: http://travis-ci.org/kataras/iris
[License Widget]: https://img.shields.io/badge/license-Apache%202.0%20%20-E91E63.svg?style=flat-square
[License]: https://github.com/kataras/iris/blob/master/LICENSE
-[Release Widget]: https://img.shields.io/badge/release-v4.2.3-blue.svg?style=flat-square
+[Release Widget]: https://img.shields.io/badge/release-v4.2.4-blue.svg?style=flat-square
[Release]: https://github.com/kataras/iris/releases
[Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
[Chat]: https://kataras.rocket.chat/channel/iris
diff --git a/configuration.go b/configuration.go
index 7ecb970a..2b536357 100644
--- a/configuration.go
+++ b/configuration.go
@@ -41,6 +41,22 @@ func (o OptionSet) Set(c *Configuration) {
//
// Configuration is also implements the OptionSet so it's a valid option itself, this is briliant enough
type Configuration struct {
+ // CheckForUpdates will try to search for newer version of Iris based on the https://github.com/kataras/iris/releases
+ // If a newer version found then the app will ask the he dev/user if want to update the 'x' version
+ // if 'y' is pressed then the updater will try to install the latest version
+ // the updater, will notify the dev/user that the update is finished and should restart the App manually.
+ // Notes:
+ // 1. Experimental feature
+ // 2. If setted to true, the app will have a little startup delay
+ // 3. If you as developer edited the $GOPATH/src/github/kataras or any other Iris' Go dependencies at the past
+ // then the update process will fail.
+ //
+ // Usage: iris.Set(iris.OptionCheckForUpdates(true)) or
+ // iris.Config.CheckForUpdates = true or
+ // app := iris.New(iris.OptionCheckForUpdates(true))
+ // Default is false
+ CheckForUpdates bool
+
// DisablePathCorrection corrects and redirects the requested path to the registed path
// for example, if /home/ path is requested but no handler for this Route found,
// then the Router checks if /home handler exists, if yes,
@@ -151,6 +167,27 @@ func (c Configuration) Set(main *Configuration) {
// All options starts with "Option" preffix in order to be easier to find what dev searching for
var (
+ // OptionCheckForUpdates will try to search for newer version of Iris based on the https://github.com/kataras/iris/releases
+ // If a newer version found then the app will ask the he dev/user if want to update the 'x' version
+ // if 'y' is pressed then the updater will try to install the latest version
+ // the updater, will notify the dev/user that the update is finished and should restart the App manually.
+ // Notes:
+ // 1. Experimental feature
+ // 2. If setted to true, the app will have a little startup delay
+ // 3. If you as developer edited the $GOPATH/src/github/kataras or any other Iris' Go dependencies at the past
+ // then the update process will fail.
+ //
+ // Usage: iris.Set(iris.OptionCheckForUpdates(true)) or
+ // iris.Config.CheckForUpdates = true or
+ // app := iris.New(iris.OptionCheckForUpdates(true))
+ // Default is false
+ OptionCheckForUpdates = func(val bool) OptionSet {
+ return func(c *Configuration) {
+ c.CheckForUpdates = val
+ }
+
+ }
+
// OptionDisablePathCorrection corrects and redirects the requested path to the registed path
// for example, if /home/ path is requested but no handler for this Route found,
// then the Router checks if /home handler exists, if yes,
@@ -163,12 +200,14 @@ var (
}
}
+
// OptionDisablePathEscape when is false then its escapes the path, the named parameters (if any).
OptionDisablePathEscape = func(val bool) OptionSet {
return func(c *Configuration) {
c.DisablePathEscape = val
}
}
+
// OptionDisableBanner outputs the iris banner at startup
//
// Default is false
@@ -177,6 +216,7 @@ var (
c.DisableBanner = val
}
}
+
// OptionLoggerOut is the destination for output
//
// Default is os.Stdout
@@ -185,6 +225,7 @@ var (
c.LoggerOut = val
}
}
+
// OptionLoggerPreffix is the logger's prefix to write at beginning of each line
//
// Default is [IRIS]
@@ -193,6 +234,7 @@ var (
c.LoggerPreffix = val
}
}
+
// OptionProfilePath a the route path, set it to enable http pprof tool
// Default is empty, if you set it to a $path, these routes will handled:
OptionProfilePath = func(val string) OptionSet {
@@ -200,6 +242,7 @@ var (
c.ProfilePath = val
}
}
+
// OptionDisableTemplateEngines set to true to disable loading the default template engine (html/template) and disallow the use of iris.UseEngine
// Default is false
OptionDisableTemplateEngines = func(val bool) OptionSet {
@@ -207,6 +250,7 @@ var (
c.DisableTemplateEngines = val
}
}
+
// OptionIsDevelopment iris will act like a developer, for example
// If true then re-builds the templates on each request
// Default is false
@@ -215,12 +259,14 @@ var (
c.IsDevelopment = val
}
}
+
// OptionTimeFormat time format for any kind of datetime parsing
OptionTimeFormat = func(val string) OptionSet {
return func(c *Configuration) {
c.TimeFormat = val
}
}
+
// OptionCharset character encoding for various rendering
// used for templates and the rest of the responses
// Default is "UTF-8"
@@ -229,6 +275,7 @@ var (
c.Charset = val
}
}
+
// OptionGzip enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content
// If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true})
// Default is false
@@ -282,6 +329,7 @@ var (
// DefaultConfiguration returns the default configuration for an Iris station, fills the main Configuration
func DefaultConfiguration() Configuration {
return Configuration{
+ CheckForUpdates: false,
DisablePathCorrection: DefaultDisablePathCorrection,
DisablePathEscape: DefaultDisablePathEscape,
DisableBanner: false,
diff --git a/iris.go b/iris.go
index 91a56644..edeec268 100644
--- a/iris.go
+++ b/iris.go
@@ -77,8 +77,8 @@ import (
)
const (
- // Version of the iris
- Version = "4.2.3"
+ // Version is the current version of the Iris web framework
+ Version = "4.2.4"
banner = ` _____ _
|_ _| (_)
@@ -257,6 +257,56 @@ func (s *Framework) Set(setters ...OptionSetter) {
for _, setter := range setters {
setter.Set(s.Config)
}
+
+ // because of the reason that an update can be executed while Iris is running,
+ // this is the only configuration field which is re-checked at runtime for that type of action.
+ //
+ // note: we could use the IsDevelopment configuration field to do that BUT
+ // the developer may want to check for updates without, for example, re-build template files (comes from IsDevelopment) on each request
+ if s.Config.CheckForUpdates {
+ if s.updateIris() { // if updated, then do not run the web server
+ exitWaitDuration := time.Duration(0)
+ if s.Logger != nil {
+ exitWaitDuration = 5 * time.Second
+ s.Logger.Println("exiting now...")
+ }
+
+ time.AfterFunc(exitWaitDuration, func() {
+ os.Exit(0)
+ })
+ }
+ }
+}
+
+// global once because is not necessary to check for updates on more than one iris station*
+var updateOnce sync.Once
+
+const (
+ githubOwner = "kataras"
+ githubRepo = "iris"
+)
+
+func (s *Framework) updateIris() bool {
+ updated := false
+
+ updateOnce.Do(func() {
+ writer := s.Config.LoggerOut
+
+ if writer == nil {
+ writer = os.Stdout // we need a writer because the update process will not be silent.
+ }
+
+ fs.DefaultUpdaterAlreadyInstalledMessage = "INFO: Running with the latest version(%s)\n"
+ updater, err := fs.GetUpdater(githubOwner, githubRepo, Version)
+
+ if err != nil {
+ writer.Write([]byte("Update failed: " + err.Error()))
+ }
+
+ updated = updater.Run(fs.Stdout(writer), fs.Stderr(writer), fs.Silent(false))
+ })
+
+ return updated
}
func (s *Framework) initialize() {