seshcookie

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 15, 2016 License: MIT Imports: 20 Imported by: 0

README

seshcookie allows you to associate session-state with http requests while allowing your server to remain stateless. Because session-state is transferred as part of the HTTP request, state can be maintained seamlessly between server-restarts or load balancing. It's inspired by Beaker, which provides a similar service for Python webapps. The cookies are AES encrypted in CTR mode, with the key derived from a user-specified string.

examples

Perhaps the simplest example would be a handler which returns different content based on if the user has been to the site before or not:

package main

import (
	"net/http"
	"log"
	"fmt"
	"github.com/bpowers/seshcookie"
)

type VisitedHandler struct{}

func (h *VisitedHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if req.URL.Path != "/" {
		return
	}

	session := seshcookie.Session.Get(req)

	count, _ := session["count"].(int)
	count += 1
	session["count"] = count

	rw.Header().Set("Content-Type", "text/plain")
	rw.WriteHeader(200)
	if count == 1 {
		rw.Write([]byte("this is your first visit, welcome!"))
	} else {
		rw.Write([]byte(fmt.Sprintf("page view #%d", count)))
	}
}

func main() {
	key := "session key, preferably a sequence of data from /dev/urandom"
	http.Handle("/", seshcookie.NewSessionHandler(
		&VisitedHandler{},
		key,
		nil))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

There is a more detailed example in example/ which uses seshcookie to enforce authentication for a particular resource. In particular, it shows how you can embed (or stack) multiple http.Handlers to get the behavior you want.

license

seshcookie is offered under the MIT license, see LICENSE for details.

Documentation

Overview

The seshcookie package implements an http.Handler which provides stateful sessions stored in cookies. Because session-state is transferred as part of the HTTP request, state can be maintained seamlessly between server-restarts or load balancing.

For example, here is a simple handler which returns differnet content if you've visited the site before:

package main

import (
	"http"
	"log"
	"fmt"
	"seshcookie"
)

type VisitedHandler struct{}

func (h *VisitedHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if req.URL.Path != "/" {
		return
	}

	session := seshcookie.Session.Get(req)

	count, _ := session["count"].(int)
	count += 1
	session["count"] = count

	rw.Header().Set("Content-Type", "text/plain")
	rw.WriteHeader(200)
	if count == 1 {
		rw.Write([]byte("this is your first visit, welcome!"))
	} else {
		rw.Write([]byte(fmt.Sprintf("page view #%d", count)))
	}
}

func main() {
	key := "session key, preferably a sequence of data from /dev/urandom"
	http.Handle("/", seshcookie.NewSessionHandler(
		&VisitedHandler{},
		key,
		nil))

	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

Index

Constants

This section is empty.

Variables

View Source
var (
	// if you don't need multiple independent seshcookie
	// instances, you can use this RequestSessions instance to
	// manage & access your sessions.  Simply use it as the final
	// parameter in your call to seshcookie.NewSessionHandler, and
	// whenever you want to access the current session from an
	// embedded http.Handler you can simply call:
	//
	//     seshcookie.Session.Get(req)
	Session = &RequestSessions{HttpOnly: true}

	// Hash validation of the decrypted cookie failed. Most likely
	// the session was encoded with a different cookie than we're
	// using to decode it, but its possible the client (or someone
	// else) tried to modify the session.
	HashError = errors.New("Hash validation failed")

	// The cookie is too short, so we must exit decoding early.
	LenError = errors.New("Bad cookie length")
)

Functions

This section is empty.

Types

type RequestSessions

type RequestSessions struct {
	HttpOnly bool // don't allow javascript to access cookie
	Secure   bool // only send session over HTTPS
	// contains filtered or unexported fields
}

func (*RequestSessions) Clear

func (rs *RequestSessions) Clear(req *http.Request)

func (*RequestSessions) Get

func (rs *RequestSessions) Get(req *http.Request) map[string]interface{}

func (*RequestSessions) Set

func (rs *RequestSessions) Set(req *http.Request, val map[string]interface{}, gobHash []byte)

type SessionHandler

type SessionHandler struct {
	http.Handler
	CookieName string // name of the cookie to store our session in
	CookiePath string // resource path the cookie is valid for
	RS         *RequestSessions
	// contains filtered or unexported fields
}

func NewSessionHandler

func NewSessionHandler(handler http.Handler, key string, rs *RequestSessions) *SessionHandler

func (*SessionHandler) ServeHTTP

func (h *SessionHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request)

Source Files

  • doc.go
  • seshcookie.go

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL