main
- // main project main.go
- package main
- import (
- "fmt"
- "html/template"
- "log"
- "net/http"
- "strings"
- "session"
- _"memory"
- "time"
- )
- func sayHelloName(w http.ResponseWriter,r *http.Request) {
- r.ParseForm()
- fmt.Println(r.Form)
- fmt.Println(r.URL.Path)
- fmt.Println(r.URL.Scheme)
- fmt.Println(r.Form["url_long"])
- for k,v := range r.Form {
- fmt.Println("key: ",k)
- fmt.Println("value:",strings.Join(v,""))
- }
- fmt.Fprintln(w,"hello nihao")
- }
- func login(w http.ResponseWriter,r *http.Request) {
- r.ParseForm()
- fmt.Println("method: ",r.Method)
- if r.Method == "GET" {
- t,err := template.ParseFiles("src/html/login.gtpl")
- if err != nil {
- fmt.Println(err)
- return
- }
- t.Execute(w,nil)
- } else {
- fmt.Println("username: ",r.Form["username"])
- fmt.Println("password: ",r.Form["password"])
- }
- }
- func login2(w http.ResponseWriter,r *http.Request) {
- sess := globalSessions.SessionStart(w,r)
- r.ParseForm()
- if r.Method == "GET" {
- t,_ := template.ParseFiles("src/html/login.gtpl")
- //w.Header().Set("Content-Type","text/html")
- t.Execute(w,sess.Get("username"))
- } else {
- sess.Set("username",r.Form["username"])
- http.Redirect(w,r,"/",302)
- }
- }
- func count(w http.ResponseWriter,r)
- createtime := sess.Get("createtime")
- if createtime == nil {
- sess.Set("createtime",time.Now().Unix())
- } else if (createtime.(int64) + 360) < (time.Now().Unix()) {
- globalSessions.SessionDestroy(w,r)
- sess = globalSessions.SessionStart(w,r)
- }
- ct := sess.Get("countnum")
- if ct == nil {
- sess.Set("countnum",1)
- } else {
- sess.Set("countnum",(ct.(int) + 1))
- }
- t,_ := template.ParseFiles("count.gtpl")
- w.Header().Set("Content-Type","text/html")
- t.Execute(w,sess.Get("countnum"))
- }
- func main() {
- //http.HandleFunc("/",sayHelloName);
- http.HandleFunc("/login",login)
- http.HandleFunc("/login2",login2)
- err := http.ListenAndServe(":9090",nil)
- if err != nil {
- log.Fatalf("Listen and server",err)
- }
- }
- var globalSessions *session.Manager
- func init() {
- globalSessions,_ = session.NewSessionManager("memory","goSessionid",3600)
- go globalSessions.GC()
- fmt.Println("fd")
- }
session
- package session
- import (
- "crypto/rand"
- "encoding/base64"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "sync"
- "time"
- )
- type Manager struct {
- cookieName string
- lock sync.Mutex
- provider Provider
- maxLifeTime int64
- }
- type Provider interface {
- SessionInit(sid string) (Session,error)
- SessionRead(sid string) (Session,error)
- SessionDestroy(sid string) error
- SessionGC(maxLifeTime int64)
- }
- type Session interface {
- Set(key,value interface{}) error
- Get(key interface{}) interface{}
- Delete(ket interface{}) error
- SessionID() string
- }
- func NewSessionManager(provideName,cookieName string,maxLifeTime int64) (*Manager,error) {
- provide,ok := provides[provideName]
- if !ok {
- return nil,fmt.Errorf("session: unknown provide %q (forgotten import?",provideName)
- }
- return &Manager{cookieName: cookieName,provider: provide,maxLifeTime: maxLifeTime},nil
- }
- func Register(name string,provide Provider) {
- if provide == nil {
- panic("session: Register provide is nil")
- }
- if _,dup := provides[name]; dup {
- panic("session: Register called twice for provide " + name)
- }
- provides[name] = provide
- }
- var provides = make(map[string]Provider)
- func (manager *Manager) sessionId() string {
- b := make([]byte,32)
- if _,err := io.ReadFull(rand.Reader,b); err != nil {
- return ""
- }
- return base64.URLEncoding.EncodeToString(b)
- }
- func (manager *Manager) SessionStart(w http.ResponseWriter,r *http.Request) (session Session) {
- manager.lock.Lock()
- defer manager.lock.Unlock()
- cookie,err := r.Cookie(manager.cookieName)
- if err != nil || cookie.Value == "" {
- sid := manager.sessionId()
- session,_ = manager.provider.SessionInit(sid)
- cookie := http.Cookie{Name: manager.cookieName,Value: url.QueryEscape(sid),Path: "/",HttpOnly: true,MaxAge: int(manager.maxLifeTime)}
- http.SetCookie(w,&cookie)
- } else {
- sid,_ := url.QueryUnescape(cookie.Value)
- session,_ = manager.provider.SessionRead(sid)
- }
- return session
- }
- func (manager *Manager) SessionDestroy(w http.ResponseWriter,r *http.Request){
- cookie,err := r.Cookie(manager.cookieName)
- if err != nil || cookie.Value == "" {
- return
- } else {
- manager.lock.Lock()
- defer manager.lock.Unlock()
- manager.provider.SessionDestroy(cookie.Value)
- expiration := time.Now()
- cookie := http.Cookie{Name: manager.cookieName,Expires: expiration,MaxAge: -1}
- http.SetCookie(w,&cookie)
- }
- }
- func (manager *Manager) GC() {
- manager.lock.Lock()
- defer manager.lock.Unlock()
- manager.provider.SessionGC(manager.maxLifeTime)
- time.AfterFunc(time.Duration(manager.maxLifeTime),func(){ manager.GC() })
- }
memory
- package memory
- import (
- "container/list"
- "time"
- "sync"
- "fmt"
- "session"
- )
- type SessionStore struct {
- sid string //session id 唯一标示
- timeAccessed time.Time //最后访问时间
- value map[interface{}]interface{} //session 里面存储的值
- }
- func (st *SessionStore) Set(key,value interface{}) error {
- st.value[key] = value
- pder.SessionUpdate(st.sid)
- return nil
- }
- func (st *SessionStore) Get(key interface{}) interface{} {
- pder.SessionUpdate(st.sid)
- if v,ok := st.value[key]; ok {
- return v
- } else {
- return nil
- }
- return nil
- }
- func (st *SessionStore) Delete(key interface{}) error {
- delete(st.value,key)
- pder.SessionUpdate(st.sid)
- return nil
- }
- func (st *SessionStore) SessionID() string {
- return st.sid
- }
- type Provider struct {
- lock sync.Mutex //用来锁
- sessions map[string]*list.Element //用来存储在内存
- list *list.List //用来做 gc
- }
- func (provider *Provider) SessionInit(sid string) (session.Session,error) {
- provider.lock.Lock()
- defer provider.lock.Unlock()
- v := make(map[interface{}]interface{},0)
- newsess := &SessionStore{sid: sid,timeAccessed: time.Now(),value: v}
- element := provider.list.PushBack(newsess)
- provider.sessions[sid] = element
- return newsess,nil
- }
- func (provider *Provider) SessionRead(sid string) (session.Session,error) {
- if element,ok := provider.sessions[sid]; ok {
- return element.Value.(*SessionStore),nil
- } else {
- sess,err := provider.SessionInit(sid)
- return sess,err
- }
- return nil,nil
- }
- func (provider *Provider) SessionDestroy(sid string) error {
- if element,ok := provider.sessions[sid]; ok {
- delete(provider.sessions,sid)
- provider.list.Remove(element)
- return nil
- }
- return nil
- }
- func (provider *Provider) SessionGC(maxLifeTime int64) {
- provider.lock.Lock()
- defer provider.lock.Unlock()
- for {
- element := provider.list.Back()
- if element == nil {
- break
- }
- if (element.Value.(*SessionStore).timeAccessed.Unix() + maxLifeTime) <
- time.Now().Unix() {
- provider.list.Remove(element)
- delete(provider.sessions,element.Value.(*SessionStore).sid)
- } else {
- break
- }
- }
- }
- func (provider *Provider) SessionUpdate(sid string) error {
- provider.lock.Lock()
- defer provider.lock.Unlock()
- if element,ok := provider.sessions[sid]; ok {
- element.Value.(*SessionStore).timeAccessed = time.Now()
- provider.list.MoveToFront(element)
- return nil
- }
- return nil
- }
- var pder = &Provider{list: list.New()}
- func init() {
- pder.sessions = make(map[string]*list.Element,0)
- session.Register("memory",pder)
- fmt.Println("wzz")
- }