This commit is contained in:
parent
5d2497063f
commit
7ec8a77005
128
conf/wide.go
128
conf/wide.go
|
@ -1,4 +1,4 @@
|
|||
// Wide 配置相关,所有配置(包括用户配置)都是保存在 wide.json 中.
|
||||
// Configurations manipulations, all configurations (including user configurations) are stored in wide.json.
|
||||
package conf
|
||||
|
||||
import (
|
||||
|
@ -18,60 +18,60 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
PathSeparator = string(os.PathSeparator) // 系统文件路径分隔符
|
||||
PathListSeparator = string(os.PathListSeparator) // 系统路径列表分隔符
|
||||
PathSeparator = string(os.PathSeparator) // OS-specific path separator
|
||||
PathListSeparator = string(os.PathListSeparator) // OS-specific path list separator
|
||||
|
||||
)
|
||||
|
||||
// 最后一次会话内容结构.
|
||||
// The latest session content.
|
||||
type LatestSessionContent struct {
|
||||
FileTree []string // 文件树展开的路径集
|
||||
Files []string // 编辑器打开的文件路径集
|
||||
CurrentFile string // 当前编辑器文件路径
|
||||
FileTree []string // paths of expanding nodes of file tree
|
||||
Files []string // paths of files of opening editor tabs
|
||||
CurrentFile string // path of file of the current focused editor tab
|
||||
}
|
||||
|
||||
// 用户结构.
|
||||
// User.
|
||||
type User struct {
|
||||
Name string
|
||||
Password string
|
||||
Workspace string // 该用户的工作空间 GOPATH 路径
|
||||
Workspace string // the GOPATH of this user
|
||||
Locale string
|
||||
GoFormat string
|
||||
LatestSessionContent *LatestSessionContent
|
||||
}
|
||||
|
||||
// 配置结构.
|
||||
// Configuration.
|
||||
type conf struct {
|
||||
Server string // 服务地址({IP}:7070)
|
||||
StaticServer string // 静态资源服务地址(http://{IP}:7070)
|
||||
EditorChannel string // 编辑器通道地址(ws://{IP}:7070)
|
||||
OutputChannel string // 输出窗口通道地址(ws://{IP}:7070)
|
||||
ShellChannel string // Shell 通道地址(ws://{IP}:7070)
|
||||
SessionChannel string // Wide 会话通道地址(ws://{IP}:7070)
|
||||
HTTPSessionMaxAge int // HTTP 会话失效时间(秒)
|
||||
StaticResourceVersion string // 静态资源版本
|
||||
MaxProcs int // 并发执行数
|
||||
RuntimeMode string // 运行模式
|
||||
Pwd string // 工作目录
|
||||
Workspace string // 主工作空间 GOPATH 路径
|
||||
Locale string // 默认的区域
|
||||
Users []*User // 用户集
|
||||
Server string // server host and port ({IP}:7070)
|
||||
StaticServer string // static resources server scheme, host and port (http://{IP}:7070)
|
||||
EditorChannel string // editor channel (ws://{IP}:7070)
|
||||
OutputChannel string // output channel (ws://{IP}:7070)
|
||||
ShellChannel string // shell channel(ws://{IP}:7070)
|
||||
SessionChannel string // wide session channel (ws://{IP}:7070)
|
||||
HTTPSessionMaxAge int // HTTP session max age (in seciond)
|
||||
StaticResourceVersion string // version of static resources
|
||||
MaxProcs int // Go max procs
|
||||
RuntimeMode string // runtime mode (dev/prod)
|
||||
Pwd string // current working direcitory
|
||||
Workspace string // path of master workspace
|
||||
Locale string // default locale
|
||||
Users []*User // configurations of users
|
||||
}
|
||||
|
||||
// 配置.
|
||||
// Configuration variable.
|
||||
var Wide conf
|
||||
|
||||
// 维护非变化部分的配置.
|
||||
// A raw copy of configuration variable.
|
||||
//
|
||||
// 只有 Users 是会运行时变化的,保存回写文件时要使用这个变量.
|
||||
// Save function will use this variable to persist.
|
||||
var rawWide conf
|
||||
|
||||
// 定时检查 Wide 运行环境.
|
||||
// FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes).
|
||||
//
|
||||
// 如果是特别严重的问题(比如 $GOPATH 不存在)则退出进程,另一些不太严重的问题(比如 gocode 不存在)则放入全局通知队列.
|
||||
// Exits process if found fatal issues (such as not found $GOPATH),
|
||||
// Notifies user by notification queue if found warning issues (such as not found gocode).
|
||||
func FixedTimeCheckEnv() {
|
||||
go func() {
|
||||
// 7 分钟进行一次检查环境
|
||||
for _ = range time.Tick(time.Minute * 7) {
|
||||
if "" == os.Getenv("GOPATH") {
|
||||
glog.Fatal("Not found $GOPATH")
|
||||
|
@ -106,9 +106,9 @@ func FixedTimeCheckEnv() {
|
|||
}()
|
||||
}
|
||||
|
||||
// 定时(1 分钟)保存配置.
|
||||
// FixedTimeSave saves configurations (wide.json) periodically (1 minute).
|
||||
//
|
||||
// 主要目的是保存用户会话内容,以备下一次用户打开 Wide 时进行会话还原.
|
||||
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
||||
func FixedTimeSave() {
|
||||
go func() {
|
||||
// 1 分钟进行一次配置保存
|
||||
|
@ -118,11 +118,12 @@ func FixedTimeSave() {
|
|||
}()
|
||||
}
|
||||
|
||||
// 获取 username 指定的用户的工作空间路径,查找不到时返回空字符串.
|
||||
// GetUserWorkspace gets workspace path with the specified username, returns "" if not found.
|
||||
func (c *conf) GetUserWorkspace(username string) string {
|
||||
for _, user := range c.Users {
|
||||
if user.Name == username {
|
||||
ret := strings.Replace(user.Workspace, "{pwd}", c.Pwd, 1)
|
||||
|
||||
return filepath.FromSlash(ret)
|
||||
}
|
||||
}
|
||||
|
@ -130,16 +131,16 @@ func (c *conf) GetUserWorkspace(username string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// 获取主工作空间路径.
|
||||
// GetWorkspace gets the master workspace path.
|
||||
//
|
||||
// 相比起使用 Wide.Workspace,该函数会做如下处理:
|
||||
// 1. 替换里面的 {pwd} 变量为实际的目录路径
|
||||
// 2. 把 / 替换为 \\ (Windows)
|
||||
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
||||
// 1. Replace {pwd} variable with the actual directory path
|
||||
// 2. Replace "/" with "\\" (Windows)
|
||||
func (c *conf) GetWorkspace() string {
|
||||
return filepath.FromSlash(strings.Replace(c.Workspace, "{pwd}", c.Pwd, 1))
|
||||
}
|
||||
|
||||
// 获取 username 指定的用户的 Go 源码格式化工具路径,查找不到时返回 "gofmt".
|
||||
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found.
|
||||
func (c *conf) GetGoFmt(username string) string {
|
||||
for _, user := range c.Users {
|
||||
if user.Name == username {
|
||||
|
@ -158,16 +159,16 @@ func (c *conf) GetGoFmt(username string) string {
|
|||
return "gofmt"
|
||||
}
|
||||
|
||||
// 获取用户的工作空间路径.
|
||||
// GetWorkspace gets workspace path of the user.
|
||||
//
|
||||
// 相比起使用 User.Workspace,该函数会做如下处理:
|
||||
// 1. 替换里面的 {pwd} 变量为实际的目录路径
|
||||
// 2. 把 / 替换为 \\ (Windows)
|
||||
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
||||
// 1. Replace {pwd} variable with the actual directory path
|
||||
// 2. Replace "/" with "\\" (Windows)
|
||||
func (u *User) GetWorkspace() string {
|
||||
return filepath.FromSlash(strings.Replace(u.Workspace, "{pwd}", Wide.Pwd, 1))
|
||||
}
|
||||
|
||||
// 获取 username 指定的用户配置.
|
||||
// GetUser gets configuration of the user specified by the given username, returns nil if not found.
|
||||
func (*conf) GetUser(username string) *User {
|
||||
for _, user := range Wide.Users {
|
||||
if user.Name == username {
|
||||
|
@ -178,9 +179,9 @@ func (*conf) GetUser(username string) *User {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 获取 GOBIN 中 executable 指定的文件路径.
|
||||
// GetExecutableInGOBIN gets executable file under GOBIN path.
|
||||
//
|
||||
// 函数内部会判断操作系统,如果是 Windows 则在 executable 实参后加入 .exe 后缀.
|
||||
// The specified executable should not with extension, this function will append .exe if on Windows.
|
||||
func (*conf) GetExecutableInGOBIN(executable string) string {
|
||||
if util.OS.IsWindows() {
|
||||
executable += ".exe"
|
||||
|
@ -214,12 +215,12 @@ func (*conf) GetExecutableInGOBIN(executable string) string {
|
|||
return os.Getenv("GOBIN") + PathSeparator + executable
|
||||
}
|
||||
|
||||
// 保存 Wide 配置.
|
||||
// Save saves Wide configurations.
|
||||
func Save() bool {
|
||||
// 只有 Users 是会运行时变化的,其他属性只能手工维护 wide.json 配置文件
|
||||
// just the Users field are volatile
|
||||
rawWide.Users = Wide.Users
|
||||
|
||||
// 原始配置文件内容
|
||||
// format
|
||||
bytes, err := json.MarshalIndent(rawWide, "", " ")
|
||||
|
||||
if nil != err {
|
||||
|
@ -237,7 +238,7 @@ func Save() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// 加载 Wide 配置.
|
||||
// Load loads the configurations from wide.json.
|
||||
func Load() {
|
||||
bytes, _ := ioutil.ReadFile("conf/wide.json")
|
||||
|
||||
|
@ -248,7 +249,7 @@ func Load() {
|
|||
os.Exit(-1)
|
||||
}
|
||||
|
||||
// 保存未经变量替换处理的原始配置文件,用于写回时
|
||||
// keep the raw content
|
||||
json.Unmarshal(bytes, &rawWide)
|
||||
|
||||
ip, err := util.Net.LocalIP()
|
||||
|
@ -275,9 +276,9 @@ func Load() {
|
|||
initWorkspaceDirs()
|
||||
}
|
||||
|
||||
// 初始化主工作空间、各个用户的工作空间目录.
|
||||
// initWorkspaceDirs initializes the directories of master workspace, users' workspaces.
|
||||
//
|
||||
// 如果不存在 Workspace 配置所指定的目录路径则创建该目录.
|
||||
// Creates directories if not found on path of workspace.
|
||||
func initWorkspaceDirs() {
|
||||
paths := filepath.SplitList(Wide.GetWorkspace())
|
||||
|
||||
|
@ -291,27 +292,20 @@ func initWorkspaceDirs() {
|
|||
}
|
||||
}
|
||||
|
||||
// 在 path 指定的路径下创建工作空间目录.
|
||||
// createWorkspaceDir creates directories on the path.
|
||||
//
|
||||
// 1. 根目录:{path}
|
||||
// 2. 源码目录:{path}/src
|
||||
// 3. 包目录:{path}/pkg
|
||||
// 4. 可执行文件目录:{path}/bin
|
||||
// 1. root directory:{path}
|
||||
// 2. src directory: {path}/src
|
||||
// 3. package directory: {path}/pkg
|
||||
// 4. binary directory: {path}/bin
|
||||
func createWorkspaceDir(path string) {
|
||||
// {path}, workspace root
|
||||
createDir(path)
|
||||
|
||||
// {path}/src
|
||||
createDir(path + PathSeparator + "src")
|
||||
|
||||
// {path}/pkg
|
||||
createDir(path + PathSeparator + "pkg")
|
||||
|
||||
// {path}/bin
|
||||
createDir(path + PathSeparator + "bin")
|
||||
}
|
||||
|
||||
// 在 path 指定的路径下不存在目录或文件则创建目录.
|
||||
// createDir creates a directory on the path if it not exists.
|
||||
func createDir(path string) {
|
||||
if !isExist(path) {
|
||||
if err := os.MkdirAll(path, 0775); nil != err {
|
||||
|
@ -324,9 +318,7 @@ func createDir(path string) {
|
|||
}
|
||||
}
|
||||
|
||||
// 检查文件或目录是否存在.
|
||||
//
|
||||
// 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false.
|
||||
// isExist determines whether the file spcified by the given filename is exists.
|
||||
func isExist(filename string) bool {
|
||||
_, err := os.Stat(filename)
|
||||
|
||||
|
|
81
main.go
81
main.go
|
@ -25,37 +25,30 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
Ver = "1.0.1" // Wide 版本
|
||||
CodeMirrorVer = "4.7" // 编辑器版本
|
||||
Ver = "1.0.1" // wide version
|
||||
CodeMirrorVer = "4.7" // editor version
|
||||
)
|
||||
|
||||
// Wide 中唯一一个 init 函数.
|
||||
// The only one init function in Wide.
|
||||
func init() {
|
||||
// TODO: 默认启动参数
|
||||
// TODO: args
|
||||
flag.Set("logtostderr", "true")
|
||||
flag.Set("v", "3")
|
||||
flag.Parse()
|
||||
|
||||
// 加载事件处理
|
||||
event.Load()
|
||||
|
||||
// 加载配置
|
||||
conf.Load()
|
||||
|
||||
// 定时检查运行环境
|
||||
conf.FixedTimeCheckEnv()
|
||||
|
||||
// 定时保存配置
|
||||
conf.FixedTimeSave()
|
||||
|
||||
// 定时检查无效会话
|
||||
session.FixedTimeRelease()
|
||||
}
|
||||
|
||||
// 登录.
|
||||
// loginHandler handles request of user login.
|
||||
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if "GET" == r.Method {
|
||||
// 展示登录页面
|
||||
// show the login page
|
||||
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale),
|
||||
"locale": conf.Wide.Locale, "ver": Ver}
|
||||
|
@ -74,7 +67,8 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// 非 GET 请求当作是登录请求
|
||||
// non-GET request as login request
|
||||
|
||||
succ := false
|
||||
|
||||
data := map[string]interface{}{"succ": &succ}
|
||||
|
@ -102,7 +96,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// 创建 HTTP 会话
|
||||
// create a HTTP session
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
httpSession.Values["username"] = args.Username
|
||||
httpSession.Values["id"] = strconv.Itoa(rand.Int())
|
||||
|
@ -112,7 +106,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
glog.Infof("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), args.Username)
|
||||
}
|
||||
|
||||
// 退出(登出).
|
||||
// logoutHandler handles request of user logout (exit).
|
||||
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{"succ": true}
|
||||
defer util.RetJSON(w, r, data)
|
||||
|
@ -123,7 +117,7 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Save(r, w)
|
||||
}
|
||||
|
||||
// Wide 首页.
|
||||
// indexHandler handles request of Wide index.
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
|
@ -136,7 +130,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge
|
||||
httpSession.Save(r, w)
|
||||
|
||||
// 创建一个 Wide 会话
|
||||
// create a Wide session
|
||||
wideSession := session.WideSessions.New(httpSession)
|
||||
|
||||
username := httpSession.Values["username"].(string)
|
||||
|
@ -163,14 +157,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
t.Execute(w, model)
|
||||
}
|
||||
|
||||
// 单个文件资源请求处理.
|
||||
// serveSingle registers the handler function for the given pattern and filename.
|
||||
func serveSingle(pattern string, filename string) {
|
||||
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, filename)
|
||||
})
|
||||
}
|
||||
|
||||
// 起始页请求处理.
|
||||
// startHandler handles request of start page.
|
||||
func startHandler(w http.ResponseWriter, r *http.Request) {
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
|
@ -202,7 +196,7 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
|
|||
t.Execute(w, model)
|
||||
}
|
||||
|
||||
// 键盘快捷键页请求处理.
|
||||
// keyboardShortcutsHandler handles request of keyboard shortcuts page.
|
||||
func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
|
@ -232,7 +226,7 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
t.Execute(w, model)
|
||||
}
|
||||
|
||||
// 关于页请求处理.
|
||||
// aboutHandle handles request of about page.
|
||||
func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
|
@ -263,7 +257,7 @@ func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
|||
t.Execute(w, model)
|
||||
}
|
||||
|
||||
// 主程序入口.
|
||||
// Main.
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(conf.Wide.MaxProcs)
|
||||
|
||||
|
@ -279,18 +273,18 @@ func main() {
|
|||
http.HandleFunc("/about", handlerWrapper(aboutHandler))
|
||||
http.HandleFunc("/keyboard_shortcuts", handlerWrapper(keyboardShortcutsHandler))
|
||||
|
||||
// 静态资源
|
||||
// static resources
|
||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
serveSingle("/favicon.ico", "./static/favicon.ico")
|
||||
|
||||
// 库资源
|
||||
// workspaces
|
||||
http.Handle("/data/", http.StripPrefix("/data/", http.FileServer(http.Dir("data"))))
|
||||
|
||||
// 会话
|
||||
// session
|
||||
http.HandleFunc("/session/ws", handlerWrapper(session.WSHandler))
|
||||
http.HandleFunc("/session/save", handlerWrapper(session.SaveContent))
|
||||
|
||||
// 运行相关
|
||||
// run
|
||||
http.HandleFunc("/build", handlerWrapper(output.BuildHandler))
|
||||
http.HandleFunc("/run", handlerWrapper(output.RunHandler))
|
||||
http.HandleFunc("/stop", handlerWrapper(output.StopHandler))
|
||||
|
@ -299,7 +293,7 @@ func main() {
|
|||
http.HandleFunc("/go/install", handlerWrapper(output.GoInstallHandler))
|
||||
http.HandleFunc("/output/ws", handlerWrapper(output.WSHandler))
|
||||
|
||||
// 文件树
|
||||
// file tree
|
||||
http.HandleFunc("/files", handlerWrapper(file.GetFiles))
|
||||
http.HandleFunc("/file", handlerWrapper(file.GetFile))
|
||||
http.HandleFunc("/file/save", handlerWrapper(file.SaveFile))
|
||||
|
@ -307,7 +301,7 @@ func main() {
|
|||
http.HandleFunc("/file/remove", handlerWrapper(file.RemoveFile))
|
||||
http.HandleFunc("/file/search/text", handlerWrapper(file.SearchText))
|
||||
|
||||
// 编辑器
|
||||
// editor
|
||||
http.HandleFunc("/editor/ws", handlerWrapper(editor.WSHandler))
|
||||
http.HandleFunc("/go/fmt", handlerWrapper(editor.GoFmtHandler))
|
||||
http.HandleFunc("/autocomplete", handlerWrapper(editor.AutocompleteHandler))
|
||||
|
@ -317,20 +311,17 @@ func main() {
|
|||
http.HandleFunc("/html/fmt", handlerWrapper(editor.HTMLFmtHandler))
|
||||
http.HandleFunc("/json/fmt", handlerWrapper(editor.JSONFmtHandler))
|
||||
|
||||
// Shell
|
||||
// shell
|
||||
http.HandleFunc("/shell/ws", handlerWrapper(shell.WSHandler))
|
||||
http.HandleFunc("/shell", handlerWrapper(shell.IndexHandler))
|
||||
|
||||
// 通知
|
||||
// notification
|
||||
http.HandleFunc("/notification/ws", handlerWrapper(notification.WSHandler))
|
||||
|
||||
// 用户
|
||||
// user
|
||||
http.HandleFunc("/user/new", handlerWrapper(session.AddUser))
|
||||
http.HandleFunc("/user/repos/init", handlerWrapper(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)
|
||||
|
@ -339,12 +330,11 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
// HTTP Handler 包装,完成共性处理.
|
||||
//
|
||||
// 共性处理:
|
||||
// handlerWrapper wraps the HTTP Handler for some common processes.
|
||||
//
|
||||
// 1. panic recover
|
||||
// 2. 请求计时
|
||||
// 2. request stopwatch
|
||||
// 3. i18n
|
||||
func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
handler := panicRecover(f)
|
||||
handler = stopwatch(handler)
|
||||
|
@ -353,17 +343,16 @@ func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.
|
|||
return handler
|
||||
}
|
||||
|
||||
// 国际化处理包装.
|
||||
// i18nLoad wraps the i18n process.
|
||||
func i18nLoad(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
// Handler 处理
|
||||
handler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler 包装请求计时.
|
||||
// stopwatch wraps the request stopwatch process.
|
||||
func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
@ -372,24 +361,22 @@ func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http
|
|||
glog.V(5).Infof("[%s] [%s]", r.RequestURI, time.Since(start))
|
||||
}()
|
||||
|
||||
// Handler 处理
|
||||
handler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler 包装 recover panic.
|
||||
// panicRecover wraps the panic recover process.
|
||||
func panicRecover(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
defer util.Recover()
|
||||
|
||||
// Handler 处理
|
||||
handler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化 mime.
|
||||
// initMime initializes mime types.
|
||||
//
|
||||
// 有的操作系统(例如 Windows XP)上运行时根据文件后缀获取不到对应的 mime 类型,会导致响应的 HTTP content-type 不正确。
|
||||
// We can't get the mime types on some OS (such as Windows XP) by default, so initializes them here.
|
||||
func initMime() {
|
||||
mime.AddExtensionType(".css", "text/css")
|
||||
mime.AddExtensionType(".js", "application/x-javascript")
|
||||
|
|
Loading…
Reference in New Issue