Iris 4.0.0-alpha.4. Book is finally updated https://kataras.gitbooks.io/iris/content/ also

This commit is contained in:
Gerasimos Maropoulos 2016-07-20 06:33:24 +03:00
parent 566a194836
commit 7ed5ed4519
9 changed files with 86 additions and 47 deletions

View File

@ -2,6 +2,25 @@
**How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
## 4.0.0-alpha.4 -> 4.0.0-alpha.4
** The important** , is that the [book](https://kataras.gitbooks.io/iris/content/) is finally updated!
If you're **willing to donate** click [here](DONATIONS.md)!
- `iris.Config.Gzip`, enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content. If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true}). It defaults to false
**Fix**
- https://github.com/kataras/iris/issues/301
**Sessions changes **
- `iris.Config.Sessions.Expires` it was time.Time, changed to time.Duration, which defaults to 0, means unlimited session life duration, if you change it then the correct date is setted on client's cookie but also server destroys the session automatically when the duration passed, this is better approach, see [here](https://github.com/kataras/iris/issues/301)
## 4.0.0-alpha.2 -> 4.0.0-alpha.3
**New**
@ -21,7 +40,6 @@ A **Response Engine** gives you the freedom to create/change the render/response
**Fix**
- https://github.com/kataras/iris/issues/294
- https://github.com/kataras/iris/issues/301
- https://github.com/kataras/iris/issues/303
@ -29,7 +47,7 @@ A **Response Engine** gives you the freedom to create/change the render/response
- `iris.Config.Charset`, before alpha.3 was `iris.Config.Rest.Charset` & `iris.Config.Render.Template.Charset`, but you can override it at runtime by passinth a map `iris.RenderOptions` on the `context.Render` call .
- `iris.Config.IsDevelopment`, before alpha.1 was `iris.Config.Render.Template.IsDevelopment`
- `iris.Config.Gzip`, enables gzip compression on your Render actions, this includes any type of render, templates and pure/raw content. If you don't want to enable it globaly, you could just use the third parameter on context.Render("myfileOrResponse", structBinding{}, iris.RenderOptions{"gzip": true}). It defaults to false
**Websockets changes**

View File

