iris/_examples/http-server/README.md
Gerasimos (Makis) Maropoulos a018ba9b0a
add example for #1601
2020-08-22 03:21:44 +03:00

206 lines
6.0 KiB
Markdown

# Hosts
## Listen and Serve
You can start the server(s) listening to any type of `net.Listener` or even `http.Server` instance.
The method for initialization of the server should be passed at the end, via `Run` function.
The most common method that Go developers use to serve their servers are
by passing a network address with form of "hostname:ip". With Iris
we use the `iris.Addr` which is an `iris.Runner` type
```go
// Listening on tcp with network address 0.0.0.0:8080
// app.Listen(":8080") is just a shortcut of:
app.Run(iris.Addr(":8080"))
```
Sometimes you have created a standard net/http server somewhere else in your app and want to use that to serve the Iris web app
```go
// Same as before but using a custom http.Server which may being used somewhere else too
app.Run(iris.Server(&http.Server{Addr:":8080"}))
```
The most advanced usage is to create a custom or a standard `net.Listener` and pass that to `app.Run`
```go
// Using a custom net.Listener
l, err := net.Listen("tcp4", ":8080")
if err != nil {
panic(err)
}
app.Run(iris.Listener(l))
```
A more complete example, using the unix-only socket files feature
```go
package main
import (
"os"
"net"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
// UNIX socket
if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) {
app.Logger().Fatal(errOs)
}
l, err := net.Listen("unix", socketFile)
if err != nil {
app.Logger().Fatal(err)
}
if err = os.Chmod(socketFile, mode); err != nil {
app.Logger().Fatal(err)
}
app.Run(iris.Listener(l))
}
```
### HTTP/2 and Secure
If you have signed file keys you can use the `iris.TLS` to serve `https` based on those certification keys
```go
// TLS using files
app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key"))
```
The method you should use when your app is ready for **production** is the `iris.AutoTLS` which starts a secure server with automated certifications provided by https://letsencrypt.org for **free**
```go
// Automatic TLS
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))
```
### Any `iris.Runner`
There may be times that you want something very special to listen on, which is not a type of `net.Listener`. You are able to do that by `iris.Raw`, but you're responsible of that method
```go
// Using any func() error,
// the responsibility of starting up a listener is up to you with this way,
// for the sake of simplicity we will use the
// ListenAndServe function of the `net/http` package.
app.Run(iris.Raw(&http.Server{Addr:":8080"}).ListenAndServe)
```
## Host configurators
All the above forms of listening are accepting a last, variadic argument of `func(*iris.Supervisor)`. This is used to add configurators for that specific host you passed via those functions.
For example let's say that we want to add a callback which is fired when
the server is shutdown
```go
app.Run(iris.Addr(":8080", func(h *iris.Supervisor) {
h.RegisterOnShutdown(func() {
println("server terminated")
})
}))
```
You can even do that before `app.Run` method, but the difference is that
these host configurators will be executed to all hosts that you may use to serve your web app (via `app.NewHost` we'll see that in a minute)
```go
app := iris.New()
app.ConfigureHost(func(h *iris.Supervisor) {
h.RegisterOnShutdown(func() {
println("server terminated")
})
})
app.Listen(":8080")
```
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 `app.Run` method,
there are two ways of gain access to the host supervisor, read below.
We have already saw how to configure all application's hosts by second argument of `app.Run` or `app.ConfigureHost`. There is one more way which suits better for simple scenarios and that 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 terminated")
})
app.Run(iris.Raw(h.ListenAndServe))
```
## Multi hosts
You can serve your Iris web app using more than one server, the `iris.Router` is compatible with the `net/http/Handler` function therefore, as you can understand, it can be used to be adapted at any `net/http` server, however there is an easier way, by using the `app.NewHost` which is also copying all the host configurators and it closes all the hosts attached to the particular web app on `app.Shutdown`.
```go
app := iris.New()
app.Get("/", indexHandler)
// run in different goroutine in order to not block the main "goroutine".
go app.Listen(":8080")
// start a second server which is listening on tcp 0.0.0.0:9090,
// without "go" keyword because we want to block at the last server-run.
app.NewHost(&http.Server{Addr:":9090"}).ListenAndServe()
```
## Shutdown (Gracefully)
Let's continue by learning how to catch CONTROL+C/COMMAND+C or unix kill command and shutdown the server gracefully.
> Gracefully Shutdown on CONTROL+C/COMMAND+C or when kill command sent is ENABLED BY-DEFAULT.
In order to manually manage what to do when app is interrupted,
we have to disable the default behavior with the option `WithoutInterruptHandler`
and register a new interrupt handler (globally, across all possible hosts).
Example code:
```go
package main
import (
"context"
"time"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
iris.RegisterOnInterrupt(func() {
timeout := 10 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// close all hosts
app.Shutdown(ctx)
})
app.Get("/", func(ctx iris.Context) {
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
})
app.Listen(":8080", iris.WithoutInterruptHandler)
}
```