iedc-go/application.go

310 lines
7.3 KiB
Go
Raw Normal View History

2017-08-17 02:14:59 +00:00
package hotime
import (
"bytes"
"database/sql"
"encoding/json"
2017-10-13 09:52:34 +00:00
"fmt"
2017-08-17 02:14:59 +00:00
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
)
type Application struct {
Router
2017-08-23 07:35:49 +00:00
contextBase
2017-08-17 02:14:59 +00:00
Port string //端口号
2017-08-22 08:24:55 +00:00
connectListener []func(this *Context) bool //所有的访问监听,true按原计划继续使用false表示有监听器处理
2017-08-17 02:14:59 +00:00
connectDbFunc func(err ...*Error) *sql.DB
configPath string
Config Map
Db HoTimeDB
2017-10-27 04:28:47 +00:00
Server *http.Server
2017-08-17 02:14:59 +00:00
CacheIns
sessionLong CacheIns
sessionShort CacheIns
2017-10-27 04:28:47 +00:00
http.Handler
}
func (this *Application) ServeHTTP(w http.ResponseWriter, req *http.Request) {
this.handler(w, req)
2017-08-17 02:14:59 +00:00
}
//启动实例
func (this *Application) Run(router Router) {
2018-04-03 17:54:27 +00:00
2017-08-17 02:14:59 +00:00
this.Router = router
//this.Port = port
this.Port = this.Config.GetString("port")
2017-10-30 08:23:42 +00:00
if this.connectDbFunc != nil && (this.Db.DB==nil||this.Db.DB.Ping() != nil) {
2017-08-17 02:14:59 +00:00
this.Db.SetConnect(this.connectDbFunc)
}
if this.CacheIns == nil {
this.CacheIns = CacheIns(&CacheMemory{Map: Map{}, Time: this.Config.GetInt64("cacheShortTime")})
}
2017-10-13 09:52:34 +00:00
//异常处理
defer func() {
if err := recover(); err != nil {
//e.SetError(errors.New(ObjToStr(err)), LOG_FMT)
fmt.Println(err)
this.Run(router)
}
}()
2017-10-27 04:28:47 +00:00
this.Server = &http.Server{}
if !IsRun {
IsRun = true
}
App[this.Port] = this
this.Server.Handler = this
//启动服务
this.Server.Addr = ":" + this.Port
this.Server.ListenAndServe()
2017-08-17 02:14:59 +00:00
}
//启动实例
func (this *Application) SetConnectDB(connect func(err ...*Error) *sql.DB) {
this.connectDbFunc = connect
2017-10-24 01:31:20 +00:00
this.Db.SetConnect(this.connectDbFunc)
2017-08-17 02:14:59 +00:00
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetSession(short CacheIns, Long CacheIns) {
this.sessionLong = Long
this.sessionShort = short
}
//默认配置缓存和session实现
func (this *Application) SetDefault(connect func(err ...*Error) *sql.DB) {
this.SetConfig()
this.connectDbFunc = connect
2017-10-27 04:28:47 +00:00
if this.connectDbFunc != nil {
2017-10-24 01:31:20 +00:00
this.Db.SetConnect(this.connectDbFunc)
}
2017-08-17 02:14:59 +00:00
//防止手动设置缓存误伤
if this.CacheIns == nil {
this.SetCache(CacheIns(&CacheMemory{}))
}
//防止手动设置session误伤
if this.sessionShort == nil && this.sessionLong == nil {
if this.connectDbFunc == nil {
this.SetSession(CacheIns(&CacheMemory{}), nil)
} else {
this.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &this.Db, Time: this.Config.GetInt64("cacheLongTime")}))
}
}
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetCache(cache CacheIns) {
this.CacheIns = cache
}
//设置配置文件路径全路径或者相对路径
func (this *Application) SetConfig(configPath ...string) {
if len(configPath) != 0 {
this.configPath = configPath[0]
}
if this.configPath == "" {
this.configPath = "config/config.json"
}
//加载配置文件
btes, err := ioutil.ReadFile(this.configPath)
this.Config = DeepCopyMap(Config).(Map)
if err == nil {
cmap := Map{}
//文件是否损坏
cmap.JsonToMap(string(btes), &this.Error)
for k, v := range cmap {
this.Config.Put(k, v)
}
}
//else {
// //文件不存在则写入文件,存在不做处理
// var out bytes.Buffer
// err = json.Indent(&out, []byte(this.Config.ToJsonString()), "", "\t")
// os.MkdirAll(filepath.Dir(this.configPath), os.ModeDir)
// os.Create(this.configPath)
// err = ioutil.WriteFile(this.configPath, out.Bytes(), os.ModeApplicationend)
// if err != nil {
// this.Error.SetError(err)
// }
//}
//文件如果损坏则不写入配置防止配置文件数据丢失
if this.Error.GetError() == nil {
var out bytes.Buffer
err = json.Indent(&out, []byte(this.Config.ToJsonString()), "", "\t")
err = ioutil.WriteFile(this.configPath, out.Bytes(), os.ModeAppend)
if err != nil {
os.MkdirAll(filepath.Dir(this.configPath), os.ModeDir)
os.Create(this.configPath)
err = ioutil.WriteFile(this.configPath, out.Bytes(), os.ModeAppend)
if err != nil {
this.Error.SetError(err)
}
}
} else {
this.Error.SetError(nil)
}
}
//连接判断,返回true继续传输至控制层false则停止传输
2017-08-22 08:24:55 +00:00
func (this *Application) SetConnectListener(lis func(this *Context) bool) {
this.connectListener = append(this.connectListener, lis)
2017-08-17 02:14:59 +00:00
}
//网络错误
2018-04-03 17:54:27 +00:00
//func (this *Application) session(w http.ResponseWriter, req *http.Request) {
//
//}
2017-08-17 02:14:59 +00:00
2017-08-22 08:24:55 +00:00
//序列化链接
func (this *Application) urlSer(url string) (string, []string) {
q := strings.Index(url, "?")
2017-08-17 02:14:59 +00:00
if q == -1 {
2017-08-22 08:24:55 +00:00
q = len(url)
2017-08-17 02:14:59 +00:00
}
2017-08-22 08:24:55 +00:00
o := Substr(url, 0, q)
2017-08-17 02:14:59 +00:00
r := strings.SplitN(o, "/", -1)
var s = make([]string, 0)
for i := 0; i < len(r); i++ {
if !strings.EqualFold("", r[i]) {
s = append(s, r[i])
}
}
2017-08-22 08:24:55 +00:00
return o, s
}
//访问
func (this *Application) handler(w http.ResponseWriter, req *http.Request) {
o, s := this.urlSer(req.RequestURI)
//获取cookie
// 如果cookie存在直接将sessionId赋值为cookie.Value
// 如果cookie不存在就查找传入的参数中是否有token
// 如果token不存在就生成随机的sessionId
// 如果token存在就判断token是否在Session中有保存
// 如果有取出token并复制给cookie
// 没有保存就生成随机的session
2017-10-27 04:28:47 +00:00
cookie, err := req.Cookie((this.Config["sessionName"]).(string))
2017-08-22 08:24:55 +00:00
sessionId := Md5(strconv.Itoa(Rand(10)))
token := req.FormValue("token")
//isFirst:=false
if err != nil || (len(token) == 32 && cookie.Value != token) {
if len(token) == 32 {
sessionId = token
}
//else{
// isFirst=true;
//}
2017-10-27 04:28:47 +00:00
http.SetCookie(w, &http.Cookie{Name: this.Config["sessionName"].(string), Value: sessionId, Path: "/"})
2017-08-22 08:24:55 +00:00
} else {
sessionId = cookie.Value
}
2017-08-17 02:14:59 +00:00
2017-08-22 08:24:55 +00:00
//访问实例
context := Context{SessionIns: SessionIns{SessionId: sessionId,
LongCache: this.sessionLong,
ShortCache: this.sessionShort,
},
CacheIns: this.CacheIns,
Resp: w, Req: req, Application: this, RouterString: s, Config: this.Config, Db: &this.Db, HandlerStr: req.RequestURI}
2017-10-11 09:45:22 +00:00
//header默认设置
header := w.Header()
2017-10-12 02:07:51 +00:00
header.Set("Content-Type", "text/html; charset=utf-8")
2017-08-22 08:24:55 +00:00
//访问拦截true继续false暂停
2017-10-11 09:45:22 +00:00
connectListenerLen := len(this.connectListener)
if connectListenerLen != 0 {
2017-08-22 08:24:55 +00:00
for i := 0; i < connectListenerLen; i++ {
if !this.connectListener[i](&context) {
2017-10-12 02:07:51 +00:00
2017-08-22 08:24:55 +00:00
context.View()
return
}
}
}
o, s = this.urlSer(context.HandlerStr)
context.RouterString = s
2017-08-17 02:14:59 +00:00
//接口服务
if len(s) == 3 {
//如果满足规则则路由到对应控制器去
if this.Router[s[0]] != nil && this.Router[s[0]][s[1]] != nil && this.Router[s[0]][s[1]][s[2]] != nil {
//控制层
this.Router[s[0]][s[1]][s[2]](&context)
2017-10-12 02:07:51 +00:00
//header.Set("Content-Type", "text/html; charset=utf-8")
2017-08-17 02:14:59 +00:00
context.View()
return
}
}
//url赋值
2017-10-27 04:28:47 +00:00
path := this.Config.GetString("tpt") + o
2017-08-17 02:14:59 +00:00
//判断是否为默认
if path[len(path)-1] == '/' {
2017-10-27 04:28:47 +00:00
defFile := this.Config.GetSlice("defFile")
2017-08-17 02:14:59 +00:00
for i := 0; i < len(defFile); i++ {
2017-10-27 04:28:47 +00:00
temp := path + defFile.GetString(i)
2017-08-17 02:14:59 +00:00
_, err := os.Stat(temp)
if err == nil {
path = temp
break
}
}
if path[len(path)-1] == '/' {
w.WriteHeader(404)
return
}
}
if strings.Contains(path, "/.") {
w.WriteHeader(404)
return
}
2017-10-12 02:07:51 +00:00
//设置header
mimeStr := Substr(path, strings.LastIndex(path, "."), len(path))
2017-10-12 03:19:44 +00:00
2017-10-11 09:45:22 +00:00
//类型判断并设置Content-Type
2017-10-12 02:07:51 +00:00
if value, ok := mimeMaps[mimeStr]; ok {
header.Set("Content-Type", value)
2017-08-17 02:14:59 +00:00
}
2017-10-12 02:07:51 +00:00
2017-08-17 02:14:59 +00:00
header.Set("Cache-Control", "public")
//w.Write(data)
http.ServeFile(w, req, path)
}