minor version 11.2.2 - register sessions as middleware and Context.HTML/Text like Context.Writef

Former-commit-id: 6f5f1c502fb06d739c350c3ecc891f495dc03a6e
This commit is contained in:
Gerasimos (Makis) Maropoulos 2019-07-24 19:51:42 +03:00
parent 275cc14e39
commit 29bf846bd1
10 changed files with 95 additions and 39 deletions

View File

@ -308,7 +308,7 @@ iris cache library lives on its own [package](https://github.com/kataras/iris/tr
iris session manager lives on its own [package](https://github.com/kataras/iris/tree/master/sessions). iris session manager lives on its own [package](https://github.com/kataras/iris/tree/master/sessions).
- [Overview](sessions/overview/main.go) - [Overview](sessions/overview/main.go)
- [Standalone](sessions/standalone/main.go) - [Middleware](sessions/middleware/main.go)
- [Secure Cookie](sessions/securecookie/main.go) - [Secure Cookie](sessions/securecookie/main.go)
- [Flash Messages](sessions/flash-messages/main.go) - [Flash Messages](sessions/flash-messages/main.go)
- [Databases](sessions/database) - [Databases](sessions/database)

View File

@ -416,7 +416,7 @@ Iris 独立缓存包 [package](https://github.com/kataras/iris/tree/master/cache
Iris session 管理独立包 [package](https://github.com/kataras/iris/tree/master/sessions). Iris session 管理独立包 [package](https://github.com/kataras/iris/tree/master/sessions).
- [概览](sessions/overview/main.go) - [概览](sessions/overview/main.go)
- [独立使用](sessions/standalone/main.go) - [中间件](sessions/middleware/main.go)
- [安全cookie](sessions/securecookie/main.go) - [安全cookie](sessions/securecookie/main.go)
- [临时消息](sessions/flash-messages/main.go) - [临时消息](sessions/flash-messages/main.go)
- [数据库](sessions/database) - [数据库](sessions/database)

View File

@ -37,11 +37,11 @@ func (ctx *MyContext) Next() {
// Override any context's method you want... // Override any context's method you want...
// [...] // [...]
func (ctx *MyContext) HTML(htmlContents string) (int, error) { func (ctx *MyContext) HTML(format string, args ...interface{}) (int, error) {
ctx.Application().Logger().Infof("Executing .HTML function from MyContext") ctx.Application().Logger().Infof("Executing .HTML function from MyContext")
ctx.ContentType("text/html") ctx.ContentType("text/html")
return ctx.WriteString(htmlContents) return ctx.Writef(format, args...)
} }
func main() { func main() {

View File

@ -28,6 +28,12 @@ func main() {
}) })
app.Get("/execute", func(ctx iris.Context) { app.Get("/execute", func(ctx iris.Context) {
if !none.IsOnline() {
ctx.Values().Set("from", "/execute with offline access")
ctx.Exec("NONE", "/invisible/iris")
return
}
// same as navigating to "http://localhost:8080/invisible/iris" when /change has being invoked and route state changed // same as navigating to "http://localhost:8080/invisible/iris" when /change has being invoked and route state changed
// from "offline" to "online" // from "offline" to "online"
ctx.Values().Set("from", "/execute") // values and session can be shared when calling Exec from a "foreign" context. ctx.Values().Set("from", "/execute") // values and session can be shared when calling Exec from a "foreign" context.

View File

@ -26,26 +26,33 @@ func main() {
// if you want to invalid cookies on different subdomains // if you want to invalid cookies on different subdomains
// of the same host, then enable it. // of the same host, then enable it.
// Defaults to false. // Defaults to false.
DisableSubdomainPersistence: true, DisableSubdomainPersistence: false,
// AllowReclaim will allow to
// Destroy and Start a session in the same request handler.
// All it does is that it removes the cookie for both `Request` and `ResponseWriter` while `Destroy`
// or add a new cookie to `Request` while `Start`.
//
// Defaults to false.
AllowReclaim: true,
}) })
app.Use(sess.Handler()) // session is always non-nil inside handlers now.
app.Get("/", func(ctx iris.Context) { app.Get("/", func(ctx iris.Context) {
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") session := sessions.Get(ctx) // same as sess.Start(ctx, cookieOptions...)
if session.Len() == 0 {
ctx.HTML(`no session values stored yet. Navigate to: <a href="/set">set page</a>`)
return
}
ctx.HTML("<ul>")
session.Visit(func(key string, value interface{}) {
ctx.HTML("<li> %s = %v </li>", key, value)
})
ctx.HTML("</ul>")
}) })
//set session values.
app.Get("/set", func(ctx iris.Context) { app.Get("/set", func(ctx iris.Context) {
//set session values. session := sessions.Get(ctx)
s := sess.Start(ctx) session.Set("name", "iris")
s.Set("name", "iris")
//test if set here. //test if set here.
ctx.Writef("All ok session set to: %s", s.GetString("name")) ctx.Writef("All ok session set to: %s", session.GetString("name"))
// Set will set the value as-it-is, // Set will set the value as-it-is,
// if it's a slice or map // if it's a slice or map
@ -56,22 +63,32 @@ func main() {
// Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081
}) })
app.Get("/set/{key}/{value}", func(ctx iris.Context) {
key, value := ctx.Params().Get("key"), ctx.Params().Get("value")
session := sessions.Get(ctx)
session.Set(key, value)
// test if set here
ctx.Writef("All ok session value of the '%s' is: %s", key, session.GetString(key))
})
app.Get("/get", func(ctx iris.Context) { app.Get("/get", func(ctx iris.Context) {
// get a specific value, as string, // get a specific value, as string,
// if not found then it returns just an empty string. // if not found then it returns just an empty string.
name := sess.Start(ctx).GetString("name") name := sessions.Get(ctx).GetString("name")
ctx.Writef("The name on the /set was: %s", name) ctx.Writef("The name on the /set was: %s", name)
}) })
app.Get("/delete", func(ctx iris.Context) { app.Get("/delete", func(ctx iris.Context) {
// delete a specific key // delete a specific key
sess.Start(ctx).Delete("name") sessions.Get(ctx).Delete("name")
}) })
app.Get("/clear", func(ctx iris.Context) { app.Get("/clear", func(ctx iris.Context) {
// removes all entries. // removes all entries.
sess.Start(ctx).Clear() sessions.Get(ctx).Clear()
}) })
app.Get("/update", func(ctx iris.Context) { app.Get("/update", func(ctx iris.Context) {
@ -81,13 +98,15 @@ func main() {
app.Get("/destroy", func(ctx iris.Context) { app.Get("/destroy", func(ctx iris.Context) {
//destroy, removes the entire session data and cookie //destroy, removes the entire session data and cookie
sess.Destroy(ctx) // sess.Destroy(ctx)
// or
sessions.Get(ctx).Destroy()
}) })
// Note about Destroy: // Note about Destroy:
// //
// You can destroy a session outside of a handler too, using the: // You can destroy a session outside of a handler too, using the:
// mySessions.DestroyByID // sess.DestroyByID
// mySessions.DestroyAll // sess.DestroyAll
// remember: slices and maps are muttable by-design // remember: slices and maps are muttable by-design
// The `SetImmutable` makes sure that they will be stored and received // The `SetImmutable` makes sure that they will be stored and received
@ -97,9 +116,9 @@ func main() {
// Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081
app.Get("/set_immutable", func(ctx iris.Context) { app.Get("/set_immutable", func(ctx iris.Context) {
business := []businessModel{{Name: "Edward"}, {Name: "value 2"}} business := []businessModel{{Name: "Edward"}, {Name: "value 2"}}
s := sess.Start(ctx) session := sessions.Get(ctx)
s.SetImmutable("businessEdit", business) session.SetImmutable("businessEdit", business)
businessGet := s.Get("businessEdit").([]businessModel) businessGet := session.Get("businessEdit").([]businessModel)
// try to change it, if we used `Set` instead of `SetImmutable` this // try to change it, if we used `Set` instead of `SetImmutable` this
// change will affect the underline array of the session's value "businessEdit", but now it will not. // change will affect the underline array of the session's value "businessEdit", but now it will not.
@ -108,7 +127,7 @@ func main() {
}) })
app.Get("/get_immutable", func(ctx iris.Context) { app.Get("/get_immutable", func(ctx iris.Context) {
valSlice := sess.Start(ctx).Get("businessEdit") valSlice := sessions.Get(ctx).Get("businessEdit")
if valSlice == nil { if valSlice == nil {
ctx.HTML("please navigate to the <a href='/set_immutable'>/set_immutable</a> first") ctx.HTML("please navigate to the <a href='/set_immutable'>/set_immutable</a> first")
return return

View File

@ -768,9 +768,9 @@ type Context interface {
// Binary writes out the raw bytes as binary data. // Binary writes out the raw bytes as binary data.
Binary(data []byte) (int, error) Binary(data []byte) (int, error)
// Text writes out a string as plain text. // Text writes out a string as plain text.
Text(text string) (int, error) Text(format string, args ...interface{}) (int, error)
// HTML writes out a string as text/html. // HTML writes out a string as text/html.
HTML(htmlContents string) (int, error) HTML(format string, args ...interface{}) (int, error)
// JSON marshals the given interface object and writes the JSON response. // JSON marshals the given interface object and writes the JSON response.
JSON(v interface{}, options ...JSON) (int, error) JSON(v interface{}, options ...JSON) (int, error)
// JSONP marshals the given interface object and writes the JSON response. // JSONP marshals the given interface object and writes the JSON response.
@ -2876,15 +2876,15 @@ func (ctx *context) Binary(data []byte) (int, error) {
} }
// Text writes out a string as plain text. // Text writes out a string as plain text.
func (ctx *context) Text(text string) (int, error) { func (ctx *context) Text(format string, args ...interface{}) (int, error) {
ctx.ContentType(ContentTextHeaderValue) ctx.ContentType(ContentTextHeaderValue)
return ctx.writer.WriteString(text) return ctx.Writef(format, args...)
} }
// HTML writes out a string as text/html. // HTML writes out a string as text/html.
func (ctx *context) HTML(htmlContents string) (int, error) { func (ctx *context) HTML(format string, args ...interface{}) (int, error) {
ctx.ContentType(ContentHTMLHeaderValue) ctx.ContentType(ContentHTMLHeaderValue)
return ctx.writer.WriteString(htmlContents) return ctx.Writef(format, args...)
} }
// JSON contains the options for the JSON (Context's) Renderer. // JSON contains the options for the JSON (Context's) Renderer.

4
doc.go
View File

@ -38,13 +38,13 @@ Source code and other details for the project are available at GitHub:
Current Version Current Version
11.2.1 11.2.2
Installation Installation
The only requirement is the Go Programming Language, at least version 1.12. The only requirement is the Go Programming Language, at least version 1.12.
$ go get github.com/kataras/iris@v11.2.1 $ go get github.com/kataras/iris@v11.2.2
Wiki: Wiki:

View File

@ -37,7 +37,7 @@ import (
var ( var (
// Version is the current version number of the Iris Web Framework. // Version is the current version number of the Iris Web Framework.
Version = "11.2.1" Version = "11.2.2"
) )
// HTTP status codes as registered with IANA. // HTTP status codes as registered with IANA.

View File

@ -411,6 +411,11 @@ func (s *Session) Visit(cb func(k string, v interface{})) {
s.provider.db.Visit(s.sid, cb) s.provider.db.Visit(s.sid, cb)
} }
// Len returns the total number of stored values in this session.
func (s *Session) Len() int {
return s.provider.db.Len(s.sid)
}
func (s *Session) set(key string, value interface{}, immutable bool) { func (s *Session) set(key string, value interface{}, immutable bool) {
s.provider.db.Set(s.sid, s.Lifetime, key, value, immutable) s.provider.db.Set(s.sid, s.Lifetime, key, value, immutable)

View File

@ -77,7 +77,7 @@ func (s *Sessions) updateCookie(ctx context.Context, sid string, expires time.Du
func (s *Sessions) Start(ctx context.Context, cookieOptions ...context.CookieOption) *Session { func (s *Sessions) Start(ctx context.Context, cookieOptions ...context.CookieOption) *Session {
cookieValue := s.decodeCookieValue(GetCookie(ctx, s.config.Cookie)) cookieValue := s.decodeCookieValue(GetCookie(ctx, s.config.Cookie))
if cookieValue == "" { // cookie doesn't exists, let's generate a session and add set a cookie if cookieValue == "" { // cookie doesn't exist, let's generate a session and set a cookie.
sid := s.config.SessionIDGenerator(ctx) sid := s.config.SessionIDGenerator(ctx)
sess := s.provider.Init(sid, s.config.Expires) sess := s.provider.Init(sid, s.config.Expires)
@ -88,9 +88,35 @@ func (s *Sessions) Start(ctx context.Context, cookieOptions ...context.CookieOpt
return sess return sess
} }
sess := s.provider.Read(cookieValue, s.config.Expires) return s.provider.Read(cookieValue, s.config.Expires)
}
return sess const contextSessionKey = "_iris_session"
// Handler returns a sessions middleware to register on application routes.
func (s *Sessions) Handler(cookieOptions ...context.CookieOption) context.Handler {
return func(ctx context.Context) {
session := s.Start(ctx, cookieOptions...)
ctx.Values().Set(contextSessionKey, session)
ctx.Next()
}
}
// Get returns a *Session from the same request life cycle,
// can be used inside a chain of handlers of a route.
//
// The `Sessions.Start` should be called previously,
// e.g. register the `Sessions.Handler` as middleware.
// Then call `Get` package-level function as many times as you want.
// The `Sessions.Start` can be called more than one time in the same request life cycle as well.
func Get(ctx context.Context) *Session {
if v := ctx.Values().Get(contextSessionKey); v != nil {
if sess, ok := v.(*Session); ok {
return sess
}
}
return nil
} }
// StartWithPath same as `Start` but it explicitly accepts the cookie path option. // StartWithPath same as `Start` but it explicitly accepts the cookie path option.