@ -141,7 +141,7 @@ I recommend writing your API tests using this new library, [httpexpect](https://
Versioning
------------
Current: **v4.0.0-alpha.3**
Current: **v4.0.0-alpha.4**
> Iris is an active project
@ -186,7 +186,7 @@ License can be found [here](LICENSE).
[Travis]: http://travis-ci.org/kataras/iris
[License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square
[License]: https://github.com/kataras/iris/blob/master/LICENSE
[Release Widget]: https://img.shields.io/badge/release-v4.0.0--alpha.3-blue.svg?style=flat-square
[Release Widget]: https://img.shields.io/badge/release-v4.0.0--alpha.4-blue.svg?style=flat-square
[Release]: https://github.com/kataras/iris/releases
[Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
[Chat]: https://kataras.rocket.chat/channel/iris

View File

@ -13,17 +13,6 @@ const (
type (
// Iris configs for the station
// All fields can be changed before server's listen except the DisablePathCorrection field
//
// MaxRequestBodySize is the only options that can be changed after server listen -
// using Config.MaxRequestBodySize = ...
// Render's rest config can be changed after declaration but before server's listen -
// using Config.Render.Rest...
// Render's Template config can be changed after declaration but before server's listen -
// using Config.Render.Template...
// Sessions config can be changed after declaration but before server's listen -
// using Config.Sessions...
// and so on...
Iris struct {
// DisablePathCorrection corrects and redirects the requested path to the registed path
@ -106,6 +95,7 @@ type (
Websocket *Websocket
// Tester contains the configs for the test framework, so far we have only one because all test framework's configs are setted by the iris itself
// You can find example on the https://github.com/kataras/iris/glob/master/context_test.go
Tester Tester
}
)

View File

@ -9,8 +9,8 @@ import (
"github.com/valyala/fasthttp"
)
// Default values for base Server conf, can be changed for global use
var (
// Default values for base Server conf
const (
// DefaultServerHostname returns the default hostname which is 127.0.0.1
DefaultServerHostname = "127.0.0.1"
// DefaultServerPort returns the default port which is 8080
@ -31,6 +31,9 @@ var (
//
// Default buffer size is 8MB
DefaultWriteBufferSize = 8096
// DefaultServerName the response header of the 'Server' value when writes to the client
DefaultServerName = "iris"
)
var (
@ -38,9 +41,6 @@ var (
DefaultServerAddr = DefaultServerHostname + ":" + strconv.Itoa(DefaultServerPort)
)
// ServerName the response header of the 'Server' value when writes to the client
const ServerName = "iris"
// Server used inside server for listening
type Server struct {
// ListenningAddr the addr that server listens to
@ -79,6 +79,9 @@ type Server struct {
RedirectTo string
// Virtual If this server is not really listens to a real host, it mostly used in order to achieve testing without system modifications
Virtual bool
// Name the server's name, defaults to "iris".
// You're free to change it, but I will trust you to don't, this is the only setting whose somebody, like me, can see if iris web framework is used
Name string
}
// ServerParseAddr parses the listening addr and returns this
@ -114,7 +117,7 @@ func ServerParseAddr(listeningAddr string) string {
// DefaultServer returns the default configs for the server
func DefaultServer() Server {
return Server{ListeningAddr: DefaultServerAddr,
return Server{ListeningAddr: DefaultServerAddr, Name: DefaultServerName,
MaxRequestBodySize: DefaultMaxRequestBodySize,
ReadBufferSize: DefaultReadBufferSize,
WriteBufferSize: DefaultWriteBufferSize,

View File

@ -34,11 +34,12 @@ type (
// DecodeCookie set it to true to decode the cookie key with base64 URLEncoding
// Defaults to false
DecodeCookie bool
//Expires the date which the cookie must expires. Default infinitive/unlimited life
Expires time.Time
// Expires the duration of which the cookie must expires (created_time.Add(Expires)).
// Default infinitive/unlimited life duration(0)
Expires time.Duration
// GcDuration every how much duration(GcDuration) the memory should be clear for unused cookies (GcDuration)
// for example: time.Duration(2)*time.Hour. it will check every 2 hours if cookie hasn't be used for 2 hours,
// deletes it from memory until the user comes back, then the session continue to work as it was
// deletes it from backend memory until the user comes back, then the session continue to work as it was
//
// Default 2 hours
GcDuration time.Duration
@ -54,7 +55,7 @@ func DefaultSessions() Sessions {
return Sessions{
Cookie: DefaultCookieName,
DecodeCookie: false,
Expires: CookieExpireNever,
Expires: 0,
GcDuration: DefaultSessionGcDuration,
DisableSubdomainPersistence: false,
}

View File

@ -6,7 +6,6 @@ import (
"github.com/imdario/mergo"
)
// Currently only these 5 values are used for real
const (
// DefaultWriteTimeout 15 * time.Second
DefaultWriteTimeout = 15 * time.Second
@ -20,7 +19,7 @@ const (
//
// Websocket the config contains options for 'websocket' package
// Websocket the config contains options for the ../websocket.go
type Websocket struct {
// WriteTimeout time allowed to write a message to the connection.
// Default value is 15 * time.Second

View File

@ -254,7 +254,10 @@ type (
// newServer returns a pointer to a Server object, and set it's options if any, nothing more
func newServer(cfg config.Server) *Server {
s := &Server{Server: &fasthttp.Server{Name: config.ServerName}, Config: cfg}
if cfg.Name == "" {
cfg.Name = config.DefaultServerName
}
s := &Server{Server: &fasthttp.Server{Name: cfg.Name}, Config: cfg}
s.prepare()
return s
}

26
iris.go
View File

@ -84,7 +84,7 @@ import (
const (
// Version of the iris
Version = "4.0.0-alpha.3"
Version = "4.0.0-alpha.4"
banner = ` _____ _
|_ _| (_)
@ -219,8 +219,6 @@ func New(cfg ...config.Iris) *Framework {
},
engines: make([]*templateEngineWrapper, 0),
}
//set the session manager
s.sessions = newSessionsManager(&c.Sessions)
// set the websocket server
s.Websocket = NewWebsocketServer(s.Config.Websocket)
// set the servemux, which will provide us the public API also, with its context pool
@ -236,6 +234,11 @@ func New(cfg ...config.Iris) *Framework {
}
func (s *Framework) initialize() {
if s.Config.Sessions.Cookie != "" {
//set the session manager
s.sessions = newSessionsManager(s.Config.Sessions)
}
// prepare the response engines, if no response engines setted for the default content-types
// then add them
@ -335,9 +338,9 @@ func (s *Framework) Must(err error) {
}
}
// AddServer same as .Servers.Add(config.Server) instead
// AddServer same as .Servers.Add(config.Server)
//
// AddServers starts a server which listens to this station
// AddServer starts a server which listens to this station
// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https)
//
// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station
@ -352,10 +355,10 @@ func AddServer(cfg config.Server) *Server {
return Default.AddServer(cfg)
}
// AddServer same as .Servers.Add(config.Server) instead
// AddServer same as .Servers.Add(config.Server)
//
// AddServers starts a server which listens to this station
// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the first's registered server's scheme (http/https)
// AddServer starts a server which listens to this station
// Note that the view engine's functions {{ url }} and {{ urlpath }} will return the last registered server's scheme (http/https)
//
// this is useful mostly when you want to have two or more listening ports ( two or more servers ) for the same station
//
@ -369,7 +372,7 @@ func (s *Framework) AddServer(cfg config.Server) *Server {
return s.Servers.Add(cfg)
}
// ListenTo listens to a server but receives the full server's configuration
// ListenTo listens to a server but accepts the full server's configuration
// returns an error, you're responsible to handle that
// or use the iris.Must(iris.ListenTo(config.Server{}))
//
@ -378,7 +381,10 @@ func ListenTo(cfg config.Server) error {
return Default.ListenTo(cfg)
}
// ListenTo listens to a server but receives the full server's configuration
// ListenTo listens to a server but acceots the full server's configuration
// returns an error, you're responsible to handle that
// or use the iris.Must(iris.ListenTo(config.Server{}))
//
// it's a blocking func
func (s *Framework) ListenTo(cfg config.Server) (err error) {
if cfg.ReadBufferSize == 0 {

View File

@ -42,6 +42,7 @@ type session struct {
values map[string]interface{} // here is the real values
mu sync.Mutex
lastAccessedTime time.Time
createdAt time.Time
provider *sessionProvider
}
@ -135,6 +136,7 @@ type (
sessions map[string]*list.Element // underline TEMPORARY memory store used to give advantage on sessions used more times than others
list *list.List // for GC
databases []SessionDatabase
expires time.Duration
}
)
@ -145,12 +147,25 @@ func (p *sessionProvider) registerDatabase(db SessionDatabase) {
}
func (p *sessionProvider) newSession(sid string) *session {
return &session{
sess := &session{
sid: sid,
provider: p,
lastAccessedTime: time.Now(),
values: p.loadSessionValues(sid),
}
if p.expires > 0 { // if not unlimited life duration
time.AfterFunc(p.expires, func() {
// the destroy makes the check if this session is exists then or not,
// this is used to destroy the session from the server-side also
// it's good to have here for security reasons, I didn't add it on the gc function to separate its action
p.destroy(sid)
})
}
return sess
}
func (p *sessionProvider) loadSessionValues(sid string) map[string]interface{} {
@ -203,7 +218,6 @@ func (p *sessionProvider) destroy(sid string) {
p.updateDatabases(sid, nil)
delete(p.sessions, sid)
p.list.Remove(elem)
}
p.mu.Unlock()
}
@ -234,10 +248,9 @@ func (p *sessionProvider) gc(duration time.Duration) {
// if the time has passed. session was expired, then delete the session and its memory place
// we are not destroy the session completely for the case this is re-used after
if time.Now().After(elem.Value.(*session).lastAccessedTime.Add(duration)) {
sess := elem.Value.(*session)
if time.Now().After(sess.lastAccessedTime.Add(duration)) {
p.list.Remove(elem)
delete(p.sessions, elem.Value.(*session).sid)
} else {
break
}
@ -254,19 +267,19 @@ type (
// sessionsManager implements the ISessionsManager interface
// contains the cookie's name, the provider and a duration for GC and cookie life expire
sessionsManager struct {
config *config.Sessions
config config.Sessions
provider *sessionProvider
}
)
// newSessionsManager creates & returns a new SessionsManager and start its GC
func newSessionsManager(c *config.Sessions) *sessionsManager {
func newSessionsManager(c config.Sessions) *sessionsManager {
if c.DecodeCookie {
c.Cookie = base64.URLEncoding.EncodeToString([]byte(c.Cookie)) // change the cookie's name/key to a more safe(?)
// get the real value for your tests by:
//sessIdKey := url.QueryEscape(base64.URLEncoding.EncodeToString([]byte(iris.Config.Sessions.Cookie)))
}
manager := &sessionsManager{config: c, provider: &sessionProvider{list: list.New(), sessions: make(map[string]*list.Element, 0), databases: make([]SessionDatabase, 0)}}
manager := &sessionsManager{config: c, provider: &sessionProvider{list: list.New(), sessions: make(map[string]*list.Element, 0), databases: make([]SessionDatabase, 0), expires: c.Expires}}
//run the GC here
go manager.gc()
return manager
@ -327,7 +340,13 @@ func (m *sessionsManager) start(ctx *Context) *session {
}
cookie.SetHTTPOnly(true)
cookie.SetExpire(m.config.Expires)
if m.config.Expires == 0 {
// unlimited life
cookie.SetExpire(config.CookieExpireNever)
} else {
cookie.SetExpire(time.Now().Add(m.config.Expires))
}
ctx.SetCookie(cookie)
fasthttp.ReleaseCookie(cookie)
} else {