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 *http.Request) { sess := globalSessions.SessionStart(w, 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, Path: "/", HttpOnly: true, 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") }
有疑问加站长微信联系(非本文作者)