From 3393aad6afc6d826d5184f5930ca0b77445772ad Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Wed, 17 Sep 2014 14:35:48 +0800 Subject: [PATCH] . --- conf/wide.go | 43 +++++++-------- editor/editors.go | 10 ++-- file/files.go | 4 +- main.go | 27 ++++------ output/outputs.go | 8 +-- session/sessions.go | 108 +++++++++++++++++++++++++++++++++++++ {user => session}/users.go | 5 +- shell/shells.go | 19 +++---- user/sessions.go | 85 ----------------------------- 9 files changed, 161 insertions(+), 148 deletions(-) create mode 100644 session/sessions.go rename {user => session}/users.go (95%) delete mode 100644 user/sessions.go diff --git a/conf/wide.go b/conf/wide.go index 32415d2..a2bbc90 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -91,36 +91,33 @@ func (*conf) GetUserWorkspace(username string) string { // 获取 gocode 路径. func (*conf) GetGocode() string { - binDir := os.Getenv("GOBIN") - if "" != binDir { - return binDir + string(os.PathSeparator) + "gocode" - } - - binDir = os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - runtime.GOOS + "_" + os.Getenv("GOARCH") - if isExist(binDir) { - return binDir + string(os.PathSeparator) + "gocode" - } else { - return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - "gocode" - } + return getGOBIN() + "gocode" } // 获取 ide_stub 路径. func (*conf) GetIDEStub() string { - binDir := os.Getenv("GOBIN") - if "" != binDir { - return binDir + string(os.PathSeparator) + "ide_stub" + return getGOBIN() + "ide_stub" +} + +func getGOBIN() string { + ret := os.Getenv("GOBIN") + if "" != ret { + return ret + string(os.PathSeparator) } - binDir = os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - runtime.GOOS + "_" + os.Getenv("GOARCH") - if isExist(binDir) { - return binDir + string(os.PathSeparator) + "ide_stub" - } else { - return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - "ide_stub" + ret = os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + if isExist(ret) { + return ret + string(os.PathSeparator) } + + ret = os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + runtime.GOOS + "_" + runtime.GOARCH + if isExist(ret) { + return ret + string(os.PathSeparator) + } + + return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) } // 保存 Wide 配置. diff --git a/editor/editors.go b/editor/editors.go index ba680f4..d2be93e 100644 --- a/editor/editors.go +++ b/editor/editors.go @@ -12,7 +12,7 @@ import ( "strings" "github.com/b3log/wide/conf" - "github.com/b3log/wide/user" + "github.com/b3log/wide/session" "github.com/b3log/wide/util" "github.com/golang/glog" "github.com/gorilla/websocket" @@ -30,7 +30,7 @@ type snippet struct { // 建立编辑器通道. func WSHandler(w http.ResponseWriter, r *http.Request) { - session, _ := user.HTTPSession.Get(r, "wide-session") + session, _ := session.HTTPSession.Get(r, "wide-session") sid := session.Values["id"].(string) editorWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) @@ -99,7 +99,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) { return } - session, _ := user.HTTPSession.Get(r, "wide-session") + session, _ := session.HTTPSession.Get(r, "wide-session") username := session.Values["username"].(string) path := args["path"].(string) @@ -174,7 +174,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - session, _ := user.HTTPSession.Get(r, "wide-session") + session, _ := session.HTTPSession.Get(r, "wide-session") username := session.Values["username"].(string) decoder := json.NewDecoder(r.Body) @@ -255,7 +255,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - session, _ := user.HTTPSession.Get(r, "wide-session") + session, _ := session.HTTPSession.Get(r, "wide-session") username := session.Values["username"].(string) decoder := json.NewDecoder(r.Body) diff --git a/file/files.go b/file/files.go index baecea4..966a19b 100644 --- a/file/files.go +++ b/file/files.go @@ -12,7 +12,7 @@ import ( "strings" "github.com/b3log/wide/conf" - "github.com/b3log/wide/user" + "github.com/b3log/wide/session" "github.com/b3log/wide/util" "github.com/golang/glog" ) @@ -23,7 +23,7 @@ func GetFiles(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - session, _ := user.HTTPSession.Get(r, "wide-session") + session, _ := session.HTTPSession.Get(r, "wide-session") username := session.Values["username"].(string) userSrc := conf.Wide.GetUserWorkspace(username) + string(os.PathSeparator) + "src" diff --git a/main.go b/main.go index df4ec48..93df338 100644 --- a/main.go +++ b/main.go @@ -15,8 +15,8 @@ import ( "github.com/b3log/wide/i18n" "github.com/b3log/wide/notification" "github.com/b3log/wide/output" + "github.com/b3log/wide/session" "github.com/b3log/wide/shell" - "github.com/b3log/wide/user" "github.com/golang/glog" ) @@ -39,24 +39,16 @@ func init() { // Wide 首页. func indexHandler(w http.ResponseWriter, r *http.Request) { - // 创建一个 Wide 会话 - wideSession := user.WideSessions.New() - i18n.Load() - model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r), - "session": wideSession} + httpSession, _ := session.HTTPSession.Get(r, "wide-session") - httpSession, _ := user.HTTPSession.Get(r, "wide-session") - - httpSessionId := httpSession.Values["id"].(string) // TODO: 写死以 admin 作为用户登录 username := conf.Wide.Users[0].Name if httpSession.IsNew { httpSession.Values["username"] = username - httpSessionId = strconv.Itoa(rand.Int()) - httpSession.Values["id"] = httpSessionId + httpSession.Values["id"] = strconv.Itoa(rand.Int()) // 一天过期 httpSession.Options.MaxAge = 60 * 60 * 24 @@ -65,10 +57,13 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { httpSession.Save(r, w) - // Wide 会话关联 HTTP 会话 - wideSession.HTTPSessionId = httpSession.Values["id"].(string) + // 创建一个 Wide 会话 + wideSession := session.WideSessions.New(httpSession) - wideSessions := user.WideSessions.GetByHTTPSid(httpSessionId) + model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r), + "session": wideSession} + + wideSessions := session.WideSessions.GetByHTTPSession(httpSession) glog.V(3).Infof("User [%s] has [%d] sessions", username, len(wideSessions)) t, err := template.ParseFiles("view/index.html") @@ -135,8 +130,8 @@ func main() { http.HandleFunc("/notification/ws", notification.WSHandler) // 用户 - http.HandleFunc("/user/new", user.AddUser) - http.HandleFunc("/user/repos/init", user.InitGitRepos) + http.HandleFunc("/user/new", session.AddUser) + http.HandleFunc("/user/repos/init", session.InitGitRepos) // 文档 http.Handle("/doc/", http.StripPrefix("/doc/", http.FileServer(http.Dir("doc")))) diff --git a/output/outputs.go b/output/outputs.go index 9561d60..a1917f5 100644 --- a/output/outputs.go +++ b/output/outputs.go @@ -14,7 +14,7 @@ import ( "time" "github.com/b3log/wide/conf" - "github.com/b3log/wide/user" + "github.com/b3log/wide/session" "github.com/b3log/wide/util" "github.com/golang/glog" "github.com/gorilla/websocket" @@ -150,7 +150,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - httpSession, _ := user.HTTPSession.Get(r, "wide-session") + httpSession, _ := session.HTTPSession.Get(r, "wide-session") username := httpSession.Values["username"].(string) decoder := json.NewDecoder(r.Body) @@ -316,7 +316,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - httpSession, _ := user.HTTPSession.Get(r, "wide-session") + httpSession, _ := session.HTTPSession.Get(r, "wide-session") username := httpSession.Values["username"].(string) decoder := json.NewDecoder(r.Body) @@ -443,7 +443,7 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) - httpSession, _ := user.HTTPSession.Get(r, "wide-session") + httpSession, _ := session.HTTPSession.Get(r, "wide-session") username := httpSession.Values["username"].(string) decoder := json.NewDecoder(r.Body) diff --git a/session/sessions.go b/session/sessions.go new file mode 100644 index 0000000..765902e --- /dev/null +++ b/session/sessions.go @@ -0,0 +1,108 @@ +// 会话操作. +// Wide 服务器端需要维护两种会话: +// 1. HTTP 会话:主要用于验证登录 +// 2. Wide 会话:浏览器 tab 打开/刷新会创建一个,并和 HTTP 会话进行关联 +// +// TODO: 当 HTTP 会话失效时,关联的 Wide 会话也会做失效处理:释放所有和该会话相关的资源,例如运行中的程序进程、事件队列等 +package session + +import ( + "math/rand" + "strconv" + "sync" + "time" + + "github.com/golang/glog" + "github.com/gorilla/sessions" +) + +const ( + SessionStateActive = iota // 会话状态:活的 +) + +// 用户 HTTP 会话,用于验证登录. +var HTTPSession = sessions.NewCookieStore([]byte("BEYOND")) + +// Wide 会话,对应一个浏览器 tab. +type WideSession struct { + Id string // 唯一标识 + HTTPSession *sessions.Session // 关联的 HTTP 会话 + State int // 状态 + Created time.Time // 创建时间 + Updated time.Time // 最近一次使用时间 +} + +type Sessions []*WideSession + +// 所有 Wide 会话集. +var WideSessions Sessions + +// 排它锁,防止并发问题. +var mutex sync.Mutex + +// 创建一个 Wide 会话. +func (sessions *Sessions) New(httpSession *sessions.Session) *WideSession { + mutex.Lock() + defer mutex.Unlock() + + rand.Seed(time.Now().UnixNano()) + + id := strconv.Itoa(rand.Int()) + now := time.Now() + + ret := &WideSession{ + Id: id, + HTTPSession: httpSession, + State: SessionStateActive, + Created: now, + Updated: now, + } + + *sessions = append(*sessions, ret) + + return ret +} + +// 移除 Wide 会话. +func (sessions *Sessions) Remove(sid string) { + mutex.Lock() + defer mutex.Unlock() + + for i, s := range *sessions { + if s.Id == sid { + *sessions = append((*sessions)[:i], (*sessions)[i+1:]...) + + glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions)) + } + } +} + +// 获取 HTTP 会话关联的所有 Wide 会话. +func (sessions *Sessions) GetByHTTPSession(httpSession *sessions.Session) []*WideSession { + mutex.Lock() + defer mutex.Unlock() + + ret := []*WideSession{} + + for _, s := range *sessions { + if s.HTTPSession.ID == httpSession.ID { + ret = append(ret, s) + } + } + + return ret +} + +// 移除 HTTP 会话关联的所有 Wide 会话. +func (sessions *Sessions) RemoveByHTTPSession(httpSession *sessions.Session) { + mutex.Lock() + defer mutex.Unlock() + + for i, s := range *sessions { + if s.HTTPSession.ID == httpSession.ID { + *sessions = append((*sessions)[:i], (*sessions)[i+1:]...) + + glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions)) + } + } +} diff --git a/user/users.go b/session/users.go similarity index 95% rename from user/users.go rename to session/users.go index 765d3a9..e9977ab 100644 --- a/user/users.go +++ b/session/users.go @@ -1,5 +1,6 @@ -// 用户操作. -package user +package session + +// TODO: 这个包目前没有使用,只是开了个头 :p import ( "encoding/json" diff --git a/shell/shells.go b/shell/shells.go index 936506c..72885ec 100644 --- a/shell/shells.go +++ b/shell/shells.go @@ -14,7 +14,7 @@ import ( "github.com/b3log/wide/conf" "github.com/b3log/wide/i18n" - "github.com/b3log/wide/user" + "github.com/b3log/wide/session" "github.com/b3log/wide/util" "github.com/golang/glog" "github.com/gorilla/websocket" @@ -26,15 +26,9 @@ var shellWS = map[string]*util.WSChannel{} // Shell 首页. func IndexHandler(w http.ResponseWriter, r *http.Request) { - // 创建一个 Wide 会话 - wideSession := user.WideSessions.New() - i18n.Load() - model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r), - "session": wideSession} - - httpSession, _ := user.HTTPSession.Get(r, "wide-session") + httpSession, _ := session.HTTPSession.Get(r, "wide-session") if httpSession.IsNew { // TODO: 写死以 admin 作为用户登录 @@ -50,8 +44,11 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { httpSession.Save(r, w) - // Wide 会话关联 HTTP 会话 - wideSession.HTTPSessionId = httpSession.Values["id"].(string) + // 创建一个 Wide 会话 + wideSession := session.WideSessions.New(httpSession) + + model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r), + "session": wideSession} t, err := template.ParseFiles("view/shell.html") @@ -67,7 +64,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { // 建立 Shell 通道. func WSHandler(w http.ResponseWriter, r *http.Request) { - httpSession, _ := user.HTTPSession.Get(r, "wide-session") + httpSession, _ := session.HTTPSession.Get(r, "wide-session") username := httpSession.Values["username"].(string) // TODO: 会话校验 diff --git a/user/sessions.go b/user/sessions.go deleted file mode 100644 index 13de7b1..0000000 --- a/user/sessions.go +++ /dev/null @@ -1,85 +0,0 @@ -package user - -import ( - "math/rand" - "strconv" - "time" - - "github.com/golang/glog" - "github.com/gorilla/sessions" -) - -const ( - SessionStateActive = iota // 会话状态:活的 -) - -// 用户 HTTP 会话,用于验证登录. -var HTTPSession = sessions.NewCookieStore([]byte("BEYOND")) - -// Wide 会话,对应一个浏览器 tab. -type WideSession struct { - Id string // 唯一标识 - HTTPSessionId string // HTTP 会话 id - State int // 状态 - Created time.Time // 创建时间 - Updated time.Time // 最近一次使用时间 -} - -type Sessions []*WideSession - -// 所有 Wide 会话集. -var WideSessions Sessions - -// 创建一个 Wide 会话. -func (sessions *Sessions) New() *WideSession { - rand.Seed(time.Now().UnixNano()) - - id := strconv.Itoa(rand.Int()) - now := time.Now() - - ret := &WideSession{ - Id: id, - State: SessionStateActive, - Created: now, - Updated: now, - } - - *sessions = append(*sessions, ret) - - return ret -} - -// 移除 Wide 会话. -func (sessions *Sessions) Remove(sid string) { - for i, s := range *sessions { - if s.Id == sid { - *sessions = append((*sessions)[:i], (*sessions)[i+1:]...) - - glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions)) - } - } -} - -// 获取 HTTP 会话关联的所有 Wide 会话. -func (sessions *Sessions) GetByHTTPSid(httpSessionId string) []*WideSession { - ret := []*WideSession{} - - for _, s := range *sessions { - if s.HTTPSessionId == httpSessionId { - ret = append(ret, s) - } - } - - return ret -} - -// 移除 HTTP 会话关联的所有 Wide 会话. -func (sessions *Sessions) RemoveByHTTPSid(httpSessionId string) { - for i, s := range *sessions { - if s.HTTPSessionId == httpSessionId { - *sessions = append((*sessions)[:i], (*sessions)[i+1:]...) - - glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions)) - } - } -}