mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
Some minor but helpful additions, like CookieOption
. Relative: https://github.com/kataras/iris/issues/1018. Simple cookies example added too. Cookie encoding (side by side with the already session's cookie id encoding) and version upgrade will come tomorrow with a new HISTORY.md entry as well, stay tuned!
Former-commit-id: d14181fac998d32d77690b1b3e42b6c7c72f1ace
This commit is contained in:
parent
f84248cb4e
commit
fcff62d5b4
|
@ -395,6 +395,10 @@ iris cache library lives on its own [package](https://github.com/kataras/iris/tr
|
|||
|
||||
> You're free to use your own favourite caching package if you'd like so.
|
||||
|
||||
### Cookies
|
||||
|
||||
- [Basic](cookies/basic/main.go)
|
||||
|
||||
### Sessions
|
||||
|
||||
iris session manager lives on its own [package](https://github.com/kataras/iris/tree/master/sessions).
|
||||
|
|
|
@ -394,6 +394,10 @@ Iris 独立缓存包 [package](https://github.com/kataras/iris/tree/master/cache
|
|||
|
||||
> 可以随意使用自定义的缓存包。
|
||||
|
||||
### Cookies
|
||||
|
||||
- [Basic](cookies/basic/main.go)
|
||||
|
||||
### Sessions
|
||||
|
||||
Iris session 管理独立包 [package](https://github.com/kataras/iris/tree/master/sessions).
|
||||
|
|
64
_examples/cookies/basic/main.go
Normal file
64
_examples/cookies/basic/main.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris"
|
||||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
|
||||
// Set A Cookie.
|
||||
app.Get("/cookies/{name}/{value}", func(ctx iris.Context) {
|
||||
name := ctx.Params().Get("name")
|
||||
value := ctx.Params().Get("value")
|
||||
|
||||
ctx.SetCookieKV(name, value) // <--
|
||||
// Alternatively: ctx.SetCookie(&http.Cookie{...})
|
||||
//
|
||||
// If you want to set custom the path:
|
||||
// ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored"))
|
||||
//
|
||||
// If you want to be visible only to current request path:
|
||||
// (note that client should be responsible for that if server sent an empty cookie's path, all browsers are compatible)
|
||||
// ctx.SetCookieKV(name, value, iris.CookieCleanPath /* or iris.CookiePath("") */)
|
||||
// More:
|
||||
// iris.CookieExpires(time.Duration)
|
||||
// iris.CookieHTTPOnly(false)
|
||||
|
||||
ctx.Writef("cookie added: %s = %s", name, value)
|
||||
})
|
||||
|
||||
// Retrieve A Cookie.
|
||||
app.Get("/cookies/{name}", func(ctx iris.Context) {
|
||||
name := ctx.Params().Get("name")
|
||||
|
||||
value := ctx.GetCookie(name) // <--
|
||||
// If you want more than the value then:
|
||||
// cookie, err := ctx.Request().Cookie(name)
|
||||
// if err != nil {
|
||||
// handle error.
|
||||
// }
|
||||
|
||||
ctx.WriteString(value)
|
||||
})
|
||||
|
||||
// Delete A Cookie.
|
||||
app.Delete("/cookies/{name}", func(ctx iris.Context) {
|
||||
name := ctx.Params().Get("name")
|
||||
|
||||
ctx.RemoveCookie(name) // <--
|
||||
// If you want to set custom the path:
|
||||
// ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored"))
|
||||
|
||||
ctx.Writef("cookie %s removed", name)
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := newApp()
|
||||
|
||||
// GET: http://localhost:8080/cookies/my_name/my_value
|
||||
// GET: http://localhost:8080/cookies/my_name
|
||||
// DELETE: http://localhost:8080/cookies/my_name
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
32
_examples/cookies/basic/main_test.go
Normal file
32
_examples/cookies/basic/main_test.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
func TestCookiesBasic(t *testing.T) {
|
||||
app := newApp()
|
||||
e := httptest.New(t, app, httptest.URL("http://example.com"))
|
||||
|
||||
cookieName, cookieValue := "my_cookie_name", "my_cookie_value"
|
||||
|
||||
// Test Set A Cookie.
|
||||
t1 := e.GET(fmt.Sprintf("/cookies/%s/%s", cookieName, cookieValue)).Expect().Status(httptest.StatusOK)
|
||||
t1.Cookie(cookieName).Value().Equal(cookieValue) // validate cookie's existence, it should be there now.
|
||||
t1.Body().Contains(cookieValue)
|
||||
|
||||
// Test Retrieve A Cookie.
|
||||
t2 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK)
|
||||
t2.Body().Equal(cookieValue)
|
||||
|
||||
// Test Remove A Cookie.
|
||||
t3 := e.DELETE(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK)
|
||||
t3.Body().Contains(cookieName)
|
||||
|
||||
t4 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK)
|
||||
t4.Cookies().Empty()
|
||||
t4.Body().Empty()
|
||||
}
|
|
@ -854,18 +854,41 @@ type Context interface {
|
|||
// | Cookies |
|
||||
// +------------------------------------------------------------+
|
||||
|
||||
// SetCookie adds a cookie
|
||||
SetCookie(cookie *http.Cookie)
|
||||
// SetCookieKV adds a cookie, receives just a name(string) and a value(string)
|
||||
// SetCookie adds a cookie.
|
||||
// Use of the "options" is not required, they can be used to amend the "cookie".
|
||||
//
|
||||
// If you use this method, it expires at 2 hours
|
||||
// use ctx.SetCookie or http.SetCookie if you want to change more fields.
|
||||
SetCookieKV(name, value string)
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
SetCookie(cookie *http.Cookie, options ...CookieOption)
|
||||
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
||||
//
|
||||
// By default it expires at 2 hours and it's added to the root path,
|
||||
// use the `CookieExpires` and `CookiePath` to modify them.
|
||||
// Alternatively: ctx.SetCookie(&http.Cookie{...})
|
||||
//
|
||||
// If you want to set custom the path:
|
||||
// ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored"))
|
||||
//
|
||||
// If you want to be visible only to current request path:
|
||||
// ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath(""))
|
||||
// More:
|
||||
// iris.CookieExpires(time.Duration)
|
||||
// iris.CookieHTTPOnly(false)
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
SetCookieKV(name, value string, options ...CookieOption)
|
||||
// GetCookie returns cookie's value by it's name
|
||||
// returns empty string if nothing was found.
|
||||
GetCookie(name string) string
|
||||
// RemoveCookie deletes a cookie by it's name.
|
||||
RemoveCookie(name string)
|
||||
//
|
||||
// If you want more than the value then:
|
||||
// cookie, err := ctx.Request().Cookie("name")
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
GetCookie(name string, options ...CookieOption) string
|
||||
// RemoveCookie deletes a cookie by it's name and path = "/".
|
||||
// Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath)
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
RemoveCookie(name string, options ...CookieOption)
|
||||
// VisitAllCookies takes a visitor which loops
|
||||
// on each (request's) cookies' name and value.
|
||||
VisitAllCookies(visitor func(name string, value string))
|
||||
|
@ -1233,7 +1256,7 @@ func (ctx *context) HandlerName() string {
|
|||
// It can be changed to a customized one if needed (very advanced usage).
|
||||
//
|
||||
// See `DefaultNext` for more information about this and why it's exported like this.
|
||||
var Next = DefaultNext ///TODO: add an example for this usecase, i.e describe handlers and skip only file handlers.
|
||||
var Next = DefaultNext
|
||||
|
||||
// DefaultNext is the default function that executed on each middleware if `ctx.Next()`
|
||||
// is called.
|
||||
|
@ -2992,57 +3015,144 @@ func (ctx *context) SendFile(filename string, destinationName string) error {
|
|||
}
|
||||
|
||||
// +------------------------------------------------------------+
|
||||
// | Cookies, Session and Flashes |
|
||||
// | Cookies |
|
||||
// +------------------------------------------------------------+
|
||||
|
||||
// SetCookie adds a cookie
|
||||
func (ctx *context) SetCookie(cookie *http.Cookie) {
|
||||
// CookieOption is the type of function that is accepted on
|
||||
// context's methods like `SetCookieKV`, `RemoveCookie` and `SetCookie`
|
||||
// as their (last) variadic input argument to amend the end cookie's form.
|
||||
//
|
||||
// Any custom or built'n `CookieOption` is valid,
|
||||
// see `CookiePath`, `CookieCleanPath`, `CookieExpires` and `CookieHTTPOnly` for more.
|
||||
type CookieOption func(*http.Cookie)
|
||||
|
||||
// CookiePath is a `CookieOption`.
|
||||
// Use it to change the cookie's Path field.
|
||||
func CookiePath(path string) CookieOption {
|
||||
return func(c *http.Cookie) {
|
||||
c.Path = path
|
||||
}
|
||||
}
|
||||
|
||||
// CookieCleanPath is a `CookieOption`.
|
||||
// Use it to clear the cookie's Path field, exactly the same as `CookiePath("")`.
|
||||
func CookieCleanPath(c *http.Cookie) {
|
||||
c.Path = ""
|
||||
}
|
||||
|
||||
// CookieExpires is a `CookieOption`.
|
||||
// Use it to change the cookie's Expires and MaxAge fields by passing the lifetime of the cookie.
|
||||
func CookieExpires(durFromNow time.Duration) CookieOption {
|
||||
return func(c *http.Cookie) {
|
||||
c.Expires = time.Now().Add(durFromNow)
|
||||
c.MaxAge = int(durFromNow.Seconds())
|
||||
}
|
||||
}
|
||||
|
||||
// CookieHTTPOnly is a `CookieOption`.
|
||||
// Use it to set the cookie's HttpOnly field to false or true.
|
||||
// HttpOnly field defaults to true for `RemoveCookie` and `SetCookieKV`.
|
||||
func CookieHTTPOnly(httpOnly bool) CookieOption {
|
||||
return func(c *http.Cookie) {
|
||||
c.HttpOnly = httpOnly
|
||||
}
|
||||
}
|
||||
|
||||
// SetCookie adds a cookie.
|
||||
// Use of the "options" is not required, they can be used to amend the "cookie".
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
func (ctx *context) SetCookie(cookie *http.Cookie, options ...CookieOption) {
|
||||
for _, opt := range options {
|
||||
opt(cookie)
|
||||
}
|
||||
|
||||
http.SetCookie(ctx.writer, cookie)
|
||||
}
|
||||
|
||||
var (
|
||||
// SetCookieKVExpiration is 2 hours by-default
|
||||
// you can change it or simple, use the SetCookie for more control.
|
||||
SetCookieKVExpiration = time.Duration(120) * time.Minute
|
||||
)
|
||||
|
||||
// SetCookieKV adds a cookie, receives just a name(string) and a value(string)
|
||||
// SetCookieKV adds a cookie, requires the name(string) and the value(string).
|
||||
//
|
||||
// If you use this method, it expires at 2 hours
|
||||
// use ctx.SetCookie or http.SetCookie if you want to change more fields.
|
||||
func (ctx *context) SetCookieKV(name, value string) {
|
||||
// By default it expires at 2 hours and it's added to the root path,
|
||||
// use the `CookieExpires` and `CookiePath` to modify them.
|
||||
// Alternatively: ctx.SetCookie(&http.Cookie{...})
|
||||
//
|
||||
// If you want to set custom the path:
|
||||
// ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored"))
|
||||
//
|
||||
// If you want to be visible only to current request path:
|
||||
// (note that client should be responsible for that if server sent an empty cookie's path, all browsers are compatible)
|
||||
// ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath(""))
|
||||
// More:
|
||||
// iris.CookieExpires(time.Duration)
|
||||
// iris.CookieHTTPOnly(false)
|
||||
//
|
||||
// Examples: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
func (ctx *context) SetCookieKV(name, value string, options ...CookieOption) {
|
||||
c := &http.Cookie{}
|
||||
c.Path = "/"
|
||||
c.Name = name
|
||||
c.Value = url.QueryEscape(value)
|
||||
c.HttpOnly = true
|
||||
c.Expires = time.Now().Add(SetCookieKVExpiration)
|
||||
c.MaxAge = int(SetCookieKVExpiration.Seconds())
|
||||
ctx.SetCookie(c)
|
||||
ctx.SetCookie(c, options...)
|
||||
}
|
||||
|
||||
// GetCookie returns cookie's value by it's name
|
||||
// returns empty string if nothing was found.
|
||||
func (ctx *context) GetCookie(name string) string {
|
||||
//
|
||||
// If you want more than the value then:
|
||||
// cookie, err := ctx.Request().Cookie("name")
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
func (ctx *context) GetCookie(name string, options ...CookieOption) string {
|
||||
cookie, err := ctx.request.Cookie(name)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Q: Why named as `CookieOption` and not like `CookieInterceptor`?
|
||||
// A: Because an interceptor would be able to modify the cookie AND stop the 'x' operation, but we don't want to cancel anything.
|
||||
//
|
||||
// Q: Why "Cookie Options" here?
|
||||
// A: Because of the future suport of cookie encoding like I did with sessions.
|
||||
// Two impl ideas:
|
||||
// - Do it so each caller of `GetCookie/SetCookieKV/SetCookie` can have each own encoding or share one, no limit.
|
||||
// - Do it so every of the above three methods will use the same encoding, therefore to the Application's level, limit per Iris app.
|
||||
// We'll see...
|
||||
//
|
||||
// Finally, I should not forget to add links for the new translated READMEs(2) and push a new version with the minor changes so far,
|
||||
// API is stable, so relax and do it on the next commit tomorrow, need sleep.
|
||||
for _, opt := range options {
|
||||
opt(cookie)
|
||||
}
|
||||
|
||||
value, _ := url.QueryUnescape(cookie.Value)
|
||||
return value
|
||||
}
|
||||
|
||||
// RemoveCookie deletes a cookie by it's name.
|
||||
func (ctx *context) RemoveCookie(name string) {
|
||||
// SetCookieKVExpiration is 2 hours by-default
|
||||
// you can change it or simple, use the SetCookie for more control.
|
||||
//
|
||||
// See `SetCookieKVExpiration` and `CookieExpires` for more.
|
||||
var SetCookieKVExpiration = time.Duration(120) * time.Minute
|
||||
|
||||
// RemoveCookie deletes a cookie by it's name and path = "/".
|
||||
// Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath)
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
|
||||
func (ctx *context) RemoveCookie(name string, options ...CookieOption) {
|
||||
c := &http.Cookie{}
|
||||
c.Name = name
|
||||
c.Value = ""
|
||||
c.Path = "/"
|
||||
c.Path = "/" // if user wants to change it, use of the CookieOption `CookiePath` is required if not `ctx.SetCookie`.
|
||||
c.HttpOnly = true
|
||||
// RFC says 1 second, but let's do it 1 minute to make sure is working
|
||||
// RFC says 1 second, but let's do it 1 to make sure is working
|
||||
exp := time.Now().Add(-time.Duration(1) * time.Minute)
|
||||
c.Expires = exp
|
||||
c.MaxAge = -1
|
||||
ctx.SetCookie(c)
|
||||
ctx.SetCookie(c, options...)
|
||||
// delete request's cookie also, which is temporary available.
|
||||
ctx.request.Header.Set("Cookie", "")
|
||||
}
|
||||
|
|
10
go19.go
10
go19.go
|
@ -71,4 +71,14 @@ type (
|
|||
//
|
||||
// See `ExecutionRules` and `core/router/Party#SetExecutionRules` for more.
|
||||
ExecutionOptions = router.ExecutionOptions
|
||||
|
||||
// CookieOption is the type of function that is accepted on
|
||||
// context's methods like `SetCookieKV`, `RemoveCookie` and `SetCookie`
|
||||
// as their (last) variadic input argument to amend the end cookie's form.
|
||||
//
|
||||
// Any custom or built'n `CookieOption` is valid,
|
||||
// see `CookiePath`, `CookieCleanPath`, `CookieExpires` and `CookieHTTPOnly` for more.
|
||||
//
|
||||
// An alias for the `context/Context#CookieOption`.
|
||||
CookieOption = context.CookieOption
|
||||
)
|
||||
|
|
|
@ -87,6 +87,7 @@ func New(t *testing.T, app *iris.Application, setters ...OptionSetter) *httpexpe
|
|||
// set the logger or disable it (default) and disable the updater (for any case).
|
||||
app.Configure(iris.WithoutVersionChecker)
|
||||
app.Logger().SetLevel(conf.LogLevel)
|
||||
|
||||
if err := app.Build(); err != nil {
|
||||
if conf.Debug && (conf.LogLevel == "disable" || conf.LogLevel == "disabled") {
|
||||
app.Logger().Println(err.Error())
|
||||
|
|
22
iris.go
22
iris.go
|
@ -422,6 +422,28 @@ var (
|
|||
//
|
||||
// A shortcut of the `cache#Cache304`.
|
||||
Cache304 = cache.Cache304
|
||||
|
||||
// CookiePath is a `CookieOption`.
|
||||
// Use it to change the cookie's Path field.
|
||||
//
|
||||
// A shortcut for the `context#CookiePath`.
|
||||
CookiePath = context.CookiePath
|
||||
// CookieCleanPath is a `CookieOption`.
|
||||
// Use it to clear the cookie's Path field, exactly the same as `CookiePath("")`.
|
||||
//
|
||||
// A shortcut for the `context#CookieCleanPath`.
|
||||
CookieCleanPath = context.CookieCleanPath
|
||||
// CookieExpires is a `CookieOption`.
|
||||
// Use it to change the cookie's Expires and MaxAge fields by passing the lifetime of the cookie.
|
||||
//
|
||||
// A shortcut for the `context#CookieExpires`.
|
||||
CookieExpires = context.CookieExpires
|
||||
// CookieHTTPOnly is a `CookieOption`.
|
||||
// Use it to set the cookie's HttpOnly field to false or true.
|
||||
// HttpOnly field defaults to true for `RemoveCookie` and `SetCookieKV`.
|
||||
//
|
||||
// A shortcut for the `context#CookieHTTPOnly`.
|
||||
CookieHTTPOnly = context.CookieHTTPOnly
|
||||
)
|
||||
|
||||
// SPA accepts an "assetHandler" which can be the result of an
|
||||
|
|
Loading…
Reference in New Issue
Block a user