Analysis of gin-contrib/session source code

Initial code:

redis.NewStore is used to configure the redis connection, and the last parameter is used as the encryption key to encrypt the sessionid.


The first is that the sessions.Sessions method returns an httphandler middleware. All requests share the same store, that is, share the same underlying storage.


Next, obtain the value corresponding to the count key in the session server information through session.Get("count"). The Get method is as follows:


The Session method is defined as follows:


The following method is defined in the redistore.go file


This code is called by the session.Sessions() method. The method returns the sessions.Session structure. The structure is defined as follows. The name in the structure is the name of the session, and Values ​​is the key-value pair stored on the server corresponding to the session-name. User-defined information in the form of. Options are cookie options, such as Domain, Path, Expires, HttpOnly, etc. cookie configuration options, store is the underlying storage of session, and the current analysis is corresponding to redis.

// Session stores the values and optional configuration for a session.
type Session struct {
	// The ID of the session, generated by stores. It should not be used for
	// user data.
	ID string
	// Values contains the user-data for the session.
	Values  map[interface{}]interface{}
	Options *Options
	IsNew   bool
	store   Store
	name    string

Here is the actual cookie in the browser to help understand:


Back to the Get method above, first call the sessions.GetRegistry® method, the GetRegistry® method is as follows:


This code first calls the Get method in to determine whether the request carries a key-value pair whose key is registryKey. The Registry structure contains a member request and a mapping session. This mapping contains the session name and One-to-one correspondence of the above Session structure. In other words, a request can correspond to multiple sessions, and these sessions have different names or sessionids. This structure can be simply understood as a request session management module that maintains different sessions requested by a request. Here is a little question, why does a request have a different session? I realized that because a request can have multiple session-ids, a session-id is in the form of a cookie, and a user can have multiple session-ids to obtain different user information, for example, session-userinfo is used Login verification, session-articlelike is used to get user’s article like information. Here is an example:


Back to the code analysis,

If the above key-value pair does not exist in the request, the structure is created and the key-value pair is included in the request, and the structure is returned.

Next, call the Get method of the Registry structure in the Get method,


As you can see, this method first judges whether the session-name is legal, if it is not legal, it returns directly, then it judges whether the key is already included in the Registry, and if it does, it returns the corresponding value directly, which is the Session structure above. Session.Values ​​can get session custom information. If this key is not included, go to the store.New method.


This code is the code that creates the Session structure. If the request contains the cookie value corresponding to the name, the actual ID value of the session is obtained by secure decryption, and then the ID is passed from the redis cache through s.load(session) The value is session.ID to find the corresponding custom session information and fill it in the session.values ​​mapping.


This code is the specific load method. It is very simple. It is to obtain the redis connection from the redis connection pool and then query the key-value pair data through the Get command, and then deserialize it and store it in the values ​​field of the session structure.


So the whole process above is the process of reading the corresponding value of a key. Think about it. At the beginning, the user first initiates a get request, and the process goes to the store.New method. At this time, the request sent by the browser does not contain the session cookie, so it directly returns a Session structure with no key in the values ​​member. Correct. At this time, the above session.Get("count") is nil.


Use a picture to visually summarize the above process:


Next, call the session.Set("count", count) method.


This method is to directly store the user-defined sessioninfo key-value pair into the values ​​mapping of the sessions.Session structure. At this time, it has not been persisted to the Redis cache.

Next, call the session.Save() method to persist the key-value pairs in values ​​to redis.


The process of s.Session() is consistent with the above, so I won't repeat it. Take a look at the Save method:


Call the Save method in redistore.go:


If the cookie corresponding to the Session expires, the corresponding cookie is recreated and returned; if the cookie corresponding to the Session is not expired, a random sessionid is generated first, and then is called to map the values ​​in the session structure Key-value pairs are persisted in the redis cache. Then the sessionID is encrypted and encoded with a key and set into the set-cookie field of the request response. The following is the definition of the save method. It is to store the session-id and the serialized user-defined key-value pair string in the redis set.