session/tracker.go
2016-01-20 17:11:10 +08:00

220 lines
4.7 KiB
Go

// Copyright 2015 The Tango Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package session
import (
"net/http"
"net/url"
"sync"
"time"
)
// Tracker provide and set sessionid
type Tracker interface {
SetMaxAge(maxAge time.Duration)
Get(req *http.Request) (Id, error)
Set(req *http.Request, rw http.ResponseWriter, id Id)
Clear(rw http.ResponseWriter)
}
// CookieTracker provide sessionid from cookie
type CookieTracker struct {
Name string
MaxAge time.Duration
Lock sync.Mutex
Secure bool
RootPath string
Domain string
}
func NewCookieTracker(name string, maxAge time.Duration, secure bool, rootPath string) *CookieTracker {
return &CookieTracker{
Name: name,
MaxAge: maxAge,
Secure: secure,
RootPath: rootPath,
}
}
func (tracker *CookieTracker) SetMaxAge(maxAge time.Duration) {
tracker.MaxAge = maxAge
}
func (tracker *CookieTracker) Get(req *http.Request) (Id, error) {
cookie, err := req.Cookie(tracker.Name)
if err != nil {
if err == http.ErrNoCookie {
return "", nil
}
return "", err
}
if cookie.Value == "" {
return Id(""), nil
}
id, _ := url.QueryUnescape(cookie.Value)
return Id(id), nil
}
func (tracker *CookieTracker) Set(req *http.Request, rw http.ResponseWriter, id Id) {
sid := url.QueryEscape(string(id))
tracker.Lock.Lock()
defer tracker.Lock.Unlock()
cookie, _ := req.Cookie(tracker.Name)
if cookie == nil {
cookie = &http.Cookie{
Name: tracker.Name,
Value: sid,
Path: tracker.RootPath,
Domain: tracker.Domain,
HttpOnly: true,
Secure: tracker.Secure,
}
req.AddCookie(cookie)
} else {
cookie.Value = sid
}
http.SetCookie(rw, cookie)
}
func (tracker *CookieTracker) Clear(rw http.ResponseWriter) {
cookie := http.Cookie{
Name: tracker.Name,
Path: tracker.RootPath,
Domain: tracker.Domain,
HttpOnly: true,
Secure: tracker.Secure,
Expires: time.Date(0, 1, 1, 0, 0, 0, 0, time.Local),
MaxAge: -1,
}
http.SetCookie(rw, &cookie)
}
var _ Tracker = NewCookieTracker("test", 0, false, "/")
// UrlTracker provide sessionid from url
type UrlTracker struct {
Key string
ReplaceLink bool
}
func NewUrlTracker(key string, replaceLink bool) *UrlTracker {
return &UrlTracker{key, replaceLink}
}
func (tracker *UrlTracker) Get(req *http.Request) (Id, error) {
sessionId := req.URL.Query().Get(tracker.Key)
if sessionId != "" {
sessionId, _ = url.QueryUnescape(sessionId)
return Id(sessionId), nil
}
return Id(""), nil
}
func (tracker *UrlTracker) Set(req *http.Request, rw http.ResponseWriter, id Id) {
if tracker.ReplaceLink {
}
}
func (tracker *UrlTracker) SetMaxAge(maxAge time.Duration) {
}
func (tracker *UrlTracker) Clear(rw http.ResponseWriter) {
}
var (
_ Tracker = NewUrlTracker("id", false)
)
//for SWFUpload ...
func NewCookieUrlTracker(name string, maxAge time.Duration, secure bool, rootPath string) *CookieUrlTracker {
return &CookieUrlTracker{
CookieTracker: CookieTracker{
Name: name,
MaxAge: maxAge,
Secure: secure,
RootPath: rootPath,
},
}
}
type CookieUrlTracker struct {
CookieTracker
}
func (tracker *CookieUrlTracker) Get(req *http.Request) (Id, error) {
sessionId := req.URL.Query().Get(tracker.Name)
if sessionId != "" {
sessionId, _ = url.QueryUnescape(sessionId)
return Id(sessionId), nil
}
return tracker.CookieTracker.Get(req)
}
type HeaderTracker struct {
Name string
}
func NewHeaderTracker(name string) *HeaderTracker {
return &HeaderTracker{
Name: name,
}
}
func (tracker *HeaderTracker) SetMaxAge(maxAge time.Duration) {
}
func (tracker *HeaderTracker) Get(req *http.Request) (Id, error) {
val := req.Header.Get(tracker.Name)
return Id(val), nil
}
func (tracker *HeaderTracker) Set(req *http.Request, rw http.ResponseWriter, id Id) {
rw.Header().Set(tracker.Name, string(id))
}
func (tracker *HeaderTracker) Clear(rw http.ResponseWriter) {
}
/*
type CompositeTracker struct {
Trackers []Tracker
}
func NewCompositeTracker(trackers ...Tracker) *CompositeTracker {
return &CompositeTracker{trackers}
}
func (trackers *CompositeTracker) Get(req *http.Request) (Id, error) {
for _, tracker := range trackers.Trackers {
if id, err := tracker.Get(req); err == nil {
return id, nil
}
}
return Id(""), nil
}
func (trackers *CompositeTracker) SetMaxAge(maxAge time.Duration) {
for _, tracker := range trackers.Trackers {
tracker.SetMaxAge(maxAge)
}
}
func (trackers *CompositeTracker) Set(req *http.Request, rw http.ResponseWriter, id Id) {
for _, tracker := range trackers.Trackers {
tracker.Set(req, rw, id)
}
}
func (trackers *CompositeTracker) Clear(rw http.ResponseWriter) {
for _, tracker := range trackers.Trackers {
tracker.Clear(rw)
}
}*/