Beego source code analysis three (session module)

The session module is used to store client users. The session module currently only supports cookie requests. If the client does not support cookies, the module cannot be used.

Beego session module code structure

Look at the readme to see how to use it

The package must first be imported:

import (	"github.com/astaxie/beego/session")

Then you need to define a global variable

var globalSessions *session.Manager

Finally, you can use session in the following way

func init() {	globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid", "enableSetCookie,omitempty": true, "gclifetime":3600, "maxLifetime": 3600, "secure": false, "sessionIDHashFunc": "sha1", "sessionIDHashKey": "", "cookieLifeTime": 3600, "providerConfig": ""}`)	go globalSessions.GC()}

The above is the usage of the session module introduced in the readme.md file.

Let's see how beego uses this module.

Mouse click session.NewManager to see where it is used, and you can see that beego uses this sessino module in the following functions

func registerSession() error {	if BConfig.WebConfig.Session.SessionOn {		var err error		sessionConfig := AppConfig.String("sessionConfig")		conf := new(session.ManagerConfig)		if sessionConfig == "" {			conf.CookieName = BConfig.WebConfig.Session.SessionName			conf.EnableSetCookie = BConfig.WebConfig.Session.SessionAutoSetCookie			conf.Gclifetime = BConfig.WebConfig.Session.SessionGCMaxLifetime			conf.Secure = BConfig.Listen.EnableHTTPS			conf.CookieLifeTime = BConfig.WebConfig.Session.SessionCookieLifeTime			conf.ProviderConfig = filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig)			conf.DisableHTTPOnly = BConfig.WebConfig.Session.SessionDisableHTTPOnly			conf.Domain = BConfig.WebConfig.Session.SessionDomain			conf.EnableSidInHTTPHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader			conf.SessionNameInHTTPHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader			conf.EnableSidInURLQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery		} else {			if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil {				return err			}		}		if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, conf); err != nil {			return err		}		go GlobalSessions.GC()	}	return nil}

The above code is very simple.

1. First, configure the session ON state,

2. Read sessionConfig from the configuration file, and read it out as a string,

3. If sessionConfig is not configured in the configuration file, that is, the string is empty, then the default configuration is used (see the previous article, the configuration in this structure will first initialize some configuration items and fill it in)

4. If the sessionConfig string is read, it will be deserialized into a conf structure,

5. Next is the introduction in readme.md in the session module, first newManager, then gc

There is a problem here :

What is passed in the readme is a string, why is a configuration structure passed in when beego is used?

View source code

func NewManager(provideName string, cf *ManagerConfig) (*Manager, error) {    ...}

The parameter is indeed a pointer to the ManagerConfig structure, so why pass a string in readme.md?

Will it be automatically deserialized?

I decided to experiment:

Strange, why not? Is there a problem with the readme.md?

I decided to go to beego to use the session function and try to change the conf to a string

????

What about cheating?

Is the readme.md wrong? I directly copied the string in readme.md. as follows:

Wipe, what about cheating?

--------------------------------------------

Cross it first, let's look at the source code first!

The session module, like the config module in the previous article, also adopts the factory mode, using one interface and multiple implementations. Four storage engines, memory, file, Redis, and MySQL are currently implemented.

Interface: Two interfaces need to be implemented here, one Provider and one Store.Store is used for storage, and Provide is used for session-related, and Store interface will be used.

type Provider interface {	SessionInit(gclifetime int64, config string) error	SessionRead(sid string) (Store, error)	SessionExist(sid string) bool	SessionRegenerate(oldsid, sid string) (Store, error)	SessionDestroy(sid string) error	SessionAll() int //get all active session	SessionGC()}// Store contains all data for one session process with specific id.type Store interface {	Set(key, value interface{}) error     //set session value	Get(key interface{}) interface{}      //get session value	Delete(key interface{}) error         //delete session value	SessionID() string                    //back current sessionID	SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data	Flush() error                         //delete all data}

Look at the realization of a file:,

First implement the store interface

Then implement the Provider interface

Finally, call the registration function of the session and register it to the session module

func init() {	Register("file", filepder)}

It's very simple, how to achieve it, I won't go into it, and I will look at it if necessary.