diff --git a/HISTORY.md b/HISTORY.md
index cc42612f..3e31ac49 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -18,6 +18,109 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
+# Sa, 29 July 2017 | v8.1.1
+
+No breaking changes, just an addition to make your life easier.
+
+This feature has been implemented after @corebreaker 's request, posted at: https://github.com/kataras/iris/issues/688. He was also tried to fix that by a [PR](https://github.com/kataras/iris/pull/689), we thanks him but the problem with that PR was the duplication and the separation of concepts, however we thanks him for pushing for a solution. The current feature's implementation gives a permant solution to host supervisor access issues.
+
+Optional host configurators added to all common serve and listen functions.
+
+Below you'll find how to gain access to the host, **the second way is the new feature.**
+
+### Hosts
+
+Access to all hosts that serve your application can be provided by
+the `Application#Hosts` field, after the `Run` method.
+
+But the most common scenario is that you may need access to the host before the `Run` method,
+there are two ways of gain access to the host supervisor, read below.
+
+First way is to use the `app.NewHost` to create a new host
+and use one of its `Serve` or `Listen` functions
+to start the application via the `iris#Raw` Runner.
+Note that this way needs an extra import of the `net/http` package.
+
+Example Code:
+
+```go
+h := app.NewHost(&http.Server{Addr:":8080"})
+h.RegisterOnShutdown(func(){
+ println("server was closed!")
+})
+
+app.Run(iris.Raw(h.ListenAndServe))
+```
+
+Second, and probably easier way is to use the `host.Configurator`.
+
+Note that this method requires an extra import statement of
+"github.com/kataras/iris/core/host" when using go < 1.9,
+if you're targeting on go1.9 then you can use the `iris#Supervisor`
+and omit the extra host import.
+
+All common `Runners` we saw earlier (`iris#Addr, iris#Listener, iris#Server, iris#TLS, iris#AutoTLS`)
+accept a variadic argument of `host.Configurator`, there are just `func(*host.Supervisor)`.
+Therefore the `Application` gives you the rights to modify the auto-created host supervisor through these.
+
+
+Example Code:
+
+```go
+package main
+
+import (
+ stdContext "context"
+ "time"
+
+ "github.com/kataras/iris"
+ "github.com/kataras/iris/context"
+ "github.com/kataras/iris/core/host"
+)
+
+func main() {
+ app := iris.New()
+
+ app.Get("/", func(ctx context.Context) {
+ ctx.HTML("
Hello, try to refresh the page after ~10 secs
")
+ })
+
+ app.Logger().Info("Wait 10 seconds and check your terminal again")
+ // simulate a shutdown action here...
+ go func() {
+ <-time.After(10 * time.Second)
+ timeout := 5 * time.Second
+ ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
+ defer cancel()
+ // close all hosts, this will notify the callback we had register
+ // inside the `configureHost` func.
+ app.Shutdown(ctx)
+ }()
+
+ // start the server as usual, the only difference is that
+ // we're adding a second (optional) function
+ // to configure the just-created host supervisor.
+ //
+ // http://localhost:8080
+ // wait 10 seconds and check your terminal.
+ app.Run(iris.Addr(":8080", configureHost), iris.WithoutServerError(iris.ErrServerClosed))
+
+}
+
+func configureHost(su *host.Supervisor) {
+ // here we have full access to the host that will be created
+ // inside the `Run` function.
+ //
+ // we register a shutdown "event" callback
+ su.RegisterOnShutdown(func() {
+ println("server is closed")
+ })
+ // su.RegisterOnError
+ // su.RegisterOnServe
+}
+```
+
+Read more about listening and gracefully shutdown by navigating to: https://github.com/kataras/iris/tree/master/_examples/#http-listening
# We, 26 July 2017 | v8.1.0
diff --git a/README.md b/README.md
index a153f83f..91539b2c 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ Iris is a fast, simple and efficient micro web framework for Go. It provides a b
### 📑 Table of contents
* [Installation](#-installation)
-* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#we-26-july-2017--v810)
+* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#sa-29-july-2017--v811)
* [Learn](#-learn)
* [HTTP Listening](_examples/#http-listening)
* [Configuration](_examples/#configuration)
@@ -340,7 +340,7 @@ Thank You for your trust!
### 📌 Version
-Current: **8.1.0**
+Current: **8.1.1**
Each new release is pushed to the master. It stays there until the next version. When a next version is released then the previous version goes to its own branch with `gopkg.in` as its import path (and its own vendor folder), in order to keep it working "for-ever".
diff --git a/_examples/README.md b/_examples/README.md
index fe6ad8ca..2dee2ade 100644
--- a/_examples/README.md
+++ b/_examples/README.md
@@ -31,7 +31,8 @@ It doesn't always contain the "best ways" but it does cover each important featu
- Graceful Shutdown
* [using the `RegisterOnInterrupt`](http-listening/graceful-shutdown/default-notifier/main.go)
* [using a custom notifier](http-listening/graceful-shutdown/custom-notifier/main.go)
-
+ * [notify on shutdown](http-listening/graceful-shutdown/notify-on-shutdown/main.go)
+
### Configuration
- [Functional](configuration/functional/main.go)
diff --git a/_examples/http-listening/notify-on-shutdown/main.go b/_examples/http-listening/notify-on-shutdown/main.go
new file mode 100644
index 00000000..8fe15607
--- /dev/null
+++ b/_examples/http-listening/notify-on-shutdown/main.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ stdContext "context"
+ "time"
+
+ "github.com/kataras/iris"
+ "github.com/kataras/iris/context"
+ "github.com/kataras/iris/core/host"
+)
+
+func main() {
+ app := iris.New()
+
+ app.Get("/", func(ctx context.Context) {
+ ctx.HTML("Hello, try to refresh the page after ~10 secs
")
+ })
+
+ app.Logger().Info("Wait 10 seconds and check your terminal again")
+ // simulate a shutdown action here...
+ go func() {
+ <-time.After(10 * time.Second)
+ timeout := 5 * time.Second
+ ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
+ defer cancel()
+ // close all hosts, this will notify the callback we had register
+ // inside the `configureHost` func.
+ app.Shutdown(ctx)
+ }()
+
+ // start the server as usual, the only difference is that
+ // we're adding a second (optional) function
+ // to configure the just-created host supervisor.
+ //
+ // http://localhost:8080
+ // wait 10 seconds and check your terminal.
+ app.Run(iris.Addr(":8080", configureHost), iris.WithoutServerError(iris.ErrServerClosed))
+
+}
+
+func configureHost(su *host.Supervisor) {
+ // here we have full access to the host that will be created
+ // inside the `Run` function.
+ //
+ // we register a shutdown "event" callback
+ su.RegisterOnShutdown(func() {
+ println("server is closed")
+ })
+ // su.RegisterOnError
+ // su.RegisterOnServe
+}
diff --git a/context.go b/context.go
index 673dde23..81c3bb4f 100644
--- a/context.go
+++ b/context.go
@@ -4,8 +4,11 @@ package iris
import (
"github.com/kataras/iris/context"
+ "github.com/kataras/iris/core/host"
)
+// TODO: When go 1.9 will be released
+// split this file in order to separate the concepts.
type (
// Context is the midle-man server's "object" for the clients.
//
@@ -32,4 +35,9 @@ type (
Handler = context.Handler
// A Map is a shortcut of the map[string]interface{}.
Map = context.Map
+
+ // Supervisor is a shortcut of the `host#Supervisor`.
+ // Used to add supervisor configurators on common Runners
+ // without the need of importing the `core/host` package.
+ Supervisor = host.Supervisor
)
diff --git a/core/host/supervisor.go b/core/host/supervisor.go
index 3def0a9f..688f2f44 100644
--- a/core/host/supervisor.go
+++ b/core/host/supervisor.go
@@ -13,6 +13,12 @@ import (
"golang.org/x/crypto/acme/autocert"
)
+// Configurator provides an easy way to modify
+// the Supervisor.
+//
+// Look the `Configure` func for more.
+type Configurator func(su *Supervisor)
+
// Supervisor is the wrapper and the manager for a compatible server
// and it's relative actions, called Tasks.
//
@@ -54,6 +60,22 @@ func New(srv *http.Server) *Supervisor {
}
}
+// Configure accepts one or more `Configurator`.
+// With this function you can use simple functions
+// that are spread across your app to modify
+// the supervisor, these Configurators can be
+// used on any Supervisor instance.
+//
+// Look `Configurator` too.
+//
+// Returns itself.
+func (su *Supervisor) Configure(configurators ...Configurator) *Supervisor {
+ for _, conf := range configurators {
+ conf(su)
+ }
+ return su
+}
+
// DeferFlow defers the flow of the exeuction,
// i.e: when server should return error and exit
// from app, a DeferFlow call inside a Task
diff --git a/doc.go b/doc.go
index a3d898ca..af92e110 100644
--- a/doc.go
+++ b/doc.go
@@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub:
Current Version
-8.1.0
+8.1.1
Installation
@@ -303,6 +303,99 @@ Example code:
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
}
+
+Hosts
+
+Access to all hosts that serve your application can be provided by
+the `Application#Hosts` field, after the `Run` method.
+
+
+But the most common scenario is that you may need access to the host before the `Run` method,
+there are two ways of gain access to the host supervisor, read below.
+
+First way is to use the `app.NewHost` to create a new host
+and use one of its `Serve` or `Listen` functions
+to start the application via the `iris#Raw` Runner.
+Note that this way needs an extra import of the `net/http` package.
+
+Example Code:
+
+
+ h := app.NewHost(&http.Server{Addr:":8080"})
+ h.RegisterOnShutdown(func(){
+ println("server was closed!")
+ })
+
+ app.Run(iris.Raw(h.ListenAndServe))
+
+Second, and probably easier way is to use the `host.Configurator`.
+
+Note that this method requires an extra import statement of
+"github.com/kataras/iris/core/host" when using go < 1.9,
+if you're targeting on go1.9 then you can use the `iris#Supervisor`
+and omit the extra host import.
+
+All common `Runners` we saw earlier (`iris#Addr, iris#Listener, iris#Server, iris#TLS, iris#AutoTLS`)
+accept a variadic argument of `host.Configurator`, there are just `func(*host.Supervisor)`.
+Therefore the `Application` gives you the rights to modify the auto-created host supervisor through these.
+
+
+Example Code:
+
+
+ package main
+
+ import (
+ stdContext "context"
+ "time"
+
+ "github.com/kataras/iris"
+ "github.com/kataras/iris/context"
+ "github.com/kataras/iris/core/host"
+ )
+
+ func main() {
+ app := iris.New()
+
+ app.Get("/", func(ctx context.Context) {
+ ctx.HTML("Hello, try to refresh the page after ~10 secs
")
+ })
+
+ app.Logger().Info("Wait 10 seconds and check your terminal again")
+ // simulate a shutdown action here...
+ go func() {
+ <-time.After(10 * time.Second)
+ timeout := 5 * time.Second
+ ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
+ defer cancel()
+ // close all hosts, this will notify the callback we had register
+ // inside the `configureHost` func.
+ app.Shutdown(ctx)
+ }()
+
+ // start the server as usual, the only difference is that
+ // we're adding a second (optional) function
+ // to configure the just-created host supervisor.
+ //
+ // http://localhost:8080
+ // wait 10 seconds and check your terminal.
+ app.Run(iris.Addr(":8080", configureHost), iris.WithoutServerError(iris.ErrServerClosed))
+
+ }
+
+ func configureHost(su *host.Supervisor) {
+ // here we have full access to the host that will be created
+ // inside the `Run` function.
+ //
+ // we register a shutdown "event" callback
+ su.RegisterOnShutdown(func() {
+ println("server is closed")
+ })
+ // su.RegisterOnError
+ // su.RegisterOnServe
+ }
+
+
Read more about listening and gracefully shutdown by navigating to:
https://github.com/kataras/iris/tree/master/_examples/#http-listening
diff --git a/iris.go b/iris.go
index 588a60f8..04154c65 100644
--- a/iris.go
+++ b/iris.go
@@ -33,7 +33,7 @@ import (
const (
// Version is the current version number of the Iris Web Framework.
- Version = "8.1.0"
+ Version = "8.1.1"
)
// HTTP status codes as registered with IANA.
@@ -397,11 +397,20 @@ type Runner func(*Application) error
// Listener can be used as an argument for the `Run` method.
// It can start a server with a custom net.Listener via server's `Serve`.
//
+// Second argument is optional, it accepts one or more
+// `func(*host.Configurator)` that are being executed
+// on that specific host that this function will create to start the server.
+// Via host configurators you can configure the back-end host supervisor,
+// i.e to add events for shutdown, serve or error.
+// An example of this use case can be found at:
+// https://github.com/kataras/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go
+//
// See `Run` for more.
-func Listener(l net.Listener) Runner {
+func Listener(l net.Listener, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error {
app.config.vhost = netutil.ResolveVHost(l.Addr().String())
return app.NewHost(new(http.Server)).
+ Configure(hostConfigs...).
Serve(l)
}
}
@@ -409,10 +418,19 @@ func Listener(l net.Listener) Runner {
// Server can be used as an argument for the `Run` method.
// It can start a server with a *http.Server.
//
+// Second argument is optional, it accepts one or more
+// `func(*host.Configurator)` that are being executed
+// on that specific host that this function will create to start the server.
+// Via host configurators you can configure the back-end host supervisor,
+// i.e to add events for shutdown, serve or error.
+// An example of this use case can be found at:
+// https://github.com/kataras/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go
+//
// See `Run` for more.
-func Server(srv *http.Server) Runner {
+func Server(srv *http.Server, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error {
return app.NewHost(srv).
+ Configure(hostConfigs...).
ListenAndServe()
}
}
@@ -423,10 +441,19 @@ func Server(srv *http.Server) Runner {
//
// Addr should have the form of [host]:port, i.e localhost:8080 or :8080.
//
+// Second argument is optional, it accepts one or more
+// `func(*host.Configurator)` that are being executed
+// on that specific host that this function will create to start the server.
+// Via host configurators you can configure the back-end host supervisor,
+// i.e to add events for shutdown, serve or error.
+// An example of this use case can be found at:
+// https://github.com/kataras/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go
+//
// See `Run` for more.
-func Addr(addr string) Runner {
+func Addr(addr string, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error {
return app.NewHost(&http.Server{Addr: addr}).
+ Configure(hostConfigs...).
ListenAndServe()
}
}
@@ -439,10 +466,19 @@ func Addr(addr string) Runner {
// Addr should have the form of [host]:port, i.e localhost:443 or :443.
// CertFile & KeyFile should be filenames with their extensions.
//
+// Second argument is optional, it accepts one or more
+// `func(*host.Configurator)` that are being executed
+// on that specific host that this function will create to start the server.
+// Via host configurators you can configure the back-end host supervisor,
+// i.e to add events for shutdown, serve or error.
+// An example of this use case can be found at:
+// https://github.com/kataras/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go
+//
// See `Run` for more.
-func TLS(addr string, certFile, keyFile string) Runner {
+func TLS(addr string, certFile, keyFile string, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error {
return app.NewHost(&http.Server{Addr: addr}).
+ Configure(hostConfigs...).
ListenAndServeTLS(certFile, keyFile)
}
}
@@ -454,10 +490,19 @@ func TLS(addr string, certFile, keyFile string) Runner {
//
// Addr should have the form of [host]:port, i.e mydomain.com:443.
//
+// Second argument is optional, it accepts one or more
+// `func(*host.Configurator)` that are being executed
+// on that specific host that this function will create to start the server.
+// Via host configurators you can configure the back-end host supervisor,
+// i.e to add events for shutdown, serve or error.
+// An example of this use case can be found at:
+// https://github.com/kataras/iris/blob/master/_examples/http-listening/notify-on-shutdown/main.go
+//
// See `Run` for more.
-func AutoTLS(addr string) Runner {
+func AutoTLS(addr string, hostConfigs ...host.Configurator) Runner {
return func(app *Application) error {
return app.NewHost(&http.Server{Addr: addr}).
+ Configure(hostConfigs...).
ListenAndServeAutoTLS()
}
}