commit
cb49025e3c
23 changed files with 1430 additions and 0 deletions
-
16.gitignore
-
257README.md
-
43example/app/wstest.go
-
8example/config.json
-
13example/main.go
-
11example/private.json
-
157osmanthuswine.go
-
122src/core/config.go
-
25src/core/controller.go
-
121src/core/db.go
-
36src/core/redis.go
-
117src/core/request.go
-
115src/core/response.go
-
118src/core/router.go
-
51src/core/websocket.go
-
71src/core/xorm.go
-
30src/helper/db2struct.go
-
19src/helper/log.go
-
10src/helper/md5.go
-
8src/helper/uuid.go
-
11src/helper/uuid_test.go
-
21src/interfaces/websocket.go
-
50src/session/securecookie.go
@ -0,0 +1,16 @@ |
|||
# Binaries for programs and plugins |
|||
*.exe |
|||
*.exe~ |
|||
*.dll |
|||
*.so |
|||
*.dylib |
|||
|
|||
# Test binary, build with `go test -c` |
|||
*.test |
|||
|
|||
# Output of the go coverage tool, specifically when used with LiteIDE |
|||
*.out |
|||
|
|||
.idea |
|||
dev.bat |
|||
test.go |
@ -0,0 +1,257 @@ |
|||
## 内部使用基于go-chi的web框架 |
|||
|
|||
# 框架引入 |
|||
> go get -u github.com/wailovet/osmanthuswine |
|||
|
|||
### 目录结构 |
|||
``` |
|||
app |
|||
|--index |
|||
|--index.go |
|||
html |
|||
|--静态文件.... |
|||
main.go |
|||
config.json |
|||
``` |
|||
|
|||
# 开始 |
|||
#### 创建以上目录结构 |
|||
|
|||
|
|||
+ /config.json 配置文件 |
|||
|
|||
```json |
|||
{ |
|||
"port": "8808", |
|||
"host": "0.0.0.0", |
|||
"cross_domain": "*", |
|||
"post_max_memory": 1024000, |
|||
"update_path": "new_exe", |
|||
"db": { |
|||
"host": "", |
|||
"port": "", |
|||
"user": "", |
|||
"password": "", |
|||
"name": "", |
|||
"max_open_conn": 500 |
|||
} |
|||
} |
|||
``` |
|||
|
|||
+ /main.go文件 |
|||
|
|||
``` |
|||
package main |
|||
|
|||
import ( |
|||
"./app/index" |
|||
"github.com/wailovet/osmanthuswine" |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
) |
|||
|
|||
func main() { |
|||
//注册index控制器 |
|||
core.GetInstanceRouterManage().Registered(&index.Index{}) |
|||
//主程序执行 |
|||
osmanthuswine.Run() |
|||
} |
|||
``` |
|||
|
|||
|
|||
+ /app/index/index.go文件 |
|||
|
|||
``` |
|||
package index |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
) |
|||
|
|||
type Index struct { |
|||
core.Controller |
|||
} |
|||
|
|||
func (that *Index) Index() { |
|||
that.DisplayByData(that.Request.REQUEST) |
|||
} |
|||
|
|||
``` |
|||
## core.Controller.Request 使用说明 |
|||
#### 输入参数 |
|||
+ that.Request.GET["参数"] //类型:map[string]string |
|||
+ that.Request.POST["参数"] //类型:map[string]string |
|||
+ that.Request.REQUEST["参数"] //类型:map[string]string , 为GET以及POST的合并值,当出现值冲突时GET参数会被覆盖 |
|||
#### session与cookie获取 |
|||
+ that.Request.SESSION["参数"] //类型:map[string]string |
|||
+ that.Request.COOKIE["参数"] //类型:map[string]string |
|||
#### header信息获取 |
|||
+ that.Request.HEADER["参数"] //类型:map[string]string |
|||
#### 该取值一般以POST-RAW形式传入原始数据,有可能 |
|||
+ that.Request.BODY //类型:string |
|||
#### 快速获取上传的文件 |
|||
+ that.Request.FILE //类型:*multipart.FileHeader |
|||
#### 获取上传的所有文件 |
|||
+ that.Request.FILES //类型:map[string][]*multipart.FileHeader |
|||
|
|||
|
|||
|
|||
## core.Controller 使用说明 |
|||
#### 输出显示 |
|||
> 即使输出时不处于函数结尾,也无需return |
|||
+ that.DisplayByData(data interface{}) |
|||
``` |
|||
{ |
|||
"code":0, |
|||
"data":data, |
|||
"msg":"" |
|||
} |
|||
``` |
|||
- - - |
|||
+ that.DisplayBySuccess(msg string) |
|||
``` |
|||
{ |
|||
"code":0, |
|||
"data":null, |
|||
"msg":msg |
|||
} |
|||
``` |
|||
- - - |
|||
+ that.DisplayByError(msg string, code int) |
|||
``` |
|||
{ |
|||
"code":code, |
|||
"data":null, |
|||
"msg":msg |
|||
} |
|||
``` |
|||
- - - |
|||
+ that.Display(data interface{}, msg string, code int) |
|||
``` |
|||
{ |
|||
"code":code, |
|||
"data":data, |
|||
"msg":msg |
|||
} |
|||
``` |
|||
- - - |
|||
+ that.DisplayByString(data string) |
|||
``` |
|||
data //直接输出data以string形式 |
|||
``` |
|||
- - - |
|||
+ that.DisplayByRaw(data []byte) |
|||
``` |
|||
data //直接输出data以[]byte形式,可用于直接输出二进制文件 |
|||
``` |
|||
- - - |
|||
##### 20190416新增 |
|||
+ that.CheckErrDisplayByError(err error,msg...) |
|||
``` |
|||
err //错误信息,自动判断是否等于nil,如果等于nil该语句会被忽略 |
|||
msg //错误文案提示,不填直接输出err.Error() |
|||
``` |
|||
|
|||
#### session操作 |
|||
> 目前session实现基于securecookie,以加密形式储存在cookie中,注意不要存放大量数据,以免超过cookie的最大储存值 |
|||
+ that.SetSession(name string, value string) //设置session |
|||
+ that.DeleteSession(name string) //删除session |
|||
+ that.ClearSession() //清空session |
|||
|
|||
#### cookie操作 |
|||
> 尽量以session的形式操作 |
|||
+ that.SetCookie(name string, value string) |
|||
|
|||
|
|||
## 数据库操作 |
|||
> 目前框架中集成gorm与xorm框架 |
|||
+ core.GetXormAuto() //获取xorm实例 |
|||
+ core.GetGormAuto() //获取gorm实例 |
|||
#### 数据库配置 |
|||
``` |
|||
实例的数据库配置来自于相同目录下的config.json或者private.json文件 |
|||
{ |
|||
...其他配置 |
|||
"db": { |
|||
"host": "", |
|||
"port": "", |
|||
"user": "", |
|||
"password": "", |
|||
"name": "", |
|||
"prefix": "", |
|||
"max_open_conn": 500 |
|||
} |
|||
} |
|||
prefix为表前缀 |
|||
max_open_conn为可支持最大连接数(未测试是否可用 |
|||
``` |
|||
|
|||
## 支持WebSocket |
|||
> 当传入core.GetInstanceRouterManage().Registered的对象继承自core.WebSocket时,协议升级为websocket,路由地址忽略最后方法名 |
|||
|
|||
|
|||
#### 集成melody库,使用详情https://github.com/olahol/melody |
|||
``` |
|||
package index |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
"gopkg.in/olahol/melody.v1" |
|||
) |
|||
|
|||
type Index struct { |
|||
core.WebSocket |
|||
} |
|||
|
|||
func (that *Wstest) HandleConnect(session *melody.Session) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandlePong(session *melody.Session) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleMessage(session *melody.Session, data []byte) { |
|||
that.GetMelody().Broadcast(data) |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleMessageBinary(session *melody.Session, data []byte) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleSentMessage(session *melody.Session, data []byte) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleSentMessageBinary(session *melody.Session, data []byte) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleDisconnect(session *melody.Session) { |
|||
//implement |
|||
} |
|||
|
|||
func (that *Wstest) HandleError(session *melody.Session, err error) { |
|||
//implement |
|||
} |
|||
|
|||
``` |
|||
|
|||
``` |
|||
//javascript |
|||
var ws = new WebSocket("ws://127.0.0.1/Api/Index/Index") |
|||
``` |
|||
> PS:不同url对应不同的melody实例 |
|||
|
|||
|
|||
## 杂项 |
|||
> 热更新,仅支持linux |
|||
``` |
|||
默认情况下,检测同路径下的<文件名_update>,如果该文件与当前文件不一致,则进行热更,已连接的连接无需断连 |
|||
可在config.json中配置检测的文件名 |
|||
{ |
|||
...其他配置 |
|||
"update_path": "需要检测的文件路径" |
|||
} |
|||
备注:需要检测的文件路径最好不要与当前运行的文件路径相同 |
|||
``` |
@ -0,0 +1,43 @@ |
|||
package app |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
"gopkg.in/olahol/melody.v1" |
|||
) |
|||
|
|||
type Wstest struct { |
|||
core.WebSocket |
|||
} |
|||
|
|||
func (that *Wstest) HandleConnect(session *melody.Session) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandlePong(session *melody.Session) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleMessage(session *melody.Session, data []byte) { |
|||
that.GetMelody().Broadcast(data) |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleMessageBinary(session *melody.Session, data []byte) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleSentMessage(session *melody.Session, data []byte) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleSentMessageBinary(session *melody.Session, data []byte) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleDisconnect(session *melody.Session) { |
|||
//implement
|
|||
} |
|||
|
|||
func (that *Wstest) HandleError(session *melody.Session, err error) { |
|||
//implement
|
|||
} |
@ -0,0 +1,8 @@ |
|||
{ |
|||
"port": "20180", |
|||
"host": "0.0.0.0", |
|||
"cross_domain": "*", |
|||
"post_max_memory": 1024000, |
|||
"api_router": "/Api/*", |
|||
"update_path": "example_update" |
|||
} |
@ -0,0 +1,13 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine" |
|||
"github.com/wailovet/osmanthuswine/example/app" |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
) |
|||
|
|||
func main() { |
|||
core.GetInstanceRouterManage().Registered(&app.Wstest{}) |
|||
core.GetInstanceRouterManage().Registered(&app.Test{}) |
|||
osmanthuswine.Run() |
|||
} |
@ -0,0 +1,11 @@ |
|||
{ |
|||
"db": { |
|||
"host": "", |
|||
"port": "", |
|||
"user": "", |
|||
"password": "", |
|||
"name": "", |
|||
"prefix": "", |
|||
"max_open_conn": 500 |
|||
} |
|||
} |
@ -0,0 +1,157 @@ |
|||
package osmanthuswine |
|||
|
|||
import ( |
|||
"errors" |
|||
"fmt" |
|||
"github.com/go-chi/chi" |
|||
"github.com/go-chi/chi/middleware" |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
"github.com/wailovet/osmanthuswine/src/helper" |
|||
"github.com/wailovet/osmanthuswine/src/session" |
|||
"github.com/wailovet/overseer" |
|||
"github.com/wailovet/overseer/fetcher" |
|||
"io/ioutil" |
|||
"log" |
|||
"net" |
|||
"net/http" |
|||
"os" |
|||
"os/exec" |
|||
"path/filepath" |
|||
"runtime" |
|||
"runtime/debug" |
|||
"strings" |
|||
"time" |
|||
) |
|||
|
|||
var chiRouter *chi.Mux |
|||
|
|||
func GetChiRouter() *chi.Mux { |
|||
if chiRouter == nil { |
|||
|
|||
chiRouter = chi.NewRouter() |
|||
chiRouter.Use(middleware.RequestID) |
|||
chiRouter.Use(middleware.RealIP) |
|||
chiRouter.Use(middleware.Logger) |
|||
chiRouter.Use(middleware.Recoverer) |
|||
chiRouter.Use(middleware.Timeout(60 * time.Second)) |
|||
} |
|||
return chiRouter |
|||
} |
|||
func Run() { |
|||
path, _ := GetCurrentPath() |
|||
os.Chdir(path) |
|||
log.Println("工作目录:", path) |
|||
cc := core.GetInstanceConfig() |
|||
|
|||
if runtime.GOOS == "windows" || cc.UpdatePath == "" { |
|||
listener, err := net.Listen("tcp", cc.Host+":"+cc.Port) |
|||
if err != nil { |
|||
log.Fatal(err.Error()) |
|||
} |
|||
RunProg(overseer.State{ |
|||
Listener: listener, |
|||
}) |
|||
} else { |
|||
overseer.Run(overseer.Config{ |
|||
Program: RunProg, |
|||
Address: cc.Host + ":" + cc.Port, |
|||
Fetcher: &fetcher.File{ |
|||
Path: cc.UpdateDir + cc.UpdatePath, |
|||
Interval: time.Second * 10, |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
} |
|||
func RunProg(state overseer.State) { |
|||
|
|||
cc := core.GetInstanceConfig() |
|||
helper.GetInstanceLog().Out("开始监听:", cc.Host+":"+cc.Port) |
|||
|
|||
r := GetChiRouter() |
|||
|
|||
apiRouter := cc.ApiRouter |
|||
|
|||
r.HandleFunc(apiRouter, func(writer http.ResponseWriter, request *http.Request) { |
|||
|
|||
requestData := core.Request{} |
|||
|
|||
sessionMan := session.New(request, writer) |
|||
|
|||
requestData.REQUEST = make(map[string]string) |
|||
//GET
|
|||
requestData.SyncGetData(request) |
|||
//POST
|
|||
requestData.SyncPostData(request, cc.PostMaxMemory) |
|||
//HEADER
|
|||
requestData.SyncHeaderData(request) |
|||
//COOKIE
|
|||
requestData.SyncCookieData(request) |
|||
//SESSION
|
|||
requestData.SyncSessionData(sessionMan) |
|||
|
|||
responseHandle := core.Response{OriginResponseWriter: writer, Session: sessionMan} |
|||
|
|||
defer func() { |
|||
errs := recover() |
|||
if errs == nil { |
|||
return |
|||
} |
|||
errtxt := fmt.Sprintf("%v", errs) |
|||
if errtxt != "" { |
|||
responseHandle.DisplayByError(errtxt, 500, strings.Split(string(debug.Stack()), "\n\t")...) |
|||
} |
|||
}() |
|||
|
|||
core.GetInstanceRouterManage().RouterSend(request.URL.Path, requestData, responseHandle, cc.CrossDomain) |
|||
|
|||
}) |
|||
|
|||
r.HandleFunc("/*", func(writer http.ResponseWriter, request *http.Request) { |
|||
path := request.URL.Path |
|||
if path == "/" { |
|||
path = "/index.html" |
|||
} |
|||
|
|||
helper.GetInstanceLog().Out("静态文件:", "./html"+path) |
|||
|
|||
f, err := os.Stat("./html" + path) |
|||
if err == nil { |
|||
if f.IsDir() { |
|||
path += "/index.html" |
|||
} |
|||
data, err := ioutil.ReadFile("./html" + path) |
|||
if err == nil { |
|||
writer.Write(data) |
|||
return |
|||
} |
|||
} |
|||
|
|||
writer.WriteHeader(404) |
|||
writer.Write([]byte(err.Error())) |
|||
|
|||
}) |
|||
|
|||
http.Serve(state.Listener, r) |
|||
//http.ListenAndServe(cc.Host+":"+cc.Port, r)
|
|||
|
|||
} |
|||
|
|||
func GetCurrentPath() (string, error) { |
|||
file, err := exec.LookPath(os.Args[0]) |
|||
if err != nil { |
|||
return "", err |
|||
} |
|||
path, err := filepath.Abs(file) |
|||
if err != nil { |
|||
return "", err |
|||
} |
|||
i := strings.LastIndex(path, "/") |
|||
if i < 0 { |
|||
i = strings.LastIndex(path, "\\") |
|||
} |
|||
if i < 0 { |
|||
return "", errors.New(`error: Can't find "/" or "\".`) |
|||
} |
|||
return string(path[0 : i+1]), nil |
|||
} |
@ -0,0 +1,122 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"io/ioutil" |
|||
"log" |
|||
"os" |
|||
) |
|||
|
|||
type Config struct { |
|||
Port string `json:"port"` |
|||
Host string `json:"host"` |
|||
CrossDomain string `json:"cross_domain"` |
|||
ApiRouter string `json:"api_router"` |
|||
PostMaxMemory int64 `json:"post_max_memory"` |
|||
Db struct { |
|||
Host string `json:"host"` |
|||
Port string `json:"port"` |
|||
User string `json:"user"` |
|||
Password string `json:"password"` |
|||
Name string `json:"name"` |
|||
Prefix string `json:"prefix"` |
|||
MaxOpenConn int `json:"max_open_conn"` |
|||
Params map[string]string `json:"params"` |
|||
Debug bool `json:"debug"` |
|||
} `json:"db"` |
|||
Redis struct { |
|||
Addr string `json:"addr"` |
|||
Password string `json:"password"` |
|||
Db int `json:"db"` |
|||
} `json:"redis"` |
|||
UpdateDir string `json:"update_dir"` |
|||
UpdatePath string `json:"update_path"` |
|||
} |
|||
|
|||
var instanceConfig *Config |
|||
var configFile = "./config.json" |
|||
var privateConfigFile = "./private.json" |
|||
|
|||
func SetConfigFile(c string) { |
|||
configFile = c |
|||
} |
|||
|
|||
func SetConfig(c *Config) { |
|||
instanceConfig = c |
|||
} |
|||
|
|||
func GetInstanceConfig() *Config { |
|||
if instanceConfig == nil { |
|||
instanceConfig = &Config{ |
|||
Host: "localhost", |
|||
Port: "8808", |
|||
ApiRouter: "/Api/*", |
|||
CrossDomain: "*", |
|||
PostMaxMemory: 1024 * 1024 * 10, |
|||
Db: struct { |
|||
Host string `json:"host"` |
|||
Port string `json:"port"` |
|||
User string `json:"user"` |
|||
Password string `json:"password"` |
|||
Name string `json:"name"` |
|||
Prefix string `json:"prefix"` |
|||
MaxOpenConn int `json:"max_open_conn"` |
|||
Params map[string]string `json:"params"` |
|||
Debug bool `json:"debug"` |
|||
}{ |
|||
Host: "localhost", |
|||
Port: "3306", |
|||
User: "root", |
|||
Password: "root", |
|||
Name: "test", |
|||
Prefix: "", |
|||
MaxOpenConn: 500, |
|||
Params: map[string]string{ |
|||
"charset": "utf8mb4", |
|||
"parseTime": "true", |
|||
}, |
|||
Debug: true, |
|||
}, |
|||
Redis: struct { |
|||
Addr string `json:"addr"` |
|||
Password string `json:"password"` |
|||
Db int `json:"db"` |
|||
}{ |
|||
Addr: "localhost:6379", |
|||
Password: "", |
|||
Db: 0, |
|||
}, |
|||
UpdateDir: "", |
|||
UpdatePath: os.Args[0] + "_update", |
|||
} |
|||
|
|||
instanceConfig.ReadConfig(configFile) |
|||
instanceConfig.ReadPrivateConfig(privateConfigFile) |
|||
} |
|||
return instanceConfig |
|||
} |
|||
|
|||
func (c *Config) ReadConfig(file string) { |
|||
configText, err := ioutil.ReadFile(file) |
|||
if err != nil { |
|||
log.Println("配置文件错误,启动失败:", err.Error()) |
|||
os.Exit(0) |
|||
} |
|||
err = json.Unmarshal(configText, c) |
|||
if err != nil { |
|||
log.Println("配置文件错误,启动失败:", err.Error()) |
|||
os.Exit(0) |
|||
} |
|||
} |
|||
|
|||
func (c *Config) ReadPrivateConfig(file string) { |
|||
configText, err := ioutil.ReadFile(file) |
|||
if err != nil { |
|||
log.Println("未加载", privateConfigFile, ":", err.Error()) |
|||
return |
|||
} |
|||
err = json.Unmarshal(configText, c) |
|||
if err != nil { |
|||
log.Println("未加载", privateConfigFile, ":", err.Error()) |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
package core |
|||
|
|||
import "encoding/json" |
|||
|
|||
type Controller struct { |
|||
Response |
|||
Request Request |
|||
} |
|||
|
|||
func (c *Controller) ControllerInit(req Request, res Response) { |
|||
c.Request = req |
|||
c.Session = res.Session |
|||
c.OriginResponseWriter = res.OriginResponseWriter |
|||
} |
|||
|
|||
func (c *Controller) RequestToStruct(v interface{}) error { |
|||
if c.Request.BODY != "" { |
|||
err := json.Unmarshal([]byte(c.Request.BODY), v) |
|||
if err == nil { |
|||
return err |
|||
} |
|||
} |
|||
data, _ := json.Marshal(c.Request.REQUEST) |
|||
return json.Unmarshal(data, v) |
|||
} |
@ -0,0 +1,121 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"fmt" |
|||
"github.com/go-sql-driver/mysql" |
|||
"github.com/jinzhu/gorm" |
|||
"strings" |
|||
"time" |
|||
) |
|||
|
|||
var instanceDb *gorm.DB |
|||
|
|||
func GetDb() (*gorm.DB, error) { |
|||
if instanceDb == nil { |
|||
config := GetInstanceConfig() |
|||
mysqlConfig := mysql.NewConfig() |
|||
mysqlConfig.User = config.Db.User |
|||
mysqlConfig.DBName = config.Db.Name |
|||
mysqlConfig.Passwd = config.Db.Password |
|||
mysqlConfig.Params = config.Db.Params |
|||
mysqlConfig.Net = "tcp" |
|||
mysqlConfig.Addr = config.Db.Host + ":" + config.Db.Port |
|||
|
|||
db, err := gorm.Open("mysql", mysqlConfig.FormatDSN()) |
|||
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { |
|||
if len(defaultTableName) > len(config.Db.Prefix) && defaultTableName[:len(config.Db.Prefix)] == config.Db.Prefix { |
|||
return defaultTableName |
|||
} |
|||
return config.Db.Prefix + defaultTableName |
|||
} |
|||
db.DB().SetMaxOpenConns(config.Db.MaxOpenConn) |
|||
db.SingularTable(true) |
|||
instanceDb = db |
|||
return instanceDb, err |
|||
} |
|||
return instanceDb, nil |
|||
} |
|||
|
|||
func GetGormAuto() *gorm.DB { |
|||
return GetDbAuto() |
|||
} |
|||
|
|||
func GetDbAuto() *gorm.DB { |
|||
db, err := GetDb() |
|||
if err != nil { |
|||
panic("数据库访问错误") |
|||
} |
|||
return db |
|||
} |
|||
|
|||
func DbQuery(query string, args ...interface{}) []map[string]interface{} { |
|||
db := GetDbAuto() |
|||
rows, _ := db.DB().Query(query, args...) // Note: Ignoring errors for brevity
|
|||
defer rows.Close() |
|||
cols, _ := rows.Columns() |
|||
var data []map[string]interface{} |
|||
for rows.Next() { |
|||
columns := make([]interface{}, len(cols)) |
|||
columnPointers := make([]interface{}, len(cols)) |
|||
for i, _ := range columns { |
|||
columnPointers[i] = &columns[i] |
|||
} |
|||
|
|||
// Scan the result into the column pointers...
|
|||
if err := rows.Scan(columnPointers...); err != nil { |
|||
panic(err) |
|||
} |
|||
// Create our map, and retrieve the value for each column from the pointers slice,
|
|||
// storing it in the map with the name of the column as the key.
|
|||
m := make(map[string]interface{}) |
|||
for i, colName := range cols { |
|||
val := columnPointers[i].(*interface{}) |
|||
m[colName] = *val |
|||
} |
|||
data = append(data, m) |
|||
} |
|||
return data |
|||
} |
|||
|
|||
var isUpdateComment = make(map[string]bool) |
|||
|
|||
func GetDbAutoMigrate(values ...interface{}) *gorm.DB { |
|||
db := GetDbAuto() |
|||
db.AutoMigrate(values...) |
|||
|
|||
for _, value := range values { |
|||
scope := db.NewScope(value) |
|||
tableName := scope.TableName() |
|||
_, isOk := isUpdateComment[tableName] |
|||
if !isOk { |
|||
field := scope.Fields() |
|||
for e := range field { |
|||
comment := field[e].Tag.Get("comment") |
|||
|
|||
if len(strings.Trim(comment, " ")) > 0 { |
|||
fieldType := db.Dialect().DataTypeOf(field[e].StructField) |
|||
scope.Raw(fmt.Sprintf("ALTER TABLE `%v` MODIFY COLUMN `%v` %v COMMENT '%v';", tableName, field[e].DBName, fieldType, comment)).Exec() |
|||
} |
|||
} |
|||
} |
|||
isUpdateComment[tableName] = true |
|||
} |
|||
|
|||
return db |
|||
} |
|||
|
|||
func init() { |
|||
go func() { |
|||
for { |
|||
if instanceDb != nil { |
|||
err := instanceDb.DB().Ping() |
|||
if err != nil { |
|||
println(err.Error()) |
|||
instanceDb.Close() |
|||
instanceDb = nil |
|||
} |
|||
} |
|||
time.Sleep(time.Second) |
|||
} |
|||
}() |
|||
} |
@ -0,0 +1,36 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/go-redis/redis" |
|||
"time" |
|||
) |
|||
|
|||
var instanceRedis *redis.Client |
|||
|
|||
func GetRedis() *redis.Client { |
|||
if instanceRedis == nil { |
|||
config := GetInstanceConfig() |
|||
instanceRedis = redis.NewClient(&redis.Options{ |
|||
Addr: config.Redis.Addr, |
|||
Password: config.Redis.Password, // no password set
|
|||
DB: config.Redis.Db, // use default DB
|
|||
}) |
|||
} |
|||
return instanceRedis |
|||
} |
|||
|
|||
func init() { |
|||
go func() { |
|||
for { |
|||
if instanceRedis != nil { |
|||
err := instanceRedis.Ping().Err() |
|||
if err != nil { |
|||
println(err.Error()) |
|||
instanceRedis.Close() |
|||
instanceRedis = nil |
|||
} |
|||
} |
|||
time.Sleep(time.Second) |
|||
} |
|||
}() |
|||
} |
@ -0,0 +1,117 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/session" |
|||
"io/ioutil" |
|||
"log" |
|||
"mime/multipart" |
|||
"net/http" |
|||
"net/url" |
|||
) |
|||
|
|||
type Request struct { |
|||
GET map[string]string |
|||
POST map[string]string |
|||
REQUEST map[string]string |
|||
COOKIE map[string]string |
|||
SESSION map[string]string |
|||
HEADER map[string]string |
|||
BODY string |
|||
FILES map[string][]*multipart.FileHeader |
|||
FILE *multipart.FileHeader |
|||
OriginRequest *http.Request |
|||
} |
|||
|
|||
func (r *Request) SyncGetData(request *http.Request) { |
|||
if r.OriginRequest == nil { |
|||
r.OriginRequest = request |
|||
} |
|||
get := request.URL.Query() |
|||
r.GET = make(map[string]string) |
|||
for k := range get { |
|||
str := request.URL.Query().Get(k) |
|||
tmp, err := url.QueryUnescape(str) |
|||
if err != nil { |
|||
log.Println(err.Error()) |
|||
r.GET[k] = str |
|||
r.REQUEST[k] = str |
|||
} else { |
|||
r.GET[k] = tmp |
|||
r.REQUEST[k] = tmp |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (r *Request) SyncPostData(request *http.Request, mem int64) { |
|||
if r.OriginRequest == nil { |
|||
r.OriginRequest = request |
|||
} |
|||
request.ParseForm() |
|||
request.ParseMultipartForm(mem) |
|||
r.POST = make(map[string]string) |
|||
|
|||
post := request.PostForm |
|||
for k := range post { |
|||
str := request.PostFormValue(k) |
|||
tmp, err := url.QueryUnescape(str) |
|||
if err != nil { |
|||
log.Println(err.Error()) |
|||
r.POST[k] = str |
|||
r.REQUEST[k] = str |
|||
} else { |
|||
r.POST[k] = tmp |
|||
r.REQUEST[k] = tmp |
|||
} |
|||
} |
|||
|
|||
if request.MultipartForm != nil { |
|||
r.FILES = request.MultipartForm.File |
|||
if len(r.FILES) > 0 { |
|||
for fe := range r.FILES { |
|||
for fk := range r.FILES[fe] { |
|||
r.FILE = r.FILES[fe][fk] |
|||
} |
|||
} |
|||
} |
|||
|
|||
mf := request.MultipartForm.Value |
|||
for k := range mf { |
|||
if len(mf[k]) > 0 { |
|||
r.POST[k] = mf[k][0] |
|||
r.REQUEST[k] = mf[k][0] |
|||
} |
|||
} |
|||
} |
|||
|
|||
body, _ := ioutil.ReadAll(request.Body) |
|||
r.BODY = string(body) |
|||
} |
|||
|
|||
func (r *Request) SyncHeaderData(request *http.Request) { |
|||
if r.OriginRequest == nil { |
|||
r.OriginRequest = request |
|||
} |
|||
r.HEADER = make(map[string]string) |
|||
header := request.Header |
|||
for k := range header { |
|||
if len(header[k]) > 0 { |
|||
r.HEADER[k] = header[k][0] |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
func (r *Request) SyncCookieData(request *http.Request) { |
|||
if r.OriginRequest == nil { |
|||
r.OriginRequest = request |
|||
} |
|||
cookie := request.Cookies() |
|||
r.COOKIE = make(map[string]string) |
|||
for k := range cookie { |
|||
r.COOKIE[cookie[k].Name] = cookie[k].Value |
|||
} |
|||
} |
|||
|
|||
func (r *Request) SyncSessionData(session *session.Session) { |
|||
r.SESSION = session.GetSession() |
|||
} |
@ -0,0 +1,115 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"github.com/wailovet/osmanthuswine/src/session" |
|||
"net/http" |
|||
"strings" |
|||
) |
|||
|
|||
type ResponseData struct { |
|||
Code int `json:"code"` |
|||
Data interface{} `json:"data"` |
|||
Message string `json:"message"` |
|||
} |
|||
|
|||
type Response struct { |
|||
Session *session.Session |
|||
IsWebSocket bool |
|||
OriginResponseWriter http.ResponseWriter |
|||
} |
|||
|
|||
func (r *Response) DisplayByRaw(data []byte) { |
|||
if r.IsWebSocket { |
|||
panic(nil) |
|||
return |
|||
} |
|||
|
|||
r.OriginResponseWriter.Header().Add("Content-Type", "application/json; charset=utf-8") |
|||
r.OriginResponseWriter.Write(data) |
|||
panic(nil) |
|||
} |
|||
|
|||
func (r *Response) DisplayByString(data string) { |
|||
r.DisplayByRaw([]byte(data)) |
|||
} |
|||
|
|||
func (r *Response) Display(data interface{}, msg string, code int) { |
|||
result := ResponseData{code, data, msg} |
|||
text, err := json.Marshal(result) |
|||
if err != nil { |
|||
r.OriginResponseWriter.WriteHeader(500) |
|||
r.DisplayByString("服务器异常:" + err.Error()) |
|||
} |
|||
r.DisplayByRaw(text) |
|||
} |
|||
|
|||
func (r *Response) DisplayByError(msg string, code int, data ...string) { |
|||
result := ResponseData{code, data, msg} |
|||
text, err := json.Marshal(result) |
|||
if err != nil { |
|||
r.Display(nil, "JSON返回格式解析异常:"+err.Error(), 500) |
|||
} |
|||
r.DisplayByRaw(text) |
|||
} |
|||
|
|||
func (r *Response) CheckErrDisplayByError(err error, msg ...string) { |
|||
if err == nil { |
|||
return |
|||
} |
|||
if len(msg) > 0 { |
|||
r.DisplayByError(strings.Join(msg, ","), 504) |
|||
} else { |
|||
r.DisplayByError(err.Error(), 504) |
|||
} |
|||
} |
|||
|
|||
func (r *Response) DisplayBySuccess(msg string) { |
|||
result := ResponseData{0, nil, msg} |
|||
text, err := json.Marshal(result) |
|||
if err != nil { |
|||
r.Display(nil, "JSON返回格式解析异常:"+err.Error(), 500) |
|||
} |
|||
r.DisplayByRaw(text) |
|||
} |
|||
|
|||
func (r *Response) DisplayByData(data interface{}) { |
|||
result := ResponseData{0, data, ""} |
|||
text, err := json.Marshal(result) |
|||
if err != nil { |
|||
r.Display(nil, "JSON返回格式解析异常:"+err.Error(), 500) |
|||
} |
|||
r.DisplayByRaw(text) |
|||
} |
|||
|
|||
func (r *Response) SetSession(name string, value string) { |
|||
data := r.Session.GetSession() |
|||
data[name] = value |
|||
r.Session.SetSession(data) |
|||
} |
|||
|
|||
func (r *Response) DeleteSession(name string) { |
|||
data := r.Session.GetSession() |
|||
delete(data, name) |
|||
r.Session.SetSession(data) |
|||
} |
|||
|
|||
func (r *Response) ClearSession() { |
|||
data := make(map[string]string) |
|||
r.Session.SetSession(data) |
|||
} |
|||
|
|||
func (r *Response) SetCookie(name string, value string) { |
|||
cookie := &http.Cookie{ |
|||
Name: name, |
|||
Value: value, |
|||
Path: "/", |
|||
Secure: false, |
|||
HttpOnly: false, |
|||
} |
|||
http.SetCookie(r.OriginResponseWriter, cookie) |
|||
} |
|||
|
|||
func (r *Response) SetHeader(name string, value string) { |
|||
r.OriginResponseWriter.Header().Set(name, value) |
|||
} |
@ -0,0 +1,118 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/interfaces" |
|||
"log" |
|||
"reflect" |
|||
"strings" |
|||
"unicode" |
|||
) |
|||
|
|||
type RouterManage struct { |
|||
RegisteredData map[string]reflect.Type |
|||
} |
|||
|
|||
var instanceRouterManage *RouterManage |
|||
|
|||
func GetInstanceRouterManage() *RouterManage { |
|||
if instanceRouterManage == nil { |
|||
instanceRouterManage = &RouterManage{} // not thread safe
|
|||
instanceRouterManage.RegisteredData = make(map[string]reflect.Type) |
|||
} |
|||
return instanceRouterManage |
|||
} |
|||
|
|||
func (rm *RouterManage) Registered(i interface{}) { |
|||
t := reflect.ValueOf(i) |
|||
GetInstanceRouterManage().RegisteredData[t.Type().String()] = reflect.Indirect(t).Type() |
|||
} |
|||
|
|||
func (rm *RouterManage) GetModuleName(name string) string { |
|||
if name == "" { |
|||
return "index" |
|||
} |
|||
return strings.ToLower(name) |
|||
} |
|||
func (rm *RouterManage) GetControllerName(name string) string { |
|||
if name == "" { |
|||
return "Index" |
|||
} |
|||
for i, v := range name { |
|||
return string(unicode.ToUpper(v)) + name[i+1:] |
|||
} |
|||
return "Index" |
|||
} |
|||
func (rm *RouterManage) GetFunName(name string) string { |
|||
if name == "" { |
|||
return "Index" |
|||
} |
|||
for i, v := range name { |
|||
return string(unicode.ToUpper(v)) + name[i+1:] |
|||
} |
|||
return "Index" |
|||
} |
|||
|
|||
func (rm *RouterManage) RouterSend(urlPath string, request Request, response Response, crossDomain string) { |
|||
tmp := strings.Split(urlPath, ".") |
|||
if len(tmp) > 1 { |
|||
urlPath = strings.Join(tmp[0:len(tmp)-1], ".") |
|||
} |
|||
|
|||
sar := strings.Split(urlPath, "/") |
|||
for len(sar) < 5 { |
|||
sar = append(sar, "") |
|||
} |
|||
//过滤非 /Api开头的
|
|||
module := rm.GetModuleName(sar[2]) |
|||
controller := rm.GetControllerName(sar[3]) |
|||
fun := rm.GetFunName(sar[4]) |
|||
|
|||
ctr := "*" + module + "." + controller |
|||
|
|||
_, ok := rm.RegisteredData[ctr] |
|||
if !ok { |
|||
panic("未注册该组件:" + ctr) |
|||
} |
|||
|
|||
vc := reflect.New(rm.RegisteredData[ctr]) |
|||
|
|||
wsinit := vc.MethodByName("WebSocketInit") |
|||
if wsinit.IsValid() { |
|||
response.IsWebSocket = true |
|||
hand := vc.Interface().(interfaces.WebSocketInterface) |
|||
ws := GetWebSocket(ctr+"-"+fun, hand) |
|||
hand.SetFunName(fun) |
|||
hand.WebSocketInit(ws) |
|||
defer func() { |
|||
errs := recover() |
|||
if errs == nil { |
|||
return |
|||
} |
|||
log.Printf("websocket error:%v", errs) |
|||
}() |
|||
|
|||
_ = ws.HandleRequest(response.OriginResponseWriter, request.OriginRequest) |
|||
return |
|||
} |
|||
|
|||
f := vc.MethodByName(fun) |
|||
if !f.IsValid() { |
|||
panic("组件找不到相应function:" + fun) |
|||
} |
|||
|
|||
init := vc.MethodByName("ControllerInit") |
|||
if init.IsValid() { |
|||
init.Call([]reflect.Value{reflect.ValueOf(request), reflect.ValueOf(response)}) |
|||
f.Call(nil) |
|||
} else { |
|||
//兼容模式
|
|||
log.Println("兼容模式") |
|||
f.Call([]reflect.Value{reflect.ValueOf(request), reflect.ValueOf(response)}) |
|||
} |
|||
|
|||
response.OriginResponseWriter.Header().Set("Content-Type", "application/json;charset=UTF-8") |
|||
if crossDomain != "" { |
|||
response.OriginResponseWriter.Header().Set("Access-Control-Allow-Origin", crossDomain) |
|||
} |
|||
|
|||
} |
@ -0,0 +1,51 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/wailovet/osmanthuswine/src/interfaces" |
|||
"gopkg.in/olahol/melody.v1" |
|||
"net/http" |
|||
"sync" |
|||
) |
|||
|
|||
var instanceMelody sync.Map |
|||
|
|||
type WebSocket struct { |
|||
ws *melody.Melody |
|||
FunName string |
|||
} |
|||
|
|||
func (that *WebSocket) SetFunName(funName string) { |
|||
that.FunName = funName |
|||
} |
|||
|
|||
func (that *WebSocket) WebSocketInit(wsx *melody.Melody) { |
|||
that.ws = wsx |
|||
} |
|||
func (that *WebSocket) GetMelody() *melody.Melody { |
|||
return that.ws |
|||
} |
|||
|
|||
func (that *WebSocket) GetWebSocket() *melody.Melody { |
|||
return that.ws |
|||
} |
|||
|
|||
func GetWebSocket(group string, hand interfaces.WebSocketInterface) *melody.Melody { |
|||
var m *melody.Melody |
|||
tmp, ok := instanceMelody.Load(group) |
|||
if !ok { |
|||
m = melody.New() |
|||
m.Upgrader.CheckOrigin = func(r *http.Request) bool { return true } |
|||
m.HandleConnect(hand.HandleConnect) |
|||
m.HandleDisconnect(hand.HandleDisconnect) |
|||
m.HandlePong(hand.HandlePong) |
|||
m.HandleError(hand.HandleError) |
|||
m.HandleMessage(hand.HandleMessage) |
|||
m.HandleMessageBinary(hand.HandleMessageBinary) |
|||
m.HandleSentMessage(hand.HandleSentMessage) |
|||
m.HandleSentMessageBinary(hand.HandleSentMessageBinary) |
|||
instanceMelody.Store(group, m) |
|||
} else { |
|||
m = tmp.(*melody.Melody) |
|||
} |
|||
return m |
|||
} |
@ -0,0 +1,71 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/go-sql-driver/mysql" |
|||
"github.com/xormplus/core" |
|||
"github.com/xormplus/xorm" |
|||
"time" |
|||
) |
|||
|
|||
type Xorm struct { |
|||
db *xorm.Engine |
|||
} |
|||
|
|||
var instanceXorm *Xorm |
|||
|
|||
func GetXormAuto() *xorm.Engine { |
|||
db, err := GetXorm() |
|||
if err != nil { |
|||
panic("数据库访问错误") |
|||
} |
|||
return db.db |
|||
} |
|||
|
|||
func GetXorm() (*Xorm, error) { |
|||
if instanceXorm == nil { |
|||
config := GetInstanceConfig() |
|||
mysqlConfig := mysql.NewConfig() |
|||
mysqlConfig.User = config.Db.User |
|||
mysqlConfig.DBName = config.Db.Name |
|||
mysqlConfig.Passwd = config.Db.Password |
|||
mysqlConfig.Params = config.Db.Params |
|||
mysqlConfig.Net = "tcp" |
|||
mysqlConfig.Addr = config.Db.Host + ":" + config.Db.Port |
|||
|
|||
engine, err := xorm.NewEngine("mysql", mysqlConfig.FormatDSN()) |
|||
if config.Db.Prefix != "" { |
|||
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, config.Db.Prefix) |
|||
engine.SetTableMapper(tbMapper) |
|||
} |
|||
|
|||
instanceXorm = &Xorm{db: engine} |
|||
instanceXorm.db.SetMaxOpenConns(config.Db.MaxOpenConn) |
|||
if config.Db.Debug { |
|||
instanceXorm.db.ShowSQL(true) |
|||
} |
|||
return instanceXorm, err |
|||
} |
|||
return instanceXorm, nil |
|||
} |
|||
|
|||
func (x *Xorm) Ping() error { |
|||
session := x.db.NewSession() |
|||
defer session.Close() |
|||
return session.DB().Ping() |
|||
} |
|||
|
|||
func init() { |
|||
go func() { |
|||
for { |
|||
if instanceXorm != nil { |
|||
err := instanceXorm.Ping() |
|||
if err != nil { |
|||
println(err.Error()) |
|||
instanceXorm.db.Close() |
|||
instanceXorm = nil |
|||
} |
|||
} |
|||
time.Sleep(time.Second) |
|||
} |
|||
}() |
|||
} |
@ -0,0 +1,30 @@ |
|||
package helper |
|||
|
|||
import ( |
|||
"github.com/go-errors/errors" |
|||
"github.com/wailovet/db2struct" |
|||
"github.com/wailovet/osmanthuswine/src/core" |
|||
"strconv" |
|||
) |
|||
|
|||
func GetStructByDb(tableName string, packageName string, structName string) (string, error) { |
|||
mariadbUser := core.GetInstanceConfig().Db.User |
|||
mariadbPassword := core.GetInstanceConfig().Db.Password |
|||
mariadbHost := core.GetInstanceConfig().Db.Host |
|||
mariadbPort, _ := strconv.Atoi(core.GetInstanceConfig().Db.Port) |
|||
mariadbDatabase := core.GetInstanceConfig().Db.Name |
|||
columnDataTypes, err := db2struct.GetColumnsFromMysqlTable(mariadbUser, mariadbPassword, mariadbHost, mariadbPort, mariadbDatabase, tableName) |
|||
|
|||
if err != nil { |
|||
return "", errors.New("Error in selecting column data information from mysql information schema") |
|||
} |
|||
|
|||
// Generate struct string based on columnDataTypes
|
|||
struc, err := db2struct.Generate(*columnDataTypes, tableName, structName, packageName, true, true, false) |
|||
|
|||
if err != nil { |
|||
return "", errors.New("Error in creating struct from json: " + err.Error()) |
|||
} |
|||
return string(struc), nil |
|||
|
|||
} |
@ -0,0 +1,19 @@ |
|||
package helper |
|||
|
|||
import "log" |
|||
|
|||
type Log struct { |
|||
} |
|||
|
|||
var instanceLog *Log |
|||
|
|||
func GetInstanceLog() *Log { |
|||
if instanceLog == nil { |
|||
instanceLog = &Log{} // not thread safe
|
|||
} |
|||
return instanceLog |
|||
} |
|||
|
|||
func (l *Log) Out(args ...interface{}) { |
|||
log.Println(args) |
|||
} |
@ -0,0 +1,10 @@ |
|||
package helper |
|||
|
|||
import ( |
|||
"crypto/md5" |
|||
"fmt" |
|||
) |
|||
|
|||
func Md5(data string) string { |
|||
return fmt.Sprintf("%x", md5.Sum([]byte(data))) |
|||
} |
@ -0,0 +1,8 @@ |
|||
package helper |
|||
|
|||
import "github.com/satori/go.uuid" |
|||
|
|||
func CreateUUID() string { |
|||
u1 := uuid.Must(uuid.NewV4()) |
|||
return u1.String() |
|||
} |
@ -0,0 +1,11 @@ |
|||
package helper |
|||
|
|||
import "testing" |
|||
|
|||
func TestCreateUUID(t *testing.T) { |
|||
s := CreateUUID() |
|||
println(s) |
|||
if len(s) != 36 { |
|||
t.Error("UUID长度错误") |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
package interfaces |
|||
|
|||
import ( |
|||
"gopkg.in/olahol/melody.v1" |
|||
) |
|||
|
|||
//WebSocketInterface interface
|
|||
type WebSocketInterface interface { |
|||
SetFunName(funName string) |
|||
WebSocketInit(ws *melody.Melody) |
|||
GetWebSocket() *melody.Melody |
|||
GetMelody() *melody.Melody |
|||
HandleConnect(*melody.Session) |
|||
HandlePong(*melody.Session) |
|||
HandleMessage(*melody.Session, []byte) |
|||
HandleMessageBinary(*melody.Session, []byte) |
|||
HandleSentMessage(*melody.Session, []byte) |
|||
HandleSentMessageBinary(*melody.Session, []byte) |
|||
HandleDisconnect(*melody.Session) |
|||
HandleError(*melody.Session, error) |
|||
} |
@ -0,0 +1,50 @@ |
|||
package session |
|||
|
|||
import ( |
|||
"github.com/gorilla/securecookie" |
|||
"net/http" |
|||
) |
|||
|
|||
type Session struct { |
|||
secureCookie *securecookie.SecureCookie |
|||
r *http.Request |
|||
w http.ResponseWriter |
|||
data map[string]string |
|||
} |
|||
|
|||
func New(r *http.Request, w http.ResponseWriter) *Session { |
|||
session := &Session{} // not thread safe
|
|||
var hashKey = []byte("osmanthuswine-very-secret") |
|||
// Block keys should be 16 bytes (AES-128) or 32 bytes (AES-256) long.
|
|||
// Shorter keys may weaken the encryption used.
|
|||
var blockKey = []byte("osmanthuswine-lot-secret") |
|||
session.secureCookie = securecookie.New(hashKey, blockKey) |
|||
session.r = r |
|||
session.w = w |
|||
|
|||
session.data = make(map[string]string) |
|||
if cookie, err := session.r.Cookie("osmseccidhas"); err == nil { |
|||
session.secureCookie.Decode("osmseccidhas", cookie.Value, &session.data) |
|||
} else { |
|||
//helper.GetInstanceLog().Out(err.Error())
|
|||
} |
|||
return session |
|||
} |
|||
|
|||
func (session *Session) GetSession() map[string]string { |
|||
return session.data |
|||
} |
|||
|
|||
func (session *Session) SetSession(value map[string]string) { |
|||
if encoded, err := session.secureCookie.Encode("osmseccidhas", value); err == nil { |
|||
cookie := &http.Cookie{ |
|||
Name: "osmseccidhas", |
|||
Value: encoded, |
|||
Path: "/", |
|||
Secure: false, |
|||
HttpOnly: false, |
|||
} |
|||
http.SetCookie(session.w, cookie) |
|||
session.data = value |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue