Giter Club home page Giter Club logo

simplesessions's Introduction

simplesessions

simplesessions is a "pure" Go session library that is completely agnostic of HTTP libraries and frameworks, backend stores, and even cookie jars.

Why?

Most session libraries are highly opinionated and hard-wired to work with net/http handlers (or other 3rd party libraries like fasthttp) and take liberties on how session data should be encoded and stored. simplesessions takes a pragmatic approach, where everything from HTTP request and cookie handling to data encoding and session storage are plugged in as simple callback functions. Moreover, most session libraries treat data as strings losing type information. simplessions provides a way to maintain primitive types such as int, string etc.

Features

  1. Framework/network library agnostic.
  2. Simple API and with support for primitive data types. Complex types can be stored using own encoding/decoding.
  3. Pre-built redis/postgres/in-memory/securecookie stores that can be separately installed.
  4. Multiple session instances with custom handlers and different backend stores.

Installation

Install simplesessions and all available stores.

go get -u github.com/zerodha/simplesessions/v3

# Install the requrired store: memory|redis|postgres|securecookie
go get -u github.com/zerodha/simplesessions/v3/stores/redis
go get -u github.com/zerodha/simplesessions/v3/stores/postgres

Stores

Sessions can be stored to any backend by implementing the store interface. The following stores are bundled.

Usage

Check the examples directory for complete examples.

Connecting a store

Stores can be registered to a session instance by using Use method. Check individual Stores docs for more details.

sess := simplesessions.New(simplesessions.Options{})
sess.UseStore(store.New())

Connecting an HTTP handler

Any HTTP library can be connected to simplesessions by registering the get and set cookie hooks using SetCookieHooks(). The below example shows a simple net/http usecase. Another example showing fasthttp can be found here.

var sessMan *simplesessions.Manager

func getCookie(name string, r interface{}) (*http.Cookie, error) {
	// Get read interface registered using `Acquire` method in handlers.
	rd := r.(*http.Request)

	// Send cookie for received cookie name from request.
	// Note that other networking libs and frameworks should
	// also send back cookie in net/http cookie format.
	// If cookie is not found for given cookie name then
	// `http.ErrNoCookie` should be returned.
	// Cookie name is what you set while creating session manager
	// with custom options (`Options.CookieName`). Defaults to `session`.
	cookie, err := rd.Cookie(name)
	if err != nil {
		return nil, err
	}

	return cookie, nil
}

func setCookie(cookie *http.Cookie, w interface{}) error {
	// Get write interface registered using `Acquire` method in handlers.
	wr := w.(http.ResponseWriter)

	// net/http cookie is returned which can be
	// used to set cookie for current request.
	// Note that other network libraries or
	// framework will also receive cookie as
	// net/http cookie and it has to set cookie accordingly.
	http.SetCookie(wr, cookie)
	return nil
}

func handler(w http.ResponseWriter, r *http.Request) {
	// Use method `Acquire` to acquire a session before you access the session.
	// Acquire takes read, write interface and context respectively.
	// Read interface sent to callback registered with get cookie hook
	// and write interface is sent to callback registered with write cookie hook
	// set using `SetCookieHooks()` method.
	//
	// Optionally `context` can be sent which is usually request context where acquire
	// session will get previously loaded session. This is useful if you have multiple
	// middlewares accessing sessions. New sessions will be created in first middleware which
	// does `Acquire` and will be reused in other places.
	//
	// If `Options.EnableAutoCreate` is set to True then if session doesn't exist it will
	// be immediately created and returned. Bydefault its set to False so if session doesn't
	// exist then `ErrInvalidSession` error is returned.
	sess, err := sessMan.Acquire(nil, r, w)

	// If session doesn't exist then create new session.
	// In a traditional login flow you can create a new session once user completes the login flow.
	if err == simplesessions.ErrInvalidSession {
		sess, err = sessMan.NewSession(r, w)
	}

	// Use 'Set` or `SetMulti` to set a field for session.
	err = sess.Set("somekey", "somevalue")
	err = sess.SetMulti(map[string]interface{}{
		"k1": "v1",
		"k2": "v2",
	})

	// Use `Get` method to get a field from current session. The result will be an interface
	// so you can use helper methods like
	// `String', `Int`, `Int64`, `UInt64`, `Float64`, `Bytes`, `Bool`.
	val, err := sess.String(sess.Get("somekey"))
	fmt.Println("val=", val)

	// Use `GetAll` to get map of all fields from session.
	// The result is map of string and interface you can use helper methods to type cast it.
	all, err := sess.GetAll()
	fmt.Println("all=", all)

	// Use `GetMulti` to get values for given fields from session.
	// The result is map of string and interface you can use helper methods to type cast it.
	// If key is not there then store should ideally send `nil` value for given key.
	vals, err := sess.GetMulti("somekey", "someotherkey")
	fmt.Println("vals=", vals)

	// Use `Delete` to delete a field from session.
	err = sess.Delete("somekey")

	// Use `Clear` to empty the session but to keep the session alive.
	err = sess.Clear()

	// Use `Destroy` to clear session from store and cookie.
	err = sess.Destroy()

	fmt.Fprintf(w, "success")
}

func main() {
	// Create a session manager with custom options like cookie name,
	// cookie domain, is secure cookie etc. Check `Options` struct for more options.
	sessMan := simplesessions.New(simplesessions.Options{
		// If set to true then `Acquire()` method will create new session instead of throwing
		// `ErrInvalidSession` when the session doesn't exist. By default its set to false.
		EnableAutoCreate: false,
		Cookie: simplesessions.CookieOptions{
			// Name sets http cookie name. This is also sent as cookie name in `GetCookie` callback.
			Name: "session",
			// Domain sets hostname for the cookie. Domain specifies allowed hosts to receive the cookie.
			Domain: "example.com",
			// Path sets path for the cookie. Path indicates a URL path that must exist in the requested URL in order to send the cookie header.
			Path: "/",
			// IsSecure marks the cookie as secure cookie (only sent in HTTPS).
			IsSecure: true,
			// IsHTTPOnly marks the cookie as http only cookie. JS won't be able to access the cookie so prevents XSS attacks.
			IsHTTPOnly: true,
			// SameSite sets allows you to declare if your cookie should be restricted to a first-party or same-site context.
			SameSite: http.SameSiteDefaultMode,
			// Expires sets absolute expiration date and time for the cookie.
			// If both Expires and MaxAge are sent then MaxAge takes precedence over Expires.
			// Cookies without a Max-age or Expires attribute – are deleted when the current session ends
			// and some browsers use session restoring when restarting. This can cause session cookies to last indefinitely.
			Expires: time.Now().Add(time.Hour * 24),
			// Sets the cookie's expiration in seconds from the current time, internally its rounder off to nearest seconds.
			// If both Expires and MaxAge are sent then MaxAge takes precedence over Expires.
			// Cookies without a Max-age or Expires attribute – are deleted when the current session ends
			// and some browsers use session restoring when restarting. This can cause session cookies to last indefinitely.
			MaxAge: time.Hour * 24,
		},
	})

	// Create a new store instance and attach to session manager
	sessMan.UseStore(memory.New())
	// Register callbacks for read and write cookie.
	// Get cookie callback should get cookie based on cookie name and
	// sent back in net/http cookie format.
	// Set cookie callback should set cookie it received for received cookie name.
	sessMan.SetCookieHooks(getCookie, setCookie)

	// Initialize the handler.
	http.HandleFunc("/", handler)
}

simplesessions's People

Contributors

joeirimpan avatar joicemjoseph avatar kalbhor avatar knadh avatar riteshshrv avatar vividvilla avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

simplesessions's Issues

[Feature request] Chain Setting values in session

It will be great to have a feature to set values to a session, like the following.

sess, _ := session.Aquire(...,...)
err := sess.Set('key1', 'value1').Set('key2', 'value2')...Commit()

If this sounds good, I can add this feature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.