From 07f38fd4839ef57b8bc9e57a6f0b8c207c7780d3 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Tue, 16 Sep 2014 15:06:52 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/zh_CN/dev/index.html | 4 +-- main.go | 1 + notification/notifications.go | 62 +++++------------------------------ output/outputs.go | 27 +++++++++++---- shell/shells.go | 19 ++++++++--- util/websocket.go | 16 +++++++++ 6 files changed, 61 insertions(+), 68 deletions(-) create mode 100644 util/websocket.go diff --git a/doc/zh_CN/dev/index.html b/doc/zh_CN/dev/index.html index d93f924..e287ad3 100644 --- a/doc/zh_CN/dev/index.html +++ b/doc/zh_CN/dev/index.html @@ -44,8 +44,8 @@ WebSocket 用于后端推送数据给前端:

diff --git a/main.go b/main.go index 539fb04..aa1a5fa 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } +// 主程序入口. func main() { runtime.GOMAXPROCS(conf.Wide.MaxProcs) diff --git a/notification/notifications.go b/notification/notifications.go index 79cc94c..26874d7 100644 --- a/notification/notifications.go +++ b/notification/notifications.go @@ -3,16 +3,14 @@ package notification import ( "net/http" - "os" - "os/exec" - "runtime" + "time" "strconv" - "github.com/b3log/wide/conf" "github.com/b3log/wide/event" "github.com/b3log/wide/i18n" "github.com/b3log/wide/user" + "github.com/b3log/wide/util" "github.com/golang/glog" "github.com/gorilla/websocket" ) @@ -33,16 +31,9 @@ type Notification struct { Message string `json:"message"` } -// 一个用户会话的 WebSocket 通道结构. -type WSChannel struct { - Conn *websocket.Conn // WebSocket 连接 - Request *http.Request // 关联的 HTTP 请求 - Time time.Time // 该通道最近一次使用时间 -} - // 通知通道. -// -var notificationWSs = map[string]*WSChannel{} +// +var notificationWSs = map[string]*util.WSChannel{} // 用户事件处理:将事件转为通知,并通过通知通道推送给前端. // 当用户事件队列接收到事件时将会调用该函数进行处理. @@ -69,14 +60,17 @@ func event2Notification(e *event.Event) { notification.Message = i18n.Get(wsChannel.Request, "notification_"+strconv.Itoa(e.Code)).(string) wsChannel.Conn.WriteJSON(¬ification) + + wsChannel.Time = time.Now() } +// 建立通知通道. func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") sid := session.Values["id"].(string) conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) - wsChan := WSChannel{Conn: conn, Request: r, Time: time.Now()} + wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} notificationWSs[sid] = &wsChan @@ -114,43 +108,3 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { } } } - -func pipeCommands(username string, commands ...*exec.Cmd) string { - for i, command := range commands[:len(commands)-1] { - setCmdEnv(command, username) - - stdout, err := command.StdoutPipe() - if nil != err { - return err.Error() - } - - command.Start() - - commands[i+1].Stdin = stdout - } - - last := commands[len(commands)-1] - setCmdEnv(last, username) - - out, err := last.CombinedOutput() - - if err != nil { - return err.Error() - } - - return string(out) -} - -func setCmdEnv(cmd *exec.Cmd, username string) { - userWorkspace := conf.Wide.GetUserWorkspace(username) - - cmd.Env = append(cmd.Env, - "TERM="+os.Getenv("TERM"), - "GOPATH="+userWorkspace, - "GOOS="+runtime.GOOS, - "GOARCH="+runtime.GOARCH, - "GOROOT="+runtime.GOROOT(), - "PATH="+os.Getenv("PATH")) - - cmd.Dir = userWorkspace -} diff --git a/output/outputs.go b/output/outputs.go index 38be5aa..bdc187e 100644 --- a/output/outputs.go +++ b/output/outputs.go @@ -11,6 +11,7 @@ import ( "runtime" "strconv" "strings" + "time" "github.com/b3log/wide/conf" "github.com/b3log/wide/user" @@ -19,16 +20,22 @@ import ( "github.com/gorilla/websocket" ) -var outputWS = map[string]*websocket.Conn{} +// 输出通道. +// +var outputWS = map[string]*util.WSChannel{} +// 建立输出通道. func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") sid := session.Values["id"].(string) - outputWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) + conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) + wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} + + outputWS[sid] = &wsChan ret := map[string]interface{}{"output": "Ouput initialized", "cmd": "init-output"} - outputWS[sid].WriteJSON(&ret) + wsChan.Conn.WriteJSON(&ret) glog.V(4).Infof("Open a new [Output] with session [%s], %d", sid, len(outputWS)) } @@ -96,7 +103,9 @@ func RunHandler(w http.ResponseWriter, r *http.Request) { channelRet["cmd"] = "run" if nil != outputWS[sid] { - err := outputWS[sid].WriteJSON(&channelRet) + wsChannel := outputWS[sid] + + err := wsChannel.Conn.WriteJSON(&channelRet) if nil != err { glog.Error(err) break @@ -250,7 +259,8 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { if nil != outputWS[sid] { glog.V(3).Infof("Session [%s] 's build [id=%d, file=%s] has done", sid, runningId, filePath) - err := outputWS[sid].WriteJSON(&channelRet) + wsChannel := outputWS[sid] + err := wsChannel.Conn.WriteJSON(&channelRet) if nil != err { glog.Error(err) } @@ -371,7 +381,8 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) { if nil != outputWS[sid] { glog.V(3).Infof("Session [%s] 's running [go install] [id=%d, dir=%s] has done", sid, runningId, curDir) - err := outputWS[sid].WriteJSON(&channelRet) + wsChannel := outputWS[sid] + err := wsChannel.Conn.WriteJSON(&channelRet) if nil != err { glog.Error(err) } @@ -447,7 +458,9 @@ func GoGetHandler(w http.ResponseWriter, r *http.Request) { channelRet["cmd"] = "go get" if nil != outputWS[sid] { - err := outputWS[sid].WriteJSON(&channelRet) + wsChannel := outputWS[sid] + + err := wsChannel.Conn.WriteJSON(&channelRet) if nil != err { glog.Error(err) break diff --git a/shell/shells.go b/shell/shells.go index 0516eef..2baed54 100644 --- a/shell/shells.go +++ b/shell/shells.go @@ -10,16 +10,21 @@ import ( "runtime" "strconv" "strings" + "time" "github.com/b3log/wide/conf" "github.com/b3log/wide/i18n" "github.com/b3log/wide/user" + "github.com/b3log/wide/util" "github.com/golang/glog" "github.com/gorilla/websocket" ) -var shellWS = map[string]*websocket.Conn{} +// Shell 通道. +// > +var shellWS = map[string]*util.WSChannel{} +// Shell 首页. func IndexHandler(w http.ResponseWriter, r *http.Request) { i18n.Load() @@ -53,22 +58,26 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } +// 建立 Shell 通道. func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") username := session.Values["username"].(string) sid := session.Values["id"].(string) - shellWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) + conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) + wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} + + shellWS[sid] = &wsChan ret := map[string]interface{}{"output": "Shell initialized", "cmd": "init-shell"} - shellWS[sid].WriteJSON(&ret) + wsChan.Conn.WriteJSON(&ret) glog.Infof("Open a new [Shell] with session [%s], %d", sid, len(shellWS)) input := map[string]interface{}{} for { - if err := shellWS[sid].ReadJSON(&input); err != nil { + if err := wsChan.Conn.ReadJSON(&input); err != nil { if err.Error() == "EOF" { return } @@ -104,7 +113,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { ret = map[string]interface{}{"output": output, "cmd": "shell-output"} - if err := shellWS[sid].WriteJSON(&ret); err != nil { + if err := wsChan.Conn.WriteJSON(&ret); err != nil { glog.Error("Shell WS ERROR: " + err.Error()) return } diff --git a/util/websocket.go b/util/websocket.go new file mode 100644 index 0000000..475de5c --- /dev/null +++ b/util/websocket.go @@ -0,0 +1,16 @@ +package util + +import ( + "net/http" + "time" + + "github.com/gorilla/websocket" +) + +// 一个用户会话的 WebSocket 通道结构. +type WSChannel struct { + Sid string // 用户会话 id + Conn *websocket.Conn // WebSocket 连接 + Request *http.Request // 关联的 HTTP 请求 + Time time.Time // 该通道最近一次使用时间 +}