wide/main.go

233 lines
5.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"encoding/json"
"flag"
"html/template"
"math/rand"
"net/http"
"runtime"
"strconv"
"github.com/b3log/wide/conf"
"github.com/b3log/wide/editor"
"github.com/b3log/wide/event"
"github.com/b3log/wide/file"
"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/util"
"github.com/golang/glog"
)
// Wide 中唯一一个 init 函数.
func init() {
// TODO:默认启动参数
flag.Set("logtostderr", "true")
flag.Set("v", "3")
flag.Parse()
// 加载事件处理
event.Load()
// 加载配置
conf.Load()
// 定时检查运行环境
conf.FixedTimeCheckEnv()
// 定时保存配置
conf.FixedTimeSave()
// 定时检查无效会话
session.FixedTimeRelease()
}
// 登录.
func loginHandler(w http.ResponseWriter, r *http.Request) {
i18n.Load()
if r.Method == "GET" {
// 展示登录页面
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r)}
t, err := template.ParseFiles("view/login.html")
if nil != err {
glog.Error(err)
http.Error(w, err.Error(), 500)
return
}
t.Execute(w, model)
return
}
// 非 GET 请求当作是登录请求
succ := false
data := map[string]interface{}{"succ": &succ}
defer util.RetJSON(w, r, data)
args := struct {
Username string
Password string
}{}
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
glog.Error(err)
succ = true
return
}
for _, user := range conf.Wide.Users {
if user.Name == args.Username && user.Password == args.Password {
succ = true
}
}
if !succ {
return
}
// 创建 HTTP 会话
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
httpSession.Values["username"] = args.Username
httpSession.Values["id"] = strconv.Itoa(rand.Int())
httpSession.Options.MaxAge = 60 * 60 * 24 // 一天过期
httpSession.Save(r, w)
glog.Infof("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), args.Username)
}
// Wide 首页.
func indexHandler(w http.ResponseWriter, r *http.Request) {
i18n.Load()
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
if httpSession.IsNew {
http.Redirect(w, r, "/login", http.StatusForbidden)
return
}
httpSession.Save(r, w)
// 创建一个 Wide 会话
wideSession := session.WideSessions.New(httpSession)
username := httpSession.Values["username"].(string)
wideSessions := session.WideSessions.GetByUsername(username)
userConf := conf.Wide.GetUser(username)
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r),
"session": wideSession, "latestSessionContent": userConf.LatestSessionContent}
glog.V(3).Infof("User [%s] has [%d] sessions", username, len(wideSessions))
t, err := template.ParseFiles("view/index.html")
if nil != err {
glog.Error(err)
http.Error(w, err.Error(), 500)
return
}
t.Execute(w, model)
}
// favicon.ico 请求处理.
func faviconHandler(w http.ResponseWriter, r *http.Request) {
// TODO: favicon.ico 请求处理.
}
// 主程序入口.
func main() {
runtime.GOMAXPROCS(conf.Wide.MaxProcs)
defer glog.Flush()
// 静态资源
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
http.HandleFunc("/favicon.ico", panicRecover(faviconHandler))
// 库资源
http.Handle("/data/", http.StripPrefix("/data/", http.FileServer(http.Dir("data"))))
// IDE
http.HandleFunc("/login", panicRecover(loginHandler))
http.HandleFunc("/", panicRecover(indexHandler))
// 会话
http.HandleFunc("/session/ws", panicRecover(session.WSHandler))
http.HandleFunc("/session/save", panicRecover(session.SaveContent))
// 运行相关
http.HandleFunc("/build", panicRecover(output.BuildHandler))
http.HandleFunc("/run", panicRecover(output.RunHandler))
http.HandleFunc("/stop", panicRecover(output.StopHandler))
http.HandleFunc("/go/get", panicRecover(output.GoGetHandler))
http.HandleFunc("/go/install", panicRecover(output.GoInstallHandler))
http.HandleFunc("/output/ws", panicRecover(output.WSHandler))
// 文件树
http.HandleFunc("/files", panicRecover(file.GetFiles))
http.HandleFunc("/file", panicRecover(file.GetFile))
http.HandleFunc("/file/save", panicRecover(file.SaveFile))
http.HandleFunc("/file/new", panicRecover(file.NewFile))
http.HandleFunc("/file/remove", panicRecover(file.RemoveFile))
// 编辑器
http.HandleFunc("/editor/ws", panicRecover(editor.WSHandler))
http.HandleFunc("/go/fmt", panicRecover(editor.GoFmtHandler))
http.HandleFunc("/autocomplete", panicRecover(editor.AutocompleteHandler))
http.HandleFunc("/find/decl", panicRecover(editor.FindDeclarationHandler))
http.HandleFunc("/find/usages", panicRecover(editor.FindUsagesHandler))
http.HandleFunc("/html/fmt", panicRecover(editor.HTMLFmtHandler))
http.HandleFunc("/json/fmt", panicRecover(editor.JSONFmtHandler))
// Shell
http.HandleFunc("/shell/ws", panicRecover(shell.WSHandler))
http.HandleFunc("/shell", panicRecover(shell.IndexHandler))
// 通知
http.HandleFunc("/notification/ws", panicRecover(notification.WSHandler))
// 用户
http.HandleFunc("/user/new", panicRecover(session.AddUser))
http.HandleFunc("/user/repos/init", panicRecover(session.InitGitRepos))
// 文档
http.Handle("/doc/", http.StripPrefix("/doc/", http.FileServer(http.Dir("doc"))))
glog.V(0).Infof("Wide is running [%s]", conf.Wide.Server)
err := http.ListenAndServe(conf.Wide.Server, nil)
if err != nil {
glog.Fatal(err)
}
}
// 包装 HTTP Handler 函数recover panic.
func panicRecover(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
glog.Errorf("PANIC RECOVERED: %v", r)
}
}()
// Handler 处理
f(w, r)
}
}