mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
add Host and Cookies sections
parent
1437e66bd3
commit
2c3673bbe0
135
Cookies.md
Normal file
135
Cookies.md
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
Cookies are accessible through the Request instance of Context. The `ctx.Request()` returns a `net/http#Request`.
|
||||||
|
|
||||||
|
However the Iris `Context` provides some helpers to make the most common use cases of cookies easier accessible to you and without any custom additional code of yours that would be required if you just using the Request's Cookies methods.
|
||||||
|
|
||||||
|
## Set a Cookie
|
||||||
|
|
||||||
|
The `SetCookie` method adds a cookie.
|
||||||
|
|
||||||
|
Use of the "options" is not required, they can be used to modify the "cookie". You'll see later on what the available options are, custom ones can be added depending on your web application requirements, this also helps to not repeat yourself in a codebase.
|
||||||
|
|
||||||
|
```go
|
||||||
|
SetCookie(cookie *http.Cookie, options ...CookieOption)
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want you can also use the `SetCookieKV` method which does not require an import of the `net/http` package.
|
||||||
|
|
||||||
|
```go
|
||||||
|
SetCookieKV(name, value string, options ...CookieOption)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the default expiration for a cookie set by `SetCookieKV` is 365 days. You can either use the `CookieExpires` Cookie Option(see below) or globally by setting the `kataras/iris/Context.SetCookieKVExpiration` package-level variable.
|
||||||
|
|
||||||
|
The `CookieOption` is just a type for `func(*http.Cookie)`.
|
||||||
|
|
||||||
|
**Set Path**
|
||||||
|
|
||||||
|
```go
|
||||||
|
CookiePath(path string) CookieOption
|
||||||
|
```
|
||||||
|
|
||||||
|
**Set Expiration**
|
||||||
|
|
||||||
|
```go
|
||||||
|
iris.CookieExpires(durFromNow time.Duration) CookieOption
|
||||||
|
```
|
||||||
|
|
||||||
|
**HttpOnly**
|
||||||
|
|
||||||
|
```go
|
||||||
|
iris.CookieHTTPOnly(httpOnly bool) CookieOption
|
||||||
|
```
|
||||||
|
|
||||||
|
> HttpOnly field defaults to true for `RemoveCookie` and `SetCookieKV`.
|
||||||
|
|
||||||
|
|
||||||
|
And let's go a bit further with cookie encoding.
|
||||||
|
|
||||||
|
**Encode**
|
||||||
|
|
||||||
|
Provides encoding functionality when adding a cookie.
|
||||||
|
|
||||||
|
Accepts a `CookieEncoder` and sets the cookie's value to the encoded value.
|
||||||
|
|
||||||
|
Users of that is the `SetCookie` and `SetCookieKV`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
iris.CookieEncode(encode CookieEncoder) CookieOption
|
||||||
|
```
|
||||||
|
|
||||||
|
**Decode**
|
||||||
|
|
||||||
|
Provides decoding functionality when retrieving a cookie.
|
||||||
|
|
||||||
|
Accepts a `CookieDecoder` and sets the cookie's value to the decoded value before return by the `GetCookie`.
|
||||||
|
|
||||||
|
User of that is the `GetCookie`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
iris.CookieDecode(decode CookieDecoder) CookieOption
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `CookieEncoder` can be described as:
|
||||||
|
|
||||||
|
A CookieEncoder should encode the cookie value.
|
||||||
|
|
||||||
|
* Should accept the cookie's name as its first argument and
|
||||||
|
* as second argument the cookie value ptr.
|
||||||
|
* Should return an encoded value or an empty one if encode operation failed.
|
||||||
|
* Should return an error if encode operation failed.
|
||||||
|
|
||||||
|
```go
|
||||||
|
CookieEncoder func(cookieName string, value interface{}) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
And `CookieDecoder`:
|
||||||
|
|
||||||
|
CookieDecoder should decode the cookie value.
|
||||||
|
|
||||||
|
* Should accept the cookie's name as its first argument,
|
||||||
|
* as second argument the encoded cookie value and as third argument the decoded value ptr.
|
||||||
|
* Should return a decoded value or an empty one if decode operation failed.
|
||||||
|
* Should return an error if decode operation failed.
|
||||||
|
|
||||||
|
```go
|
||||||
|
CookieDecoder func(cookieName string, cookieValue string, v interface{}) error
|
||||||
|
```
|
||||||
|
|
||||||
|
Errors are not printed, so you have to know what you're doing,
|
||||||
|
and remember: if you use AES it only supports key sizes of 16, 24 or 32 bytes.
|
||||||
|
|
||||||
|
You either need to provide exactly that amount or you derive the key from what you type in.
|
||||||
|
|
||||||
|
## Get a Cookie
|
||||||
|
|
||||||
|
The `GetCookie` returns cookie's value by its name, returns empty string if nothing was found.
|
||||||
|
|
||||||
|
```go
|
||||||
|
GetCookie(name string, options ...CookieOption) string
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want more than the value then use the following instead:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cookie, err := ctx.Request().Cookie("name")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get all Cookies
|
||||||
|
|
||||||
|
The `ctx.Request().Cookies()` method returns a slice of all the available request cookies. Sometimes you want to modify them or perform an action on each one of them, the easiet way to do that is by the `VisitAllCookies` method.
|
||||||
|
|
||||||
|
```go
|
||||||
|
VisitAllCookies(visitor func(name string, value string))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Remove a Cookie
|
||||||
|
|
||||||
|
The `RemoveCookie` method deletes a cookie by its name and path = "/", the root one.
|
||||||
|
|
||||||
|
Tip: change the cookie's path to the current one by providing the `iris.CookieCleanPath` Cookie Options, as : `RemoveCookie("nname", iris.CookieCleanPath)`.
|
||||||
|
|
||||||
|
Also, note that the default behavior is to set its `HttpOnly` to true. It performs a removal of cookie based on the web standards.
|
||||||
|
|
||||||
|
```go
|
||||||
|
RemoveCookie(name string, options ...CookieOption)
|
||||||
|
```
|
2
Home.md
2
Home.md
|
@ -8,6 +8,7 @@ This wiki is the main source of documentation for **developers** working with (o
|
||||||
* [[Support]]
|
* [[Support]]
|
||||||
* [[Installing Iris|Installation]]
|
* [[Installing Iris|Installation]]
|
||||||
* [[Getting Started]]
|
* [[Getting Started]]
|
||||||
|
* [[Host]]
|
||||||
* [[Routing]]
|
* [[Routing]]
|
||||||
* [[Path Parameter Types|Routing-path-parameter-types]]
|
* [[Path Parameter Types|Routing-path-parameter-types]]
|
||||||
* [[Reverse Lookups|Routing-reverse-lookups]]
|
* [[Reverse Lookups|Routing-reverse-lookups]]
|
||||||
|
@ -15,6 +16,7 @@ This wiki is the main source of documentation for **developers** working with (o
|
||||||
* [[Handle HTTP errors|Routing-error-handlers]]
|
* [[Handle HTTP errors|Routing-error-handlers]]
|
||||||
* [[Wrap the Router|Routing-wrap-the-router]]
|
* [[Wrap the Router|Routing-wrap-the-router]]
|
||||||
* [[Dependency Injection|Routing-dependency-injection]]
|
* [[Dependency Injection|Routing-dependency-injection]]
|
||||||
|
* [[Cookies]]
|
||||||
|
|
||||||
## Runnable Examples
|
## Runnable Examples
|
||||||
|
|
||||||
|
|
249
Host.md
Normal file
249
Host.md
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
## 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 are 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.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"
|
||||||
|
)
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
UNIX and BSD hosts can take advandage of the reuse port feature
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
// Package tcplisten provides customizable TCP net.Listener with various
|
||||||
|
// performance-related options:
|
||||||
|
//
|
||||||
|
// - SO_REUSEPORT. This option allows linear scaling server performance
|
||||||
|
// on multi-CPU servers.
|
||||||
|
// See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
|
||||||
|
//
|
||||||
|
// - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
|
||||||
|
// connection before writing to them.
|
||||||
|
//
|
||||||
|
// - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
|
||||||
|
"github.com/valyala/tcplisten"
|
||||||
|
|
||||||
|
"github.com/kataras/iris"
|
||||||
|
)
|
||||||
|
|
||||||
|
// go get github.com/valyala/tcplisten
|
||||||
|
// go run main.go
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
|
||||||
|
app.Get("/", func(ctx iris.Context) {
|
||||||
|
ctx.HTML("<h1>Hello World!</h1>")
|
||||||
|
})
|
||||||
|
|
||||||
|
listenerCfg := tcplisten.Config{
|
||||||
|
ReusePort: true,
|
||||||
|
DeferAccept: true,
|
||||||
|
FastOpen: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := listenerCfg.NewListener("tcp", ":8080")
|
||||||
|
if 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.Run(iris.Addr(":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.Run(iris.Addr(":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"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
|
||||||
|
iris.RegisterOnInterrupt(func() {
|
||||||
|
timeout := 5 * 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.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
|
||||||
|
}
|
||||||
|
```
|
|
@ -3,6 +3,7 @@
|
||||||
* [[Support]]
|
* [[Support]]
|
||||||
* [[Installing Iris|Installation]]
|
* [[Installing Iris|Installation]]
|
||||||
* [[Getting Started]]
|
* [[Getting Started]]
|
||||||
|
* [[Host]]
|
||||||
* [[Routing]]
|
* [[Routing]]
|
||||||
* [[Path Parameter Types|Routing-path-parameter-types]]
|
* [[Path Parameter Types|Routing-path-parameter-types]]
|
||||||
* [[Reverse Lookups|Routing-reverse-lookups]]
|
* [[Reverse Lookups|Routing-reverse-lookups]]
|
||||||
|
@ -10,3 +11,4 @@
|
||||||
* [[Custom error handlers|Routing-error-handlers]]
|
* [[Custom error handlers|Routing-error-handlers]]
|
||||||
* [[Wrap the Router|Routing-wrap-the-router]]
|
* [[Wrap the Router|Routing-wrap-the-router]]
|
||||||
* [[Dependency Injection|Routing-dependency-injection]]
|
* [[Dependency Injection|Routing-dependency-injection]]
|
||||||
|
* [[Cookies]]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user