├── .gitignore ├── README.md └── src └── api ├── Godeps ├── Godeps.json └── Readme ├── build.sh ├── conf ├── app.conf ├── mysql.ini └── redis.ini ├── config └── config.go ├── controllers ├── v1 │ └── person.go └── v2 │ ├── base.go │ ├── monitor.go │ └── person.go ├── dao ├── mysql.go └── redis.go ├── docs └── doc.go ├── main.go ├── models ├── v1 │ └── person.go └── v2 │ └── person.go ├── routers └── router.go ├── tests └── default_test.go ├── util ├── bizconst.go ├── redisconst.go ├── util.go └── xss │ └── xss.go └── vendor ├── github.com ├── astaxie │ └── beego │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── admin.go │ │ ├── adminui.go │ │ ├── app.go │ │ ├── beego.go │ │ ├── config.go │ │ ├── config │ │ ├── config.go │ │ ├── fake.go │ │ ├── ini.go │ │ └── json.go │ │ ├── context │ │ ├── acceptencoder.go │ │ ├── context.go │ │ ├── input.go │ │ └── output.go │ │ ├── controller.go │ │ ├── doc.go │ │ ├── docs.go │ │ ├── error.go │ │ ├── filter.go │ │ ├── flash.go │ │ ├── grace │ │ ├── conn.go │ │ ├── grace.go │ │ ├── listener.go │ │ └── server.go │ │ ├── hooks.go │ │ ├── log.go │ │ ├── logs │ │ ├── README.md │ │ ├── conn.go │ │ ├── console.go │ │ ├── file.go │ │ ├── log.go │ │ ├── logger.go │ │ ├── multifile.go │ │ └── smtp.go │ │ ├── mime.go │ │ ├── namespace.go │ │ ├── parser.go │ │ ├── router.go │ │ ├── session │ │ ├── README.md │ │ ├── sess_cookie.go │ │ ├── sess_file.go │ │ ├── sess_mem.go │ │ ├── sess_utils.go │ │ └── session.go │ │ ├── staticfile.go │ │ ├── template.go │ │ ├── templatefunc.go │ │ ├── toolbox │ │ ├── healthcheck.go │ │ ├── profile.go │ │ ├── statistics.go │ │ └── task.go │ │ ├── tree.go │ │ └── utils │ │ ├── caller.go │ │ ├── debug.go │ │ ├── file.go │ │ ├── mail.go │ │ ├── rand.go │ │ ├── safemap.go │ │ └── slice.go ├── garyburd │ └── redigo │ │ ├── LICENSE │ │ ├── internal │ │ └── commandinfo.go │ │ └── redis │ │ ├── conn.go │ │ ├── doc.go │ │ ├── log.go │ │ ├── pool.go │ │ ├── pubsub.go │ │ ├── redis.go │ │ ├── reply.go │ │ ├── scan.go │ │ └── script.go ├── go-sql-driver │ └── mysql │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── AUTHORS │ │ ├── CHANGELOG.md │ │ ├── CONTRIBUTING.md │ │ ├── ISSUE_TEMPLATE.md │ │ ├── LICENSE │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── README.md │ │ ├── appengine.go │ │ ├── buffer.go │ │ ├── collations.go │ │ ├── connection.go │ │ ├── const.go │ │ ├── driver.go │ │ ├── dsn.go │ │ ├── errors.go │ │ ├── infile.go │ │ ├── packets.go │ │ ├── result.go │ │ ├── rows.go │ │ ├── statement.go │ │ ├── transaction.go │ │ └── utils.go └── microcosm-cc │ └── bluemonday │ ├── .coveralls.yml │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── CREDITS.md │ ├── LICENCE.md │ ├── Makefile │ ├── README.md │ ├── doc.go │ ├── helpers.go │ ├── policies.go │ ├── policy.go │ └── sanitize.go └── golang.org └── x └── net ├── LICENSE ├── PATENTS └── html ├── atom ├── atom.go ├── gen.go └── table.go ├── const.go ├── doc.go ├── doctype.go ├── entity.go ├── escape.go ├── foreign.go ├── node.go ├── parse.go ├── render.go └── token.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | bin/* 3 | pkg/* 4 | src/api/api 5 | src/api/conf/* 6 | src/api/dump.rdb 7 | *.log 8 | *.pprof 9 | *.memprof 10 | src/exersize/* 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ccms 2 | 基于beego框架封装的通用api接口框架
3 | Features:
4 | 1、接口版本化
5 | 2、接口安全签名验证
6 | 3、入参统一处理
7 | 4、参数xss过滤
8 | 5、利用vendor管理第三方包的版本统一性
9 | 6、mysql、redis封装及配置化
10 | 11 | #项目run起来后,本地测试链接 12 | http://localhost:8080/v2/person/get/?appVersion=3.1.0&platform=ios&requestId=592385239&signature=157541d3b4a43675f00a3cf3707603697dea73d2×tamp=1458289047&userId=10001 13 | -------------------------------------------------------------------------------- /src/api/Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "api", 3 | "GoVersion": "go1.6", 4 | "GodepVersion": "v66", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/astaxie/beego", 8 | "Comment": "v1.6.1-5-g88c5dfa", 9 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 10 | }, 11 | { 12 | "ImportPath": "github.com/astaxie/beego/config", 13 | "Comment": "v1.6.1-5-g88c5dfa", 14 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 15 | }, 16 | { 17 | "ImportPath": "github.com/astaxie/beego/context", 18 | "Comment": "v1.6.1-5-g88c5dfa", 19 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 20 | }, 21 | { 22 | "ImportPath": "github.com/astaxie/beego/grace", 23 | "Comment": "v1.6.1-5-g88c5dfa", 24 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 25 | }, 26 | { 27 | "ImportPath": "github.com/astaxie/beego/logs", 28 | "Comment": "v1.6.1-5-g88c5dfa", 29 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 30 | }, 31 | { 32 | "ImportPath": "github.com/astaxie/beego/session", 33 | "Comment": "v1.6.1-5-g88c5dfa", 34 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 35 | }, 36 | { 37 | "ImportPath": "github.com/astaxie/beego/toolbox", 38 | "Comment": "v1.6.1-5-g88c5dfa", 39 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 40 | }, 41 | { 42 | "ImportPath": "github.com/astaxie/beego/utils", 43 | "Comment": "v1.6.1-5-g88c5dfa", 44 | "Rev": "88c5dfa6ead42e624c2e7d9e04eab6cb2d07412a" 45 | }, 46 | { 47 | "ImportPath": "github.com/garyburd/redigo/internal", 48 | "Rev": "8873b2f1995f59d4bcdd2b0dc9858e2cb9bf0c13" 49 | }, 50 | { 51 | "ImportPath": "github.com/garyburd/redigo/redis", 52 | "Rev": "8873b2f1995f59d4bcdd2b0dc9858e2cb9bf0c13" 53 | }, 54 | { 55 | "ImportPath": "github.com/go-sql-driver/mysql", 56 | "Comment": "v1.2-194-g7ebe0a5", 57 | "Rev": "7ebe0a500653eeb1859664bed5e48dec1e164e73" 58 | }, 59 | { 60 | "ImportPath": "github.com/microcosm-cc/bluemonday", 61 | "Rev": "4ac6f27528d0a3f2a59e0b0a6f6b3ff0bb89fe20" 62 | }, 63 | { 64 | "ImportPath": "golang.org/x/net/html", 65 | "Rev": "0c607074acd38c5f23d1344dfe74c977464d1257" 66 | }, 67 | { 68 | "ImportPath": "golang.org/x/net/html/atom", 69 | "Rev": "0c607074acd38c5f23d1344dfe74c977464d1257" 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/api/Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /src/api/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | clear 3 | rm -rf api 4 | go build 5 | ./api 6 | -------------------------------------------------------------------------------- /src/api/conf/app.conf: -------------------------------------------------------------------------------- 1 | [dev] 2 | appname = api 3 | httpport = 8080 4 | runmode = dev 5 | autorender = false 6 | copyrequestbody = true 7 | EnableDocs = true 8 | EnableAdmin = true 9 | 10 | [prod] 11 | appname = ccms 12 | httpport = 9527 13 | runmode = prod 14 | autorender = false 15 | copyrequestbody = true 16 | EnableDocs = false 17 | EnableAdmin = true -------------------------------------------------------------------------------- /src/api/conf/mysql.ini: -------------------------------------------------------------------------------- 1 | [dev] 2 | username = xxx 3 | password = xxx 4 | protocol = tcp 5 | ip = localhost 6 | port = 3306 7 | dbname = app 8 | charset = utf8 9 | 10 | [prod] 11 | username = xxxxx 12 | password = xxxxxx 13 | protocol = tcp 14 | ip = xxxxx 15 | port = 3306 16 | dbname = app 17 | charset = utf8 -------------------------------------------------------------------------------- /src/api/conf/redis.ini: -------------------------------------------------------------------------------- 1 | [dev] 2 | ip = localhost 3 | port = 6380 4 | 5 | [prod] 6 | ip = localhost 7 | port = 6379 8 | -------------------------------------------------------------------------------- /src/api/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | //一些基础配置 4 | import ( 5 | "github.com/astaxie/beego" 6 | ) 7 | 8 | //app版本与接口版本的映射关系 9 | var ApiVersionAndroid = map[string]string{ 10 | "3.1.0" : "v1", 11 | } 12 | 13 | var ApiVersionIOS = map[string]string{ 14 | "3.1.0" : "v1", 15 | } 16 | 17 | //app版本与appkey的映射关系 18 | var AppkeyAndroid = make(map[string]string) 19 | 20 | var AppkeyIOS = make(map[string]string) 21 | 22 | //初始化版本与appkey的映射值 23 | func init() { 24 | if runmode := beego.AppConfig.String("runmode"); runmode == "dev" { 25 | AppkeyAndroid["3.1.0"] = "testCcmsIam500QiangA" 26 | AppkeyIOS["3.1.0"] = "testCcmsIam500QiangA" 27 | }else{ 28 | AppkeyAndroid["3.1.0"] = "xxxx" 29 | AppkeyIOS["3.1.0"] = "xxxx" 30 | } 31 | } -------------------------------------------------------------------------------- /src/api/controllers/v1/person.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "api/models/v1" 6 | ) 7 | 8 | 9 | type PersonController struct { 10 | beego.Controller 11 | } 12 | 13 | func (p *PersonController) List() { 14 | persons := v1.List() 15 | p.Data["json"] = persons 16 | p.ServeJSON() 17 | } -------------------------------------------------------------------------------- /src/api/controllers/v2/base.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "api/config" 5 | "api/dao" 6 | "api/util" 7 | "api/util/xss" 8 | "github.com/astaxie/beego" 9 | "sort" 10 | "strconv" 11 | "strings" 12 | "time" 13 | ) 14 | 15 | //在beego.Controller上的进一步封装,主要进行一些验证 16 | type BaseController struct { 17 | beego.Controller 18 | requestParams map[string]string 19 | } 20 | 21 | // Prepare implemented Prepare() method for baseController. 22 | // It's used for request param valid and check 23 | func (b *BaseController) Prepare() { 24 | b.requestParams = b.params() 25 | b.cleanXss() 26 | beego.Error(b.requestParams) 27 | b.validParam() 28 | b.validRequest() 29 | b.validToken() 30 | } 31 | 32 | //获取请求的所有参数,以供业务controller使用 33 | //规定参数不能为空 34 | func (b *BaseController) params() (params map[string]string) { 35 | params = make(map[string]string) 36 | urlValues := b.Input() 37 | for paramKey, _ := range urlValues { 38 | paramVal := b.Ctx.Input.Query(paramKey) 39 | if "" == paramVal { 40 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 41 | } 42 | params[paramKey] = paramVal 43 | } 44 | 45 | return params 46 | } 47 | 48 | //clean xss attack 49 | func (b *BaseController) cleanXss() { 50 | for paramName, paramVal := range b.requestParams { 51 | cleanedVal := xss.GetXssHandler().Sanitize(paramVal) 52 | b.requestParams[paramName] = cleanedVal 53 | } 54 | } 55 | 56 | //校验必须参数 57 | func (b *BaseController) validParam() { 58 | params := b.Input() 59 | requireParams := []string{"requestId", "signature", "timestamp", "appVersion", "platform"} 60 | 61 | for _, key := range requireParams { 62 | if _, ok := params[key]; !ok { 63 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 64 | } 65 | } 66 | } 67 | 68 | //校验请求签名是否一致 69 | func (b *BaseController) validRequest() { 70 | platform := b.requestParams["platform"] 71 | signature := b.requestParams["signature"] 72 | timestamp := b.requestParams["timestamp"] 73 | appVersion := b.requestParams["appVersion"] 74 | requestId := b.requestParams["requestId"] 75 | 76 | //如果一个请求从发出到服务端接收到,超过10秒,丢弃请求 77 | //这一步是用来防请求重放攻击,同一请求不能无限次被抓包使用 78 | //注意,要做这一步必须做app与服务端的时间戳同步 79 | //另外,默认超时是10秒,有可能会误杀真正的慢请求 80 | now := time.Now().Unix() 81 | reqeustTime, err := strconv.ParseInt(timestamp, 10, 64) 82 | if err != nil { 83 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 84 | } 85 | 86 | if (now - reqeustTime) > util.MAX_REQUEST_INTERVAL { 87 | b.RespResult(util.REQUEST_TIMEOUT_ERRCODE, util.REQUEST_TIMEOUT_ERRMSG, nil) 88 | } 89 | 90 | appKey := b.getAppKey(platform, appVersion) 91 | 92 | dict := []string{appKey, timestamp, requestId} 93 | sort.Strings(dict) 94 | dictStr := strings.Join(dict, "") 95 | 96 | encryptStr := util.SHA1Encrypt(dictStr) 97 | 98 | if encryptStr != signature { 99 | b.RespResult(util.REQUEST_INVALID_ERRCODE, util.REQUEST_INVALID_ERRMSG, nil) 100 | } 101 | } 102 | 103 | //token是代表用户的唯一标志,前后端的往来只使用token,不能出现userid 104 | //token是有时效性的,默认一个月后过期 105 | //并不是所有接口都需要token参数,所以对请求做差异化处理 106 | //对有token的接口,对其进行token有效性验证 107 | func (b *BaseController) validToken() { 108 | params := b.Input() 109 | if token, ok := params["token"]; ok { 110 | //如果有token,不能为空 111 | if "" == token[0] { 112 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 113 | } 114 | 115 | //校验登录下的重放攻击 116 | b.validRequestId(token[0], b.requestParams["signature"]) 117 | b.checkTokenInfo(token[0]) 118 | } 119 | } 120 | 121 | //token与userid是绑定关系,token对外代表用户 122 | //这一步暂时时间实现,新项目开始忙了,说下思路 123 | //根据token获取token详情,验证token是否存在及过期 124 | //如不存在,非法请求 125 | //如没过期,拿到userid,从而查到userinfo,设置到缓存及requestParams["userinfo"],方便后续调用 126 | //如果过期,报登录态失败错误,提示app跳转登录 127 | func (b *BaseController) checkTokenInfo(token string) { 128 | // cacheName := util.USER_INFO + token 129 | // userinfo, _ := dao.GetCache(cacheName) 130 | // if userinfo != nil { 131 | // userToken = 132 | // } 133 | } 134 | 135 | //对于有token的请求,证明用户在登录态下 136 | //对请求可再做一次粗略的重放校验,以保证用户数据的安全 137 | func (b *BaseController) validRequestId(token string, signature string) { 138 | cacheName := util.REQUEST_HISTORY + token 139 | lastSignature, _ := dao.GetCache(cacheName) 140 | if (lastSignature != nil) && (lastSignature == signature) { 141 | b.RespResult(util.REQUEST_INVALID_ERRCODE, util.REQUEST_INVALID_ERRMSG, nil) 142 | } 143 | //此处可设置cache的缓存时间,与token的生存周期一致 144 | dao.SetCache(cacheName, signature) 145 | } 146 | 147 | //获取预埋appKey 148 | //ios及android可以根据不同的版本设置不同的appkey 149 | func (b *BaseController) getAppKey(platform string, appVersion string) (appKey string) { 150 | ok := true 151 | switch platform { 152 | case util.PLATFORM_ANDROID: 153 | if appKey, ok = config.AppkeyAndroid[appVersion]; !ok { 154 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 155 | } 156 | 157 | case util.PLATFORM_IOS: 158 | if appKey, ok = config.AppkeyIOS[appVersion]; !ok { 159 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 160 | } 161 | default: 162 | b.RespResult(util.PARAM_INVALID_ERRCODE, util.PARAM_INVALID_ERRMSG, nil) 163 | } 164 | 165 | return appKey 166 | } 167 | 168 | //请求回复 169 | func (b *BaseController) RespResult(errCode int, errMsg string, data interface{}) { 170 | result := make(map[string]interface{}) 171 | 172 | result["errCode"] = errCode 173 | result["errMsg"] = errMsg 174 | if nil == data { 175 | result["data"] = util.EMPTY_OBJECT 176 | } else { 177 | result["data"] = data 178 | } 179 | 180 | b.Data["json"] = result 181 | b.ServeJSON() 182 | } 183 | -------------------------------------------------------------------------------- /src/api/controllers/v2/monitor.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | // "github.com/astaxie/beego/toolbox" 6 | ) 7 | 8 | type MonitorController struct { 9 | beego.Controller 10 | } 11 | 12 | func (m *MonitorController) GC() { 13 | 14 | } 15 | 16 | func (m *MonitorController) CPU() { 17 | 18 | } 19 | 20 | func (m *MonitorController) Memory() { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/api/controllers/v2/person.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | // "api/dao" 5 | "api/models/v2" 6 | "api/util" 7 | "github.com/astaxie/beego" 8 | ) 9 | 10 | type PersonController struct { 11 | BaseController 12 | } 13 | 14 | func (p *PersonController) List() { 15 | persons := v2.List() 16 | p.Data["json"] = persons 17 | p.ServeJSON() 18 | } 19 | 20 | func (p *PersonController) Get() { 21 | beego.Info(p.requestParams) 22 | 23 | userId := p.requestParams["userId"] 24 | person := v2.Get(userId) 25 | 26 | p.RespResult(util.SUCCESS, util.SUCCESS_MSG, person) 27 | } 28 | -------------------------------------------------------------------------------- /src/api/dao/mysql.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "database/sql" 5 | "github.com/astaxie/beego" 6 | "github.com/astaxie/beego/config" 7 | _ "github.com/go-sql-driver/mysql" 8 | "os" 9 | "path/filepath" 10 | // "sync" 11 | ) 12 | 13 | var db *sql.DB 14 | 15 | // var dbOnce sync.Once 16 | 17 | //启动初始化 18 | func init() { 19 | dbURL, err := getDBUrl() 20 | if err != nil { 21 | beego.Error("Error on parse database config, %s", err.Error()) 22 | os.Exit(1) 23 | } 24 | beego.Debug(dbURL) 25 | // db, err = sql.Open("mysql", "xxx:xxx@tcp(xxx:3306)/xxx?charset=utf8") 26 | db, err = sql.Open("mysql", dbURL) 27 | if err != nil { 28 | beego.Error("Error on initializing database handle, %s", err.Error()) 29 | os.Exit(1) 30 | } 31 | 32 | err = db.Ping() 33 | if err != nil { 34 | beego.Error("Error on opening database connection: %s", err.Error()) 35 | os.Exit(1) 36 | } 37 | 38 | db.SetMaxIdleConns(50) 39 | } 40 | 41 | //The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. 42 | // Thus, the Open function should be called just once. I 43 | //t is rarely necessary to close a DB. 44 | //DB is a database handle representing a pool of zero or more underlying connections. 45 | //It's safe for concurrent use by multiple goroutines. 46 | //The sql package creates and frees connections automatically; it also maintains a free pool of idle connections 47 | //because of all of these reasons, i choose the singleton pattern to init object DB. 48 | func GetDB() *sql.DB { 49 | //单例模式,lazy load 50 | // dbOnce.Do(func() { 51 | // dbURL, err := getDBUrl() 52 | // if err != nil { 53 | // beego.Error("Error on parse database config, %s", err.Error()) 54 | // os.Exit(1) 55 | // } 56 | // beego.Debug(dbURL) 57 | // // db, err = sql.Open("mysql", "haochushi:dev4chushi007.com@tcp(localhost:3306)/app?charset=utf8") 58 | // db, err = sql.Open("mysql", dbURL) 59 | // if err != nil { 60 | // beego.Error("Error on initializing database handle, %s", err.Error()) 61 | // os.Exit(1) 62 | // } 63 | 64 | // err = db.Ping() 65 | // if err != nil { 66 | // beego.Error("Error on opening database connection: %s", err.Error()) 67 | // os.Exit(1) 68 | // } 69 | 70 | // db.SetMaxIdleConns(50) 71 | // }) 72 | return db 73 | } 74 | 75 | func getDBUrl() (string, error) { 76 | mysqlConfigPath := filepath.Join(beego.AppPath, "conf", "mysql.ini") 77 | mysqlConfig, err := config.NewConfig("ini", mysqlConfigPath) 78 | if err != nil { 79 | beego.Error("new mysql config error", err.Error()) 80 | return "", err 81 | } 82 | 83 | envRunMode := os.Getenv("BEEGO_RUNMODE") 84 | if envRunMode == "" { 85 | envRunMode = beego.PROD 86 | } 87 | 88 | username := mysqlConfig.String(envRunMode + "::username") 89 | password := mysqlConfig.String(envRunMode + "::password") 90 | protocol := mysqlConfig.String(envRunMode + "::protocol") 91 | ip := mysqlConfig.String(envRunMode + "::ip") 92 | port := mysqlConfig.String(envRunMode + "::port") 93 | dbname := mysqlConfig.String(envRunMode + "::dbname") 94 | charset := mysqlConfig.String(envRunMode + "::charset") 95 | 96 | dbURL := username + ":" + password + "@" + protocol + "(" + ip + ":" + port + ")" + "/" + dbname + "?charset=" + charset 97 | 98 | return dbURL, nil 99 | } 100 | -------------------------------------------------------------------------------- /src/api/dao/redis.go: -------------------------------------------------------------------------------- 1 | package dao 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/config" 6 | "github.com/garyburd/redigo/redis" 7 | "os" 8 | "path/filepath" 9 | // "sync" 10 | "time" 11 | ) 12 | 13 | var redisPool *redis.Pool 14 | 15 | // var redisOnce sync.Once 16 | 17 | //init函数只会执行一次,线程安全 18 | //Package initialization—variable initialization and the invocation of init functions—happens in a single goroutine, sequentially, one package at a time. 19 | //n init function may launch other goroutines, which can run concurrently with the initialization code. 20 | //However, initialization always sequences the init functions: it will not start the next init until the previous one has returned. 21 | func init() { 22 | redisURL, err := getRedisURL() 23 | if err != nil { 24 | beego.Error("init redis config fail", err.Error()) 25 | os.Exit(1) 26 | } 27 | redisPool = &redis.Pool{ 28 | MaxIdle: 10, 29 | MaxActive: 100, 30 | IdleTimeout: 30 * time.Second, 31 | Dial: func() (redis.Conn, error) { 32 | c, err := redis.Dial("tcp", redisURL) 33 | if err != nil { 34 | beego.Info("dial redis fail,", err.Error()) 35 | return nil, err 36 | } else { 37 | beego.Info("dial redis success and return a connection") 38 | } 39 | return c, nil 40 | }, 41 | } 42 | } 43 | 44 | //单例模式实现,lazy load 45 | //但是调用的时候需:dao.GetRedisPool().Get() 46 | // func GetRedisPool() *redis.Pool { 47 | // redisOnce.Do(func() { 48 | // redisURL, err := getRedisURL() 49 | // if err == nil { 50 | // redisPool = &redis.Pool{ 51 | // MaxIdle: 10, 52 | // MaxActive: 100, 53 | // IdleTimeout: 240 * time.Second, 54 | // Dial: func() (redis.Conn, error) { 55 | // c, err := redis.Dial("tcp", redisURL) 56 | // if err != nil { 57 | // beego.Error("dial redis fail,", err.Error()) 58 | // return nil, err 59 | // } else { 60 | // beego.Error("diao redis success and return a connection") 61 | // } 62 | // return c, nil 63 | // }, 64 | // } 65 | // } 66 | // }) 67 | // return redisPool 68 | // } 69 | 70 | func getRedisURL() (string, error) { 71 | redisConfigPath := filepath.Join(beego.AppPath, "conf", "redis.ini") 72 | redisConfig, err := config.NewConfig("ini", redisConfigPath) 73 | if err != nil { 74 | beego.Error("new redis config error", err.Error()) 75 | return "", err 76 | } 77 | 78 | envRunMode := os.Getenv("BEEGO_RUNMODE") 79 | if envRunMode == "" { 80 | envRunMode = beego.PROD 81 | } 82 | 83 | redisIP := redisConfig.String(envRunMode + "::ip") 84 | redisPort := redisConfig.String(envRunMode + "::port") 85 | redisAddr := redisIP + ":" + redisPort 86 | 87 | return redisAddr, nil 88 | } 89 | 90 | func SetCache(cacheName string, cacheVal interface{}) error { 91 | conn := redisPool.Get() 92 | defer conn.Close() 93 | 94 | _, err := conn.Do("SET", cacheName, cacheVal) 95 | 96 | if err != nil { 97 | beego.Error("set cache failed,", err.Error()) 98 | } 99 | return err 100 | } 101 | 102 | //上次业务并不关心redis是否挂掉,如果为nil直接从db取 103 | //error还是返回,由上层决定是否要处理 104 | func GetCache(cacheName string) (interface{}, error) { 105 | conn := redisPool.Get() 106 | defer conn.Close() 107 | 108 | result, err := conn.Do("GET", cacheName) 109 | 110 | if err != nil { 111 | beego.Error("get cache failed,", err.Error()) 112 | return nil, err 113 | } 114 | 115 | return result, err 116 | } 117 | 118 | func DelCache(cacheName string) error { 119 | conn := redisPool.Get() 120 | defer conn.Close() 121 | 122 | _, err := conn.Do("DEL", cacheName) 123 | if err != nil { 124 | beego.Error("Del cache error,cacheName ", cacheName, " errmsg ", err.Error()) 125 | } 126 | return err 127 | } 128 | -------------------------------------------------------------------------------- /src/api/docs/doc.go: -------------------------------------------------------------------------------- 1 | package docs -------------------------------------------------------------------------------- /src/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | //如果不使用单例模式,可用此方法初始化mysql,redis的连接对象,但要都放在init函数中 5 | _ "api/dao" 6 | _ "api/docs" 7 | _ "api/routers" 8 | _ "api/util/xss" 9 | 10 | "github.com/astaxie/beego" 11 | ) 12 | 13 | func main() { 14 | if beego.BConfig.RunMode == "dev" { 15 | beego.BConfig.WebConfig.DirectoryIndex = true 16 | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" 17 | } 18 | beego.Run() 19 | } 20 | -------------------------------------------------------------------------------- /src/api/models/v1/person.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | type Person struct { 4 | UserId string 5 | Age int 6 | Username string 7 | } 8 | 9 | func List() (persons []Person){ 10 | persons = make([]Person, 0) 11 | persons = append(persons,Person{UserId:"helloworld",Age:18,Username:"johnsun"}) 12 | return persons 13 | } 14 | 15 | func Get(userId string) (person *Person){ 16 | person = &Person{UserId:userId,Age:18,Username:"johnsun"} 17 | return person 18 | } 19 | -------------------------------------------------------------------------------- /src/api/models/v2/person.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "api/dao" 5 | "api/util" 6 | "database/sql" 7 | "encoding/json" 8 | "github.com/astaxie/beego" 9 | ) 10 | 11 | type Person struct { 12 | Id int32 `json:"-"` 13 | Phone string `json:"phone"` 14 | Nickname string `json:"nickname"` 15 | Gender int8 `json:"gender"` 16 | } 17 | 18 | func List() (persons []Person) { 19 | // persons = make([]Person, 0) 20 | // persons = append(persons, Person{UserId: "helloworld", Age: 18, Username: "johnsun"}) 21 | return nil 22 | } 23 | 24 | func Get(userId string) *Person { 25 | //Go strings are immutable. Concatenating two strings generates a third. 26 | //Avoid string concatenation by appending into a []bytebu 27 | buffer := make([]byte, 27) 28 | buffer = append(buffer, util.USER_INFO...) 29 | buffer = append(buffer, userId...) 30 | cacheKey := string(buffer) 31 | cacheVal, err := dao.GetCache(cacheKey) 32 | 33 | person := new(Person) 34 | if cacheVal == nil { 35 | var ( 36 | id int32 37 | phone, nickname sql.NullString 38 | gender int8 39 | ) 40 | err = dao.GetDB().QueryRow("select id,phone,nickname,gender from t_user where userId = ?", userId).Scan(&id, &phone, &nickname, &gender) 41 | if err != nil { 42 | beego.Error(err.Error()) 43 | return person 44 | } 45 | 46 | person.Id = id 47 | person.Gender = gender 48 | if phone.Valid { 49 | person.Phone = phone.String 50 | } 51 | 52 | if nickname.Valid { 53 | person.Nickname = nickname.String 54 | } 55 | 56 | cacheVal, err = json.Marshal(person) 57 | if err != nil { 58 | beego.Error("marshal error,", err.Error()) 59 | } else { 60 | err = dao.SetCache(cacheKey, cacheVal) 61 | if err != nil { 62 | beego.Error("set cache error,", err.Error()) 63 | } 64 | } 65 | } 66 | 67 | err = json.Unmarshal(cacheVal.([]byte), &person) 68 | if err != nil { 69 | beego.Error("unmarshal failed,", err.Error()) 70 | } 71 | 72 | return person 73 | } 74 | -------------------------------------------------------------------------------- /src/api/routers/router.go: -------------------------------------------------------------------------------- 1 | // @APIVersion 1.0.0 2 | // @Title beego Test API 3 | // @Description beego has a very cool tools to autogenerate documents for your API 4 | // @Contact astaxie@gmail.com 5 | // @TermsOfServiceUrl http://beego.me/ 6 | // @License Apache 2.0 7 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 8 | package routers 9 | 10 | import ( 11 | "api/controllers/v1" 12 | "api/controllers/v2" 13 | "github.com/astaxie/beego" 14 | ) 15 | 16 | //配置路由规则 17 | func init() { 18 | v1NS := beego.NewNamespace("/v1", 19 | beego.NSRouter("/person/list", &v1.PersonController{}, "get:List"), 20 | ) 21 | 22 | v2NS := beego.NewNamespace("/v2", 23 | beego.NSNamespace("/person", 24 | beego.NSRouter("/get", &v2.PersonController{}, "get:Get"), 25 | ), 26 | beego.NSRouter("/person/list", &v2.PersonController{}, "get:List"), 27 | 28 | ) 29 | 30 | beego.AddNamespace(v1NS,v2NS) 31 | } 32 | -------------------------------------------------------------------------------- /src/api/tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | "runtime" 8 | "path/filepath" 9 | _ "api/routers" 10 | 11 | "github.com/astaxie/beego" 12 | . "github.com/smartystreets/goconvey/convey" 13 | ) 14 | 15 | func init() { 16 | _, file, _, _ := runtime.Caller(1) 17 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".." + string(filepath.Separator)))) 18 | beego.TestBeegoInit(apppath) 19 | } 20 | 21 | // TestGet is a sample to run an endpoint test 22 | func TestGet(t *testing.T) { 23 | r, _ := http.NewRequest("GET", "/v1/object", nil) 24 | w := httptest.NewRecorder() 25 | beego.BeeApp.Handlers.ServeHTTP(w, r) 26 | 27 | beego.Trace("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String()) 28 | 29 | Convey("Subject: Test Station Endpoint\n", t, func() { 30 | Convey("Status Code Should Be 200", func() { 31 | So(w.Code, ShouldEqual, 200) 32 | }) 33 | Convey("The Result Should Not Be Empty", func() { 34 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 35 | }) 36 | }) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/api/util/bizconst.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | //空对象定义 4 | type EmptyObject struct{} 5 | 6 | var EMPTY_OBJECT = EmptyObject{} 7 | 8 | //业务常量 9 | const ( 10 | SUCCESS = 0 11 | SUCCESS_MSG = "success" 12 | 13 | PLATFORM_ANDROID = "android" 14 | PLATFORM_IOS = "ios" 15 | 16 | PARAM_INVALID_ERRCODE = 10001 17 | PARAM_INVALID_ERRMSG = "参数错误" 18 | 19 | REQUEST_INVALID_ERRCODE = 10000 20 | REQUEST_INVALID_ERRMSG = "非法请求" 21 | 22 | GET_DB_ERRCODE = 10002 23 | GET_DB_ERRMSG = "DB连接异常" 24 | 25 | REQUEST_TIMEOUT_ERRCODE = 10003 26 | REQUEST_TIMEOUT_ERRMSG = "请求超时" 27 | ) 28 | 29 | //配置常量 30 | const ( 31 | //请求时长 32 | MAX_REQUEST_INTERVAL = 10 33 | ) 34 | -------------------------------------------------------------------------------- /src/api/util/redisconst.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | const ( 4 | USER_INFO = "userinfo_" 5 | REQUEST_HISTORY = "request_history_" 6 | ) 7 | -------------------------------------------------------------------------------- /src/api/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "crypto/sha1" 5 | "io" 6 | "fmt" 7 | ) 8 | 9 | 10 | //获取SHA1加密串 11 | func SHA1Encrypt(str string) (encryptStr string) { 12 | h := sha1.New() 13 | io.WriteString(h, str) 14 | 15 | return fmt.Sprintf("%x", h.Sum(nil)) 16 | } -------------------------------------------------------------------------------- /src/api/util/xss/xss.go: -------------------------------------------------------------------------------- 1 | package xss 2 | 3 | import ( 4 | "github.com/microcosm-cc/bluemonday" 5 | ) 6 | 7 | var p *bluemonday.Policy 8 | 9 | func init() { 10 | p = bluemonday.UGCPolicy() 11 | } 12 | 13 | func GetXssHandler() *bluemonday.Policy { 14 | return p 15 | } 16 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | *.swp 4 | *.swo 5 | beego.iml 6 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - tip 5 | - 1.6.0 6 | - 1.5.3 7 | - 1.4.3 8 | services: 9 | - redis-server 10 | - mysql 11 | - postgresql 12 | - memcached 13 | env: 14 | - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db 15 | - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" 16 | - ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" 17 | before_install: 18 | - git clone git://github.com/ideawu/ssdb.git 19 | - cd ssdb 20 | - make 21 | - cd .. 22 | install: 23 | - go get github.com/lib/pq 24 | - go get github.com/go-sql-driver/mysql 25 | - go get github.com/mattn/go-sqlite3 26 | - go get github.com/bradfitz/gomemcache/memcache 27 | - go get github.com/garyburd/redigo/redis 28 | - go get github.com/beego/x2j 29 | - go get github.com/couchbase/go-couchbase 30 | - go get github.com/beego/goyaml2 31 | - go get github.com/belogik/goes 32 | - go get github.com/siddontang/ledisdb/config 33 | - go get github.com/siddontang/ledisdb/ledis 34 | - go get golang.org/x/tools/cmd/vet 35 | - go get github.com/golang/lint/golint 36 | - go get github.com/ssdb/gossdb/ssdb 37 | before_script: 38 | - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" 39 | - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" 40 | - sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi" 41 | - mkdir -p res/var 42 | - ./ssdb/ssdb-server ./ssdb/ssdb.conf -d 43 | after_script: 44 | -killall -w ssdb-server 45 | - rm -rf ./res/var/* 46 | script: 47 | - go vet -x ./... 48 | - $HOME/gopath/bin/golint ./... 49 | - go test -v ./... 50 | notifications: 51 | webhooks: https://hooks.pubu.im/services/z7m9bvybl3rgtg9 52 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to beego 2 | 3 | beego is an open source project. 4 | 5 | It is the work of hundreds of contributors. We appreciate your help! 6 | 7 | Here are instructions to get you started. They are probably not perfect, 8 | please let us know if anything feels wrong or incomplete. 9 | 10 | ## Contribution guidelines 11 | 12 | ### Pull requests 13 | 14 | First of all. beego follow the gitflow. So please send you pull request 15 | to **develop** branch. We will close the pull request to master branch. 16 | 17 | We are always happy to receive pull requests, and do our best to 18 | review them as fast as possible. Not sure if that typo is worth a pull 19 | request? Do it! We will appreciate it. 20 | 21 | If your pull request is not accepted on the first try, don't be 22 | discouraged! Sometimes we can make a mistake, please do more explaining 23 | for us. We will appreciate it. 24 | 25 | We're trying very hard to keep beego simple and fast. We don't want it 26 | to do everything for everybody. This means that we might decide against 27 | incorporating a new feature. But we will give you some advice on how to 28 | do it in other way. 29 | 30 | ### Create issues 31 | 32 | Any significant improvement should be documented as [a GitHub 33 | issue](https://github.com/astaxie/beego/issues) before anybody 34 | starts working on it. 35 | 36 | Also when filing an issue, make sure to answer these five questions: 37 | 38 | - What version of beego are you using (bee version)? 39 | - What operating system and processor architecture are you using? 40 | - What did you do? 41 | - What did you expect to see? 42 | - What did you see instead? 43 | 44 | ### but check existing issues and docs first! 45 | 46 | Please take a moment to check that an issue doesn't already exist 47 | documenting your bug report or improvement proposal. If it does, it 48 | never hurts to add a quick "+1" or "I have this problem too". This will 49 | help prioritize the most common problems and requests. 50 | 51 | Also if you don't know how to use it. please make sure you have read though 52 | the docs in http://beego.me/docs -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 astaxie 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/README.md: -------------------------------------------------------------------------------- 1 | ## Beego 2 | 3 | [![Build Status](https://travis-ci.org/astaxie/beego.svg?branch=master)](https://travis-ci.org/astaxie/beego) 4 | [![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego) 5 | 6 | beego is used for rapid development of RESTful APIs, web apps and backend services in Go. 7 | It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding. 8 | 9 | More info [beego.me](http://beego.me) 10 | 11 | ##Quick Start 12 | ######Download and install 13 | 14 | go get github.com/astaxie/beego 15 | 16 | ######Create file `hello.go` 17 | ```go 18 | package main 19 | 20 | import "github.com/astaxie/beego" 21 | 22 | func main(){ 23 | beego.Run() 24 | } 25 | ``` 26 | ######Build and run 27 | ```bash 28 | go build hello.go 29 | ./hello 30 | ``` 31 | ######Congratulations! 32 | You just built your first beego app. 33 | Open your browser and visit `http://localhost:8000`. 34 | Please see [Documentation](http://beego.me/docs) for more. 35 | 36 | ## Features 37 | 38 | * RESTful support 39 | * MVC architecture 40 | * Modularity 41 | * Auto API documents 42 | * Annotation router 43 | * Namespace 44 | * Powerful development tools 45 | * Full stack for Web & API 46 | 47 | ## Documentation 48 | 49 | * [English](http://beego.me/docs/intro/) 50 | * [中文文档](http://beego.me/docs/intro/) 51 | * [Русский](http://beego.me/docs/intro/) 52 | 53 | ## Community 54 | 55 | * [http://beego.me/community](http://beego.me/community) 56 | * Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited from [here](https://github.com/beego/beedoc/issues/232) 57 | 58 | ## LICENSE 59 | 60 | beego source code is licensed under the Apache Licence, Version 2.0 61 | (http://www.apache.org/licenses/LICENSE-2.0.html). 62 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/beego.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package beego 16 | 17 | import ( 18 | "os" 19 | "path/filepath" 20 | "strconv" 21 | "strings" 22 | ) 23 | 24 | const ( 25 | // VERSION represent beego web framework version. 26 | VERSION = "1.6.1" 27 | 28 | // DEV is for develop 29 | DEV = "dev" 30 | // PROD is for production 31 | PROD = "prod" 32 | ) 33 | 34 | //hook function to run 35 | type hookfunc func() error 36 | 37 | var ( 38 | hooks = make([]hookfunc, 0) //hook function slice to store the hookfunc 39 | ) 40 | 41 | // AddAPPStartHook is used to register the hookfunc 42 | // The hookfuncs will run in beego.Run() 43 | // such as sessionInit, middlerware start, buildtemplate, admin start 44 | func AddAPPStartHook(hf hookfunc) { 45 | hooks = append(hooks, hf) 46 | } 47 | 48 | // Run beego application. 49 | // beego.Run() default run on HttpPort 50 | // beego.Run("localhost") 51 | // beego.Run(":8089") 52 | // beego.Run("127.0.0.1:8089") 53 | func Run(params ...string) { 54 | initBeforeHTTPRun() 55 | 56 | if len(params) > 0 && params[0] != "" { 57 | strs := strings.Split(params[0], ":") 58 | if len(strs) > 0 && strs[0] != "" { 59 | BConfig.Listen.HTTPAddr = strs[0] 60 | } 61 | if len(strs) > 1 && strs[1] != "" { 62 | BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1]) 63 | } 64 | } 65 | 66 | BeeApp.Run() 67 | } 68 | 69 | func initBeforeHTTPRun() { 70 | //init hooks 71 | AddAPPStartHook(registerMime) 72 | AddAPPStartHook(registerDefaultErrorHandler) 73 | AddAPPStartHook(registerSession) 74 | AddAPPStartHook(registerDocs) 75 | AddAPPStartHook(registerTemplate) 76 | AddAPPStartHook(registerAdmin) 77 | 78 | for _, hk := range hooks { 79 | if err := hk(); err != nil { 80 | panic(err) 81 | } 82 | } 83 | } 84 | 85 | // TestBeegoInit is for test package init 86 | func TestBeegoInit(ap string) { 87 | os.Setenv("BEEGO_RUNMODE", "test") 88 | appConfigPath = filepath.Join(ap, "conf", "app.conf") 89 | os.Chdir(ap) 90 | initBeforeHTTPRun() 91 | } 92 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/config/config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package config is used to parse config 16 | // Usage: 17 | // import( 18 | // "github.com/astaxie/beego/config" 19 | // ) 20 | // 21 | // cnf, err := config.NewConfig("ini", "config.conf") 22 | // 23 | // cnf APIS: 24 | // 25 | // cnf.Set(key, val string) error 26 | // cnf.String(key string) string 27 | // cnf.Strings(key string) []string 28 | // cnf.Int(key string) (int, error) 29 | // cnf.Int64(key string) (int64, error) 30 | // cnf.Bool(key string) (bool, error) 31 | // cnf.Float(key string) (float64, error) 32 | // cnf.DefaultString(key string, defaultVal string) string 33 | // cnf.DefaultStrings(key string, defaultVal []string) []string 34 | // cnf.DefaultInt(key string, defaultVal int) int 35 | // cnf.DefaultInt64(key string, defaultVal int64) int64 36 | // cnf.DefaultBool(key string, defaultVal bool) bool 37 | // cnf.DefaultFloat(key string, defaultVal float64) float64 38 | // cnf.DIY(key string) (interface{}, error) 39 | // cnf.GetSection(section string) (map[string]string, error) 40 | // cnf.SaveConfigFile(filename string) error 41 | // 42 | // more docs http://beego.me/docs/module/config.md 43 | package config 44 | 45 | import ( 46 | "fmt" 47 | ) 48 | 49 | // Configer defines how to get and set value from configuration raw data. 50 | type Configer interface { 51 | Set(key, val string) error //support section::key type in given key when using ini type. 52 | String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. 53 | Strings(key string) []string //get string slice 54 | Int(key string) (int, error) 55 | Int64(key string) (int64, error) 56 | Bool(key string) (bool, error) 57 | Float(key string) (float64, error) 58 | DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. 59 | DefaultStrings(key string, defaultVal []string) []string //get string slice 60 | DefaultInt(key string, defaultVal int) int 61 | DefaultInt64(key string, defaultVal int64) int64 62 | DefaultBool(key string, defaultVal bool) bool 63 | DefaultFloat(key string, defaultVal float64) float64 64 | DIY(key string) (interface{}, error) 65 | GetSection(section string) (map[string]string, error) 66 | SaveConfigFile(filename string) error 67 | } 68 | 69 | // Config is the adapter interface for parsing config file to get raw data to Configer. 70 | type Config interface { 71 | Parse(key string) (Configer, error) 72 | ParseData(data []byte) (Configer, error) 73 | } 74 | 75 | var adapters = make(map[string]Config) 76 | 77 | // Register makes a config adapter available by the adapter name. 78 | // If Register is called twice with the same name or if driver is nil, 79 | // it panics. 80 | func Register(name string, adapter Config) { 81 | if adapter == nil { 82 | panic("config: Register adapter is nil") 83 | } 84 | if _, ok := adapters[name]; ok { 85 | panic("config: Register called twice for adapter " + name) 86 | } 87 | adapters[name] = adapter 88 | } 89 | 90 | // NewConfig adapterName is ini/json/xml/yaml. 91 | // filename is the config file path. 92 | func NewConfig(adapterName, filename string) (Configer, error) { 93 | adapter, ok := adapters[adapterName] 94 | if !ok { 95 | return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName) 96 | } 97 | return adapter.Parse(filename) 98 | } 99 | 100 | // NewConfigData adapterName is ini/json/xml/yaml. 101 | // data is the config data. 102 | func NewConfigData(adapterName string, data []byte) (Configer, error) { 103 | adapter, ok := adapters[adapterName] 104 | if !ok { 105 | return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName) 106 | } 107 | return adapter.ParseData(data) 108 | } 109 | 110 | // ParseBool returns the boolean value represented by the string. 111 | // 112 | // It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On, 113 | // 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off. 114 | // Any other value returns an error. 115 | func ParseBool(val interface{}) (value bool, err error) { 116 | if val != nil { 117 | switch v := val.(type) { 118 | case bool: 119 | return v, nil 120 | case string: 121 | switch v { 122 | case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On": 123 | return true, nil 124 | case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off": 125 | return false, nil 126 | } 127 | case int8, int32, int64: 128 | strV := fmt.Sprintf("%s", v) 129 | if strV == "1" { 130 | return true, nil 131 | } else if strV == "0" { 132 | return false, nil 133 | } 134 | case float64: 135 | if v == 1 { 136 | return true, nil 137 | } else if v == 0 { 138 | return false, nil 139 | } 140 | } 141 | return false, fmt.Errorf("parsing %q: invalid syntax", val) 142 | } 143 | return false, fmt.Errorf("parsing : invalid syntax") 144 | } 145 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/config/fake.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package config 16 | 17 | import ( 18 | "errors" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | type fakeConfigContainer struct { 24 | data map[string]string 25 | } 26 | 27 | func (c *fakeConfigContainer) getData(key string) string { 28 | return c.data[strings.ToLower(key)] 29 | } 30 | 31 | func (c *fakeConfigContainer) Set(key, val string) error { 32 | c.data[strings.ToLower(key)] = val 33 | return nil 34 | } 35 | 36 | func (c *fakeConfigContainer) String(key string) string { 37 | return c.getData(key) 38 | } 39 | 40 | func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string { 41 | v := c.getData(key) 42 | if v == "" { 43 | return defaultval 44 | } 45 | return v 46 | } 47 | 48 | func (c *fakeConfigContainer) Strings(key string) []string { 49 | v := c.getData(key) 50 | if v == "" { 51 | return nil 52 | } 53 | return strings.Split(v, ";") 54 | } 55 | 56 | func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string { 57 | v := c.Strings(key) 58 | if v == nil { 59 | return defaultval 60 | } 61 | return v 62 | } 63 | 64 | func (c *fakeConfigContainer) Int(key string) (int, error) { 65 | return strconv.Atoi(c.getData(key)) 66 | } 67 | 68 | func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int { 69 | v, err := c.Int(key) 70 | if err != nil { 71 | return defaultval 72 | } 73 | return v 74 | } 75 | 76 | func (c *fakeConfigContainer) Int64(key string) (int64, error) { 77 | return strconv.ParseInt(c.getData(key), 10, 64) 78 | } 79 | 80 | func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 81 | v, err := c.Int64(key) 82 | if err != nil { 83 | return defaultval 84 | } 85 | return v 86 | } 87 | 88 | func (c *fakeConfigContainer) Bool(key string) (bool, error) { 89 | return ParseBool(c.getData(key)) 90 | } 91 | 92 | func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { 93 | v, err := c.Bool(key) 94 | if err != nil { 95 | return defaultval 96 | } 97 | return v 98 | } 99 | 100 | func (c *fakeConfigContainer) Float(key string) (float64, error) { 101 | return strconv.ParseFloat(c.getData(key), 64) 102 | } 103 | 104 | func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 105 | v, err := c.Float(key) 106 | if err != nil { 107 | return defaultval 108 | } 109 | return v 110 | } 111 | 112 | func (c *fakeConfigContainer) DIY(key string) (interface{}, error) { 113 | if v, ok := c.data[strings.ToLower(key)]; ok { 114 | return v, nil 115 | } 116 | return nil, errors.New("key not find") 117 | } 118 | 119 | func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) { 120 | return nil, errors.New("not implement in the fakeConfigContainer") 121 | } 122 | 123 | func (c *fakeConfigContainer) SaveConfigFile(filename string) error { 124 | return errors.New("not implement in the fakeConfigContainer") 125 | } 126 | 127 | var _ Configer = new(fakeConfigContainer) 128 | 129 | // NewFakeConfig return a fake Congiger 130 | func NewFakeConfig() Configer { 131 | return &fakeConfigContainer{ 132 | data: make(map[string]string), 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/context/acceptencoder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package context 16 | 17 | import ( 18 | "bytes" 19 | "compress/flate" 20 | "compress/gzip" 21 | "compress/zlib" 22 | "io" 23 | "net/http" 24 | "os" 25 | "strconv" 26 | "strings" 27 | "sync" 28 | ) 29 | 30 | type resetWriter interface { 31 | io.Writer 32 | Reset(w io.Writer) 33 | } 34 | 35 | type nopResetWriter struct { 36 | io.Writer 37 | } 38 | 39 | func (n nopResetWriter) Reset(w io.Writer) { 40 | //do nothing 41 | } 42 | 43 | type acceptEncoder struct { 44 | name string 45 | levelEncode func(int) resetWriter 46 | bestSpeedPool *sync.Pool 47 | bestCompressionPool *sync.Pool 48 | } 49 | 50 | func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter { 51 | if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil { 52 | return nopResetWriter{wr} 53 | } 54 | var rwr resetWriter 55 | switch level { 56 | case flate.BestSpeed: 57 | rwr = ac.bestSpeedPool.Get().(resetWriter) 58 | case flate.BestCompression: 59 | rwr = ac.bestCompressionPool.Get().(resetWriter) 60 | default: 61 | rwr = ac.levelEncode(level) 62 | } 63 | rwr.Reset(wr) 64 | return rwr 65 | } 66 | 67 | func (ac acceptEncoder) put(wr resetWriter, level int) { 68 | if ac.bestSpeedPool == nil || ac.bestCompressionPool == nil { 69 | return 70 | } 71 | wr.Reset(nil) 72 | switch level { 73 | case flate.BestSpeed: 74 | ac.bestSpeedPool.Put(wr) 75 | case flate.BestCompression: 76 | ac.bestCompressionPool.Put(wr) 77 | } 78 | } 79 | 80 | var ( 81 | noneCompressEncoder = acceptEncoder{"", nil, nil, nil} 82 | gzipCompressEncoder = acceptEncoder{"gzip", 83 | func(level int) resetWriter { wr, _ := gzip.NewWriterLevel(nil, level); return wr }, 84 | &sync.Pool{ 85 | New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestSpeed); return wr }, 86 | }, 87 | &sync.Pool{ 88 | New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestCompression); return wr }, 89 | }, 90 | } 91 | 92 | //according to the sec :http://tools.ietf.org/html/rfc2616#section-3.5 ,the deflate compress in http is zlib indeed 93 | //deflate 94 | //The "zlib" format defined in RFC 1950 [31] in combination with 95 | //the "deflate" compression mechanism described in RFC 1951 [29]. 96 | deflateCompressEncoder = acceptEncoder{"deflate", 97 | func(level int) resetWriter { wr, _ := zlib.NewWriterLevel(nil, level); return wr }, 98 | &sync.Pool{ 99 | New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestSpeed); return wr }, 100 | }, 101 | &sync.Pool{ 102 | New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestCompression); return wr }, 103 | }, 104 | } 105 | ) 106 | 107 | var ( 108 | encoderMap = map[string]acceptEncoder{ // all the other compress methods will ignore 109 | "gzip": gzipCompressEncoder, 110 | "deflate": deflateCompressEncoder, 111 | "*": gzipCompressEncoder, // * means any compress will accept,we prefer gzip 112 | "identity": noneCompressEncoder, // identity means none-compress 113 | } 114 | ) 115 | 116 | // WriteFile reads from file and writes to writer by the specific encoding(gzip/deflate) 117 | func WriteFile(encoding string, writer io.Writer, file *os.File) (bool, string, error) { 118 | return writeLevel(encoding, writer, file, flate.BestCompression) 119 | } 120 | 121 | // WriteBody reads writes content to writer by the specific encoding(gzip/deflate) 122 | func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string, error) { 123 | return writeLevel(encoding, writer, bytes.NewReader(content), flate.BestSpeed) 124 | } 125 | 126 | // writeLevel reads from reader,writes to writer by specific encoding and compress level 127 | // the compress level is defined by deflate package 128 | func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int) (bool, string, error) { 129 | var outputWriter resetWriter 130 | var err error 131 | var ce = noneCompressEncoder 132 | 133 | if cf, ok := encoderMap[encoding]; ok { 134 | ce = cf 135 | } 136 | encoding = ce.name 137 | outputWriter = ce.encode(writer, level) 138 | defer ce.put(outputWriter, level) 139 | 140 | _, err = io.Copy(outputWriter, reader) 141 | if err != nil { 142 | return false, "", err 143 | } 144 | 145 | switch outputWriter.(type) { 146 | case io.WriteCloser: 147 | outputWriter.(io.WriteCloser).Close() 148 | } 149 | return encoding != "", encoding, nil 150 | } 151 | 152 | // ParseEncoding will extract the right encoding for response 153 | // the Accept-Encoding's sec is here: 154 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 155 | func ParseEncoding(r *http.Request) string { 156 | if r == nil { 157 | return "" 158 | } 159 | return parseEncoding(r) 160 | } 161 | 162 | type q struct { 163 | name string 164 | value float64 165 | } 166 | 167 | func parseEncoding(r *http.Request) string { 168 | acceptEncoding := r.Header.Get("Accept-Encoding") 169 | if acceptEncoding == "" { 170 | return "" 171 | } 172 | var lastQ q 173 | for _, v := range strings.Split(acceptEncoding, ",") { 174 | v = strings.TrimSpace(v) 175 | if v == "" { 176 | continue 177 | } 178 | vs := strings.Split(v, ";") 179 | if len(vs) == 1 { 180 | lastQ = q{vs[0], 1} 181 | break 182 | } 183 | if len(vs) == 2 { 184 | f, _ := strconv.ParseFloat(strings.Replace(vs[1], "q=", "", -1), 64) 185 | if f == 0 { 186 | continue 187 | } 188 | if f > lastQ.value { 189 | lastQ = q{vs[0], f} 190 | } 191 | } 192 | } 193 | if cf, ok := encoderMap[lastQ.name]; ok { 194 | return cf.name 195 | } 196 | return "" 197 | } 198 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package beego provide a MVC framework 3 | beego: an open-source, high-performance, modular, full-stack web framework 4 | 5 | It is used for rapid development of RESTful APIs, web apps and backend services in Go. 6 | beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding. 7 | 8 | package main 9 | import "github.com/astaxie/beego" 10 | 11 | func main() { 12 | beego.Run() 13 | } 14 | 15 | more information: http://beego.me 16 | */ 17 | package beego 18 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/docs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package beego 16 | 17 | import ( 18 | "github.com/astaxie/beego/context" 19 | ) 20 | 21 | // GlobalDocAPI store the swagger api documents 22 | var GlobalDocAPI = make(map[string]interface{}) 23 | 24 | func serverDocs(ctx *context.Context) { 25 | var obj interface{} 26 | if splat := ctx.Input.Param(":splat"); splat == "" { 27 | obj = GlobalDocAPI["Root"] 28 | } else { 29 | if v, ok := GlobalDocAPI[splat]; ok { 30 | obj = v 31 | } 32 | } 33 | if obj != nil { 34 | ctx.Output.Header("Access-Control-Allow-Origin", "*") 35 | ctx.Output.JSON(obj, false, false) 36 | return 37 | } 38 | ctx.Output.SetStatus(404) 39 | } 40 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/filter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package beego 16 | 17 | import "github.com/astaxie/beego/context" 18 | 19 | // FilterFunc defines a filter function which is invoked before the controller handler is executed. 20 | type FilterFunc func(*context.Context) 21 | 22 | // FilterRouter defines a filter operation which is invoked before the controller handler is executed. 23 | // It can match the URL against a pattern, and execute a filter function 24 | // when a request with a matching URL arrives. 25 | type FilterRouter struct { 26 | filterFunc FilterFunc 27 | tree *Tree 28 | pattern string 29 | returnOnOutput bool 30 | } 31 | 32 | // ValidRouter checks if the current request is matched by this filter. 33 | // If the request is matched, the values of the URL parameters defined 34 | // by the filter pattern are also returned. 35 | func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool { 36 | isOk := f.tree.Match(url, ctx) 37 | if isOk != nil { 38 | if b, ok := isOk.(bool); ok { 39 | return b 40 | } 41 | } 42 | return false 43 | } 44 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/flash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package beego 16 | 17 | import ( 18 | "fmt" 19 | "net/url" 20 | "strings" 21 | ) 22 | 23 | // FlashData is a tools to maintain data when using across request. 24 | type FlashData struct { 25 | Data map[string]string 26 | } 27 | 28 | // NewFlash return a new empty FlashData struct. 29 | func NewFlash() *FlashData { 30 | return &FlashData{ 31 | Data: make(map[string]string), 32 | } 33 | } 34 | 35 | // Set message to flash 36 | func (fd *FlashData) Set(key string, msg string, args ...interface{}) { 37 | if len(args) == 0 { 38 | fd.Data[key] = msg 39 | } else { 40 | fd.Data[key] = fmt.Sprintf(msg, args...) 41 | } 42 | } 43 | 44 | // Success writes success message to flash. 45 | func (fd *FlashData) Success(msg string, args ...interface{}) { 46 | if len(args) == 0 { 47 | fd.Data["success"] = msg 48 | } else { 49 | fd.Data["success"] = fmt.Sprintf(msg, args...) 50 | } 51 | } 52 | 53 | // Notice writes notice message to flash. 54 | func (fd *FlashData) Notice(msg string, args ...interface{}) { 55 | if len(args) == 0 { 56 | fd.Data["notice"] = msg 57 | } else { 58 | fd.Data["notice"] = fmt.Sprintf(msg, args...) 59 | } 60 | } 61 | 62 | // Warning writes warning message to flash. 63 | func (fd *FlashData) Warning(msg string, args ...interface{}) { 64 | if len(args) == 0 { 65 | fd.Data["warning"] = msg 66 | } else { 67 | fd.Data["warning"] = fmt.Sprintf(msg, args...) 68 | } 69 | } 70 | 71 | // Error writes error message to flash. 72 | func (fd *FlashData) Error(msg string, args ...interface{}) { 73 | if len(args) == 0 { 74 | fd.Data["error"] = msg 75 | } else { 76 | fd.Data["error"] = fmt.Sprintf(msg, args...) 77 | } 78 | } 79 | 80 | // Store does the saving operation of flash data. 81 | // the data are encoded and saved in cookie. 82 | func (fd *FlashData) Store(c *Controller) { 83 | c.Data["flash"] = fd.Data 84 | var flashValue string 85 | for key, value := range fd.Data { 86 | flashValue += "\x00" + key + "\x23" + BConfig.WebConfig.FlashSeparator + "\x23" + value + "\x00" 87 | } 88 | c.Ctx.SetCookie(BConfig.WebConfig.FlashName, url.QueryEscape(flashValue), 0, "/") 89 | } 90 | 91 | // ReadFromRequest parsed flash data from encoded values in cookie. 92 | func ReadFromRequest(c *Controller) *FlashData { 93 | flash := NewFlash() 94 | if cookie, err := c.Ctx.Request.Cookie(BConfig.WebConfig.FlashName); err == nil { 95 | v, _ := url.QueryUnescape(cookie.Value) 96 | vals := strings.Split(v, "\x00") 97 | for _, v := range vals { 98 | if len(v) > 0 { 99 | kv := strings.Split(v, "\x23"+BConfig.WebConfig.FlashSeparator+"\x23") 100 | if len(kv) == 2 { 101 | flash.Data[kv[0]] = kv[1] 102 | } 103 | } 104 | } 105 | //read one time then delete it 106 | c.Ctx.SetCookie(BConfig.WebConfig.FlashName, "", -1, "/") 107 | } 108 | c.Data["flash"] = flash.Data 109 | return flash 110 | } 111 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/grace/conn.go: -------------------------------------------------------------------------------- 1 | package grace 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | ) 7 | 8 | type graceConn struct { 9 | net.Conn 10 | server *Server 11 | } 12 | 13 | func (c graceConn) Close() (err error) { 14 | defer func() { 15 | if r := recover(); r != nil { 16 | switch x := r.(type) { 17 | case string: 18 | err = errors.New(x) 19 | case error: 20 | err = x 21 | default: 22 | err = errors.New("Unknown panic") 23 | } 24 | } 25 | }() 26 | c.server.wg.Done() 27 | return c.Conn.Close() 28 | } 29 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/grace/grace.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package grace use to hot reload 16 | // Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/ 17 | // 18 | // Usage: 19 | // 20 | // import( 21 | // "log" 22 | // "net/http" 23 | // "os" 24 | // 25 | // "github.com/astaxie/beego/grace" 26 | // ) 27 | // 28 | // func handler(w http.ResponseWriter, r *http.Request) { 29 | // w.Write([]byte("WORLD!")) 30 | // } 31 | // 32 | // func main() { 33 | // mux := http.NewServeMux() 34 | // mux.HandleFunc("/hello", handler) 35 | // 36 | // err := grace.ListenAndServe("localhost:8080", mux) 37 | // if err != nil { 38 | // log.Println(err) 39 | // } 40 | // log.Println("Server on 8080 stopped") 41 | // os.Exit(0) 42 | // } 43 | package grace 44 | 45 | import ( 46 | "flag" 47 | "net/http" 48 | "os" 49 | "strings" 50 | "sync" 51 | "syscall" 52 | "time" 53 | ) 54 | 55 | const ( 56 | // PreSignal is the position to add filter before signal 57 | PreSignal = iota 58 | // PostSignal is the position to add filter after signal 59 | PostSignal 60 | // StateInit represent the application inited 61 | StateInit 62 | // StateRunning represent the application is running 63 | StateRunning 64 | // StateShuttingDown represent the application is shutting down 65 | StateShuttingDown 66 | // StateTerminate represent the application is killed 67 | StateTerminate 68 | ) 69 | 70 | var ( 71 | regLock *sync.Mutex 72 | runningServers map[string]*Server 73 | runningServersOrder []string 74 | socketPtrOffsetMap map[string]uint 75 | runningServersForked bool 76 | 77 | // DefaultReadTimeOut is the HTTP read timeout 78 | DefaultReadTimeOut time.Duration 79 | // DefaultWriteTimeOut is the HTTP Write timeout 80 | DefaultWriteTimeOut time.Duration 81 | // DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit 82 | DefaultMaxHeaderBytes int 83 | // DefaultTimeout is the shutdown server's timeout. default is 60s 84 | DefaultTimeout = 60 * time.Second 85 | 86 | isChild bool 87 | socketOrder string 88 | once sync.Once 89 | ) 90 | 91 | func onceInit() { 92 | regLock = &sync.Mutex{} 93 | flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)") 94 | flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started") 95 | runningServers = make(map[string]*Server) 96 | runningServersOrder = []string{} 97 | socketPtrOffsetMap = make(map[string]uint) 98 | } 99 | 100 | // NewServer returns a new graceServer. 101 | func NewServer(addr string, handler http.Handler) (srv *Server) { 102 | once.Do(onceInit) 103 | regLock.Lock() 104 | defer regLock.Unlock() 105 | if !flag.Parsed() { 106 | flag.Parse() 107 | } 108 | if len(socketOrder) > 0 { 109 | for i, addr := range strings.Split(socketOrder, ",") { 110 | socketPtrOffsetMap[addr] = uint(i) 111 | } 112 | } else { 113 | socketPtrOffsetMap[addr] = uint(len(runningServersOrder)) 114 | } 115 | 116 | srv = &Server{ 117 | wg: sync.WaitGroup{}, 118 | sigChan: make(chan os.Signal), 119 | isChild: isChild, 120 | SignalHooks: map[int]map[os.Signal][]func(){ 121 | PreSignal: { 122 | syscall.SIGHUP: {}, 123 | syscall.SIGINT: {}, 124 | syscall.SIGTERM: {}, 125 | }, 126 | PostSignal: { 127 | syscall.SIGHUP: {}, 128 | syscall.SIGINT: {}, 129 | syscall.SIGTERM: {}, 130 | }, 131 | }, 132 | state: StateInit, 133 | Network: "tcp", 134 | } 135 | srv.Server = &http.Server{} 136 | srv.Server.Addr = addr 137 | srv.Server.ReadTimeout = DefaultReadTimeOut 138 | srv.Server.WriteTimeout = DefaultWriteTimeOut 139 | srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes 140 | srv.Server.Handler = handler 141 | 142 | runningServersOrder = append(runningServersOrder, addr) 143 | runningServers[addr] = srv 144 | 145 | return 146 | } 147 | 148 | // ListenAndServe refer http.ListenAndServe 149 | func ListenAndServe(addr string, handler http.Handler) error { 150 | server := NewServer(addr, handler) 151 | return server.ListenAndServe() 152 | } 153 | 154 | // ListenAndServeTLS refer http.ListenAndServeTLS 155 | func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error { 156 | server := NewServer(addr, handler) 157 | return server.ListenAndServeTLS(certFile, keyFile) 158 | } 159 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/grace/listener.go: -------------------------------------------------------------------------------- 1 | package grace 2 | 3 | import ( 4 | "net" 5 | "os" 6 | "syscall" 7 | "time" 8 | ) 9 | 10 | type graceListener struct { 11 | net.Listener 12 | stop chan error 13 | stopped bool 14 | server *Server 15 | } 16 | 17 | func newGraceListener(l net.Listener, srv *Server) (el *graceListener) { 18 | el = &graceListener{ 19 | Listener: l, 20 | stop: make(chan error), 21 | server: srv, 22 | } 23 | go func() { 24 | _ = <-el.stop 25 | el.stopped = true 26 | el.stop <- el.Listener.Close() 27 | }() 28 | return 29 | } 30 | 31 | func (gl *graceListener) Accept() (c net.Conn, err error) { 32 | tc, err := gl.Listener.(*net.TCPListener).AcceptTCP() 33 | if err != nil { 34 | return 35 | } 36 | 37 | tc.SetKeepAlive(true) 38 | tc.SetKeepAlivePeriod(3 * time.Minute) 39 | 40 | c = graceConn{ 41 | Conn: tc, 42 | server: gl.server, 43 | } 44 | 45 | gl.server.wg.Add(1) 46 | return 47 | } 48 | 49 | func (gl *graceListener) Close() error { 50 | if gl.stopped { 51 | return syscall.EINVAL 52 | } 53 | gl.stop <- nil 54 | return <-gl.stop 55 | } 56 | 57 | func (gl *graceListener) File() *os.File { 58 | // returns a dup(2) - FD_CLOEXEC flag *not* set 59 | tl := gl.Listener.(*net.TCPListener) 60 | fl, _ := tl.File() 61 | return fl 62 | } 63 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/hooks.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | "encoding/json" 5 | "mime" 6 | "net/http" 7 | "path/filepath" 8 | 9 | "github.com/astaxie/beego/session" 10 | ) 11 | 12 | // 13 | func registerMime() error { 14 | for k, v := range mimemaps { 15 | mime.AddExtensionType(k, v) 16 | } 17 | return nil 18 | } 19 | 20 | // register default error http handlers, 404,401,403,500 and 503. 21 | func registerDefaultErrorHandler() error { 22 | m := map[string]func(http.ResponseWriter, *http.Request){ 23 | "401": unauthorized, 24 | "402": paymentRequired, 25 | "403": forbidden, 26 | "404": notFound, 27 | "405": methodNotAllowed, 28 | "500": internalServerError, 29 | "501": notImplemented, 30 | "502": badGateway, 31 | "503": serviceUnavailable, 32 | "504": gatewayTimeout, 33 | } 34 | for e, h := range m { 35 | if _, ok := ErrorMaps[e]; !ok { 36 | ErrorHandler(e, h) 37 | } 38 | } 39 | return nil 40 | } 41 | 42 | func registerSession() error { 43 | if BConfig.WebConfig.Session.SessionOn { 44 | var err error 45 | sessionConfig := AppConfig.String("sessionConfig") 46 | if sessionConfig == "" { 47 | conf := map[string]interface{}{ 48 | "cookieName": BConfig.WebConfig.Session.SessionName, 49 | "gclifetime": BConfig.WebConfig.Session.SessionGCMaxLifetime, 50 | "providerConfig": filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig), 51 | "secure": BConfig.Listen.EnableHTTPS, 52 | "enableSetCookie": BConfig.WebConfig.Session.SessionAutoSetCookie, 53 | "domain": BConfig.WebConfig.Session.SessionDomain, 54 | "cookieLifeTime": BConfig.WebConfig.Session.SessionCookieLifeTime, 55 | } 56 | confBytes, err := json.Marshal(conf) 57 | if err != nil { 58 | return err 59 | } 60 | sessionConfig = string(confBytes) 61 | } 62 | if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, sessionConfig); err != nil { 63 | return err 64 | } 65 | go GlobalSessions.GC() 66 | } 67 | return nil 68 | } 69 | 70 | func registerTemplate() error { 71 | if err := BuildTemplate(BConfig.WebConfig.ViewsPath); err != nil { 72 | if BConfig.RunMode == DEV { 73 | Warn(err) 74 | } 75 | return err 76 | } 77 | return nil 78 | } 79 | 80 | func registerDocs() error { 81 | if BConfig.WebConfig.EnableDocs { 82 | Get("/docs", serverDocs) 83 | Get("/docs/*", serverDocs) 84 | } 85 | return nil 86 | } 87 | 88 | func registerAdmin() error { 89 | if BConfig.Listen.EnableAdmin { 90 | go beeAdminApp.Run() 91 | } 92 | return nil 93 | } 94 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package beego 16 | 17 | import ( 18 | "strings" 19 | 20 | "github.com/astaxie/beego/logs" 21 | ) 22 | 23 | // Log levels to control the logging output. 24 | const ( 25 | LevelEmergency = iota 26 | LevelAlert 27 | LevelCritical 28 | LevelError 29 | LevelWarning 30 | LevelNotice 31 | LevelInformational 32 | LevelDebug 33 | ) 34 | 35 | // BeeLogger references the used application logger. 36 | var BeeLogger = logs.NewLogger(100) 37 | 38 | // SetLevel sets the global log level used by the simple logger. 39 | func SetLevel(l int) { 40 | BeeLogger.SetLevel(l) 41 | } 42 | 43 | // SetLogFuncCall set the CallDepth, default is 3 44 | func SetLogFuncCall(b bool) { 45 | BeeLogger.EnableFuncCallDepth(b) 46 | BeeLogger.SetLogFuncCallDepth(3) 47 | } 48 | 49 | // SetLogger sets a new logger. 50 | func SetLogger(adaptername string, config string) error { 51 | err := BeeLogger.SetLogger(adaptername, config) 52 | if err != nil { 53 | return err 54 | } 55 | return nil 56 | } 57 | 58 | // Emergency logs a message at emergency level. 59 | func Emergency(v ...interface{}) { 60 | BeeLogger.Emergency(generateFmtStr(len(v)), v...) 61 | } 62 | 63 | // Alert logs a message at alert level. 64 | func Alert(v ...interface{}) { 65 | BeeLogger.Alert(generateFmtStr(len(v)), v...) 66 | } 67 | 68 | // Critical logs a message at critical level. 69 | func Critical(v ...interface{}) { 70 | BeeLogger.Critical(generateFmtStr(len(v)), v...) 71 | } 72 | 73 | // Error logs a message at error level. 74 | func Error(v ...interface{}) { 75 | BeeLogger.Error(generateFmtStr(len(v)), v...) 76 | } 77 | 78 | // Warning logs a message at warning level. 79 | func Warning(v ...interface{}) { 80 | BeeLogger.Warning(generateFmtStr(len(v)), v...) 81 | } 82 | 83 | // Warn compatibility alias for Warning() 84 | func Warn(v ...interface{}) { 85 | BeeLogger.Warn(generateFmtStr(len(v)), v...) 86 | } 87 | 88 | // Notice logs a message at notice level. 89 | func Notice(v ...interface{}) { 90 | BeeLogger.Notice(generateFmtStr(len(v)), v...) 91 | } 92 | 93 | // Informational logs a message at info level. 94 | func Informational(v ...interface{}) { 95 | BeeLogger.Informational(generateFmtStr(len(v)), v...) 96 | } 97 | 98 | // Info compatibility alias for Warning() 99 | func Info(v ...interface{}) { 100 | BeeLogger.Info(generateFmtStr(len(v)), v...) 101 | } 102 | 103 | // Debug logs a message at debug level. 104 | func Debug(v ...interface{}) { 105 | BeeLogger.Debug(generateFmtStr(len(v)), v...) 106 | } 107 | 108 | // Trace logs a message at trace level. 109 | // compatibility alias for Warning() 110 | func Trace(v ...interface{}) { 111 | BeeLogger.Trace(generateFmtStr(len(v)), v...) 112 | } 113 | 114 | func generateFmtStr(n int) string { 115 | return strings.Repeat("%v ", n) 116 | } 117 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/README.md: -------------------------------------------------------------------------------- 1 | ## logs 2 | logs is a Go logs manager. It can use many logs adapters. The repo is inspired by `database/sql` . 3 | 4 | 5 | ## How to install? 6 | 7 | go get github.com/astaxie/beego/logs 8 | 9 | 10 | ## What adapters are supported? 11 | 12 | As of now this logs support console, file,smtp and conn. 13 | 14 | 15 | ## How to use it? 16 | 17 | First you must import it 18 | 19 | import ( 20 | "github.com/astaxie/beego/logs" 21 | ) 22 | 23 | Then init a Log (example with console adapter) 24 | 25 | log := NewLogger(10000) 26 | log.SetLogger("console", "") 27 | 28 | > the first params stand for how many channel 29 | 30 | Use it like this: 31 | 32 | log.Trace("trace") 33 | log.Info("info") 34 | log.Warn("warning") 35 | log.Debug("debug") 36 | log.Critical("critical") 37 | 38 | 39 | ## File adapter 40 | 41 | Configure file adapter like this: 42 | 43 | log := NewLogger(10000) 44 | log.SetLogger("file", `{"filename":"test.log"}`) 45 | 46 | 47 | ## Conn adapter 48 | 49 | Configure like this: 50 | 51 | log := NewLogger(1000) 52 | log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`) 53 | log.Info("info") 54 | 55 | 56 | ## Smtp adapter 57 | 58 | Configure like this: 59 | 60 | log := NewLogger(10000) 61 | log.SetLogger("smtp", `{"username":"beegotest@gmail.com","password":"xxxxxxxx","host":"smtp.gmail.com:587","sendTos":["xiemengjun@gmail.com"]}`) 62 | log.Critical("sendmail critical") 63 | time.Sleep(time.Second * 30) 64 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "io" 20 | "net" 21 | "time" 22 | ) 23 | 24 | // connWriter implements LoggerInterface. 25 | // it writes messages in keep-live tcp connection. 26 | type connWriter struct { 27 | lg *logWriter 28 | innerWriter io.WriteCloser 29 | ReconnectOnMsg bool `json:"reconnectOnMsg"` 30 | Reconnect bool `json:"reconnect"` 31 | Net string `json:"net"` 32 | Addr string `json:"addr"` 33 | Level int `json:"level"` 34 | } 35 | 36 | // NewConn create new ConnWrite returning as LoggerInterface. 37 | func NewConn() Logger { 38 | conn := new(connWriter) 39 | conn.Level = LevelTrace 40 | return conn 41 | } 42 | 43 | // Init init connection writer with json config. 44 | // json config only need key "level". 45 | func (c *connWriter) Init(jsonConfig string) error { 46 | return json.Unmarshal([]byte(jsonConfig), c) 47 | } 48 | 49 | // WriteMsg write message in connection. 50 | // if connection is down, try to re-connect. 51 | func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { 52 | if level > c.Level { 53 | return nil 54 | } 55 | if c.needToConnectOnMsg() { 56 | err := c.connect() 57 | if err != nil { 58 | return err 59 | } 60 | } 61 | 62 | if c.ReconnectOnMsg { 63 | defer c.innerWriter.Close() 64 | } 65 | 66 | c.lg.println(when, msg) 67 | return nil 68 | } 69 | 70 | // Flush implementing method. empty. 71 | func (c *connWriter) Flush() { 72 | 73 | } 74 | 75 | // Destroy destroy connection writer and close tcp listener. 76 | func (c *connWriter) Destroy() { 77 | if c.innerWriter != nil { 78 | c.innerWriter.Close() 79 | } 80 | } 81 | 82 | func (c *connWriter) connect() error { 83 | if c.innerWriter != nil { 84 | c.innerWriter.Close() 85 | c.innerWriter = nil 86 | } 87 | 88 | conn, err := net.Dial(c.Net, c.Addr) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | if tcpConn, ok := conn.(*net.TCPConn); ok { 94 | tcpConn.SetKeepAlive(true) 95 | } 96 | 97 | c.innerWriter = conn 98 | c.lg = newLogWriter(conn) 99 | return nil 100 | } 101 | 102 | func (c *connWriter) needToConnectOnMsg() bool { 103 | if c.Reconnect { 104 | c.Reconnect = false 105 | return true 106 | } 107 | 108 | if c.innerWriter == nil { 109 | return true 110 | } 111 | 112 | return c.ReconnectOnMsg 113 | } 114 | 115 | func init() { 116 | Register("conn", NewConn) 117 | } 118 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/console.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "os" 20 | "runtime" 21 | "time" 22 | ) 23 | 24 | // brush is a color join function 25 | type brush func(string) string 26 | 27 | // newBrush return a fix color Brush 28 | func newBrush(color string) brush { 29 | pre := "\033[" 30 | reset := "\033[0m" 31 | return func(text string) string { 32 | return pre + color + "m" + text + reset 33 | } 34 | } 35 | 36 | var colors = []brush{ 37 | newBrush("1;37"), // Emergency white 38 | newBrush("1;36"), // Alert cyan 39 | newBrush("1;35"), // Critical magenta 40 | newBrush("1;31"), // Error red 41 | newBrush("1;33"), // Warning yellow 42 | newBrush("1;32"), // Notice green 43 | newBrush("1;34"), // Informational blue 44 | newBrush("1;34"), // Debug blue 45 | } 46 | 47 | // consoleWriter implements LoggerInterface and writes messages to terminal. 48 | type consoleWriter struct { 49 | lg *logWriter 50 | Level int `json:"level"` 51 | Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color 52 | } 53 | 54 | // NewConsole create ConsoleWriter returning as LoggerInterface. 55 | func NewConsole() Logger { 56 | cw := &consoleWriter{ 57 | lg: newLogWriter(os.Stdout), 58 | Level: LevelDebug, 59 | Colorful: runtime.GOOS != "windows", 60 | } 61 | return cw 62 | } 63 | 64 | // Init init console logger. 65 | // jsonConfig like '{"level":LevelTrace}'. 66 | func (c *consoleWriter) Init(jsonConfig string) error { 67 | if len(jsonConfig) == 0 { 68 | return nil 69 | } 70 | err := json.Unmarshal([]byte(jsonConfig), c) 71 | if runtime.GOOS == "windows" { 72 | c.Colorful = false 73 | } 74 | return err 75 | } 76 | 77 | // WriteMsg write message in console. 78 | func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { 79 | if level > c.Level { 80 | return nil 81 | } 82 | if c.Colorful { 83 | msg = colors[level](msg) 84 | } 85 | c.lg.println(when, msg) 86 | return nil 87 | } 88 | 89 | // Destroy implementing method. empty. 90 | func (c *consoleWriter) Destroy() { 91 | 92 | } 93 | 94 | // Flush implementing method. empty. 95 | func (c *consoleWriter) Flush() { 96 | 97 | } 98 | 99 | func init() { 100 | Register("console", NewConsole) 101 | } 102 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/logger.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logs 16 | 17 | import ( 18 | "io" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | type logWriter struct { 24 | sync.Mutex 25 | writer io.Writer 26 | } 27 | 28 | func newLogWriter(wr io.Writer) *logWriter { 29 | return &logWriter{writer: wr} 30 | } 31 | 32 | func (lg *logWriter) println(when time.Time, msg string) { 33 | lg.Lock() 34 | h, _ := formatTimeHeader(when) 35 | lg.writer.Write(append(append(h, msg...), '\n')) 36 | lg.Unlock() 37 | } 38 | 39 | func formatTimeHeader(when time.Time) ([]byte, int) { 40 | y, mo, d := when.Date() 41 | h, mi, s := when.Clock() 42 | //len(2006/01/02 15:03:04)==19 43 | var buf [20]byte 44 | t := 3 45 | for y >= 10 { 46 | p := y / 10 47 | buf[t] = byte('0' + y - p*10) 48 | y = p 49 | t-- 50 | } 51 | buf[0] = byte('0' + y) 52 | buf[4] = '/' 53 | if mo > 9 { 54 | buf[5] = '1' 55 | buf[6] = byte('0' + mo - 9) 56 | } else { 57 | buf[5] = '0' 58 | buf[6] = byte('0' + mo) 59 | } 60 | buf[7] = '/' 61 | t = d / 10 62 | buf[8] = byte('0' + t) 63 | buf[9] = byte('0' + d - t*10) 64 | buf[10] = ' ' 65 | t = h / 10 66 | buf[11] = byte('0' + t) 67 | buf[12] = byte('0' + h - t*10) 68 | buf[13] = ':' 69 | t = mi / 10 70 | buf[14] = byte('0' + t) 71 | buf[15] = byte('0' + mi - t*10) 72 | buf[16] = ':' 73 | t = s / 10 74 | buf[17] = byte('0' + t) 75 | buf[18] = byte('0' + s - t*10) 76 | buf[19] = ' ' 77 | 78 | return buf[0:], d 79 | } 80 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/multifile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logs 16 | 17 | import ( 18 | "encoding/json" 19 | "time" 20 | ) 21 | 22 | // A filesLogWriter manages several fileLogWriter 23 | // filesLogWriter will write logs to the file in json configuration and write the same level log to correspond file 24 | // means if the file name in configuration is project.log filesLogWriter will create project.error.log/project.debug.log 25 | // and write the error-level logs to project.error.log and write the debug-level logs to project.debug.log 26 | // the rotate attribute also acts like fileLogWriter 27 | type multiFileLogWriter struct { 28 | writers [LevelDebug + 1 + 1]*fileLogWriter // the last one for fullLogWriter 29 | fullLogWriter *fileLogWriter 30 | Separate []string `json:"separate"` 31 | } 32 | 33 | var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"} 34 | 35 | // Init file logger with json config. 36 | // jsonConfig like: 37 | // { 38 | // "filename":"logs/beego.log", 39 | // "maxLines":0, 40 | // "maxsize":0, 41 | // "daily":true, 42 | // "maxDays":15, 43 | // "rotate":true, 44 | // "perm":0600, 45 | // "separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"], 46 | // } 47 | 48 | func (f *multiFileLogWriter) Init(config string) error { 49 | writer := newFileWriter().(*fileLogWriter) 50 | err := writer.Init(config) 51 | if err != nil { 52 | return err 53 | } 54 | f.fullLogWriter = writer 55 | f.writers[LevelDebug+1] = writer 56 | 57 | //unmarshal "separate" field to f.Separate 58 | json.Unmarshal([]byte(config), f) 59 | 60 | jsonMap := map[string]interface{}{} 61 | json.Unmarshal([]byte(config), &jsonMap) 62 | 63 | for i := LevelEmergency; i < LevelDebug+1; i++ { 64 | for _, v := range f.Separate { 65 | if v == levelNames[i] { 66 | jsonMap["filename"] = f.fullLogWriter.fileNameOnly + "." + levelNames[i] + f.fullLogWriter.suffix 67 | jsonMap["level"] = i 68 | bs, _ := json.Marshal(jsonMap) 69 | writer = newFileWriter().(*fileLogWriter) 70 | writer.Init(string(bs)) 71 | f.writers[i] = writer 72 | } 73 | } 74 | } 75 | 76 | return nil 77 | } 78 | 79 | func (f *multiFileLogWriter) Destroy() { 80 | for i := 0; i < len(f.writers); i++ { 81 | if f.writers[i] != nil { 82 | f.writers[i].Destroy() 83 | } 84 | } 85 | } 86 | 87 | func (f *multiFileLogWriter) WriteMsg(when time.Time, msg string, level int) error { 88 | if f.fullLogWriter != nil { 89 | f.fullLogWriter.WriteMsg(when, msg, level) 90 | } 91 | for i := 0; i < len(f.writers)-1; i++ { 92 | if f.writers[i] != nil { 93 | if level == f.writers[i].Level { 94 | f.writers[i].WriteMsg(when, msg, level) 95 | } 96 | } 97 | } 98 | return nil 99 | } 100 | 101 | func (f *multiFileLogWriter) Flush() { 102 | for i := 0; i < len(f.writers); i++ { 103 | if f.writers[i] != nil { 104 | f.writers[i].Flush() 105 | } 106 | } 107 | } 108 | 109 | // newFilesWriter create a FileLogWriter returning as LoggerInterface. 110 | func newFilesWriter() Logger { 111 | return &multiFileLogWriter{} 112 | } 113 | 114 | func init() { 115 | Register("multifile", newFilesWriter) 116 | } 117 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/logs/smtp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package logs 16 | 17 | import ( 18 | "crypto/tls" 19 | "encoding/json" 20 | "fmt" 21 | "net" 22 | "net/smtp" 23 | "strings" 24 | "time" 25 | ) 26 | 27 | // SMTPWriter implements LoggerInterface and is used to send emails via given SMTP-server. 28 | type SMTPWriter struct { 29 | Username string `json:"username"` 30 | Password string `json:"password"` 31 | Host string `json:"host"` 32 | Subject string `json:"subject"` 33 | FromAddress string `json:"fromAddress"` 34 | RecipientAddresses []string `json:"sendTos"` 35 | Level int `json:"level"` 36 | } 37 | 38 | // NewSMTPWriter create smtp writer. 39 | func newSMTPWriter() Logger { 40 | return &SMTPWriter{Level: LevelTrace} 41 | } 42 | 43 | // Init smtp writer with json config. 44 | // config like: 45 | // { 46 | // "username":"example@gmail.com", 47 | // "password:"password", 48 | // "host":"smtp.gmail.com:465", 49 | // "subject":"email title", 50 | // "fromAddress":"from@example.com", 51 | // "sendTos":["email1","email2"], 52 | // "level":LevelError 53 | // } 54 | func (s *SMTPWriter) Init(jsonconfig string) error { 55 | err := json.Unmarshal([]byte(jsonconfig), s) 56 | if err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | 62 | func (s *SMTPWriter) getSMTPAuth(host string) smtp.Auth { 63 | if len(strings.Trim(s.Username, " ")) == 0 && len(strings.Trim(s.Password, " ")) == 0 { 64 | return nil 65 | } 66 | return smtp.PlainAuth( 67 | "", 68 | s.Username, 69 | s.Password, 70 | host, 71 | ) 72 | } 73 | 74 | func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAddress string, recipients []string, msgContent []byte) error { 75 | client, err := smtp.Dial(hostAddressWithPort) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | host, _, _ := net.SplitHostPort(hostAddressWithPort) 81 | tlsConn := &tls.Config{ 82 | InsecureSkipVerify: true, 83 | ServerName: host, 84 | } 85 | if err = client.StartTLS(tlsConn); err != nil { 86 | return err 87 | } 88 | 89 | if auth != nil { 90 | if err = client.Auth(auth); err != nil { 91 | return err 92 | } 93 | } 94 | 95 | if err = client.Mail(fromAddress); err != nil { 96 | return err 97 | } 98 | 99 | for _, rec := range recipients { 100 | if err = client.Rcpt(rec); err != nil { 101 | return err 102 | } 103 | } 104 | 105 | w, err := client.Data() 106 | if err != nil { 107 | return err 108 | } 109 | _, err = w.Write([]byte(msgContent)) 110 | if err != nil { 111 | return err 112 | } 113 | 114 | err = w.Close() 115 | if err != nil { 116 | return err 117 | } 118 | 119 | err = client.Quit() 120 | if err != nil { 121 | return err 122 | } 123 | 124 | return nil 125 | } 126 | 127 | // WriteMsg write message in smtp writer. 128 | // it will send an email with subject and only this message. 129 | func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error { 130 | if level > s.Level { 131 | return nil 132 | } 133 | 134 | hp := strings.Split(s.Host, ":") 135 | 136 | // Set up authentication information. 137 | auth := s.getSMTPAuth(hp[0]) 138 | 139 | // Connect to the server, authenticate, set the sender and recipient, 140 | // and send the email all in one step. 141 | contentType := "Content-Type: text/plain" + "; charset=UTF-8" 142 | mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress + 143 | ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", when.Format("2006-01-02 15:04:05")) + msg) 144 | 145 | return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg) 146 | } 147 | 148 | // Flush implementing method. empty. 149 | func (s *SMTPWriter) Flush() { 150 | return 151 | } 152 | 153 | // Destroy implementing method. empty. 154 | func (s *SMTPWriter) Destroy() { 155 | return 156 | } 157 | 158 | func init() { 159 | Register("smtp", newSMTPWriter) 160 | } 161 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/session/README.md: -------------------------------------------------------------------------------- 1 | session 2 | ============== 3 | 4 | session is a Go session manager. It can use many session providers. Just like the `database/sql` and `database/sql/driver`. 5 | 6 | ## How to install? 7 | 8 | go get github.com/astaxie/beego/session 9 | 10 | 11 | ## What providers are supported? 12 | 13 | As of now this session manager support memory, file, Redis and MySQL. 14 | 15 | 16 | ## How to use it? 17 | 18 | First you must import it 19 | 20 | import ( 21 | "github.com/astaxie/beego/session" 22 | ) 23 | 24 | Then in you web app init the global session manager 25 | 26 | var globalSessions *session.Manager 27 | 28 | * Use **memory** as provider: 29 | 30 | func init() { 31 | globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":3600}`) 32 | go globalSessions.GC() 33 | } 34 | 35 | * Use **file** as provider, the last param is the path where you want file to be stored: 36 | 37 | func init() { 38 | globalSessions, _ = session.NewManager("file",`{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"./tmp"}`) 39 | go globalSessions.GC() 40 | } 41 | 42 | * Use **Redis** as provider, the last param is the Redis conn address,poolsize,password: 43 | 44 | func init() { 45 | globalSessions, _ = session.NewManager("redis", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:6379,100,astaxie"}`) 46 | go globalSessions.GC() 47 | } 48 | 49 | * Use **MySQL** as provider, the last param is the DSN, learn more from [mysql](https://github.com/go-sql-driver/mysql#dsn-data-source-name): 50 | 51 | func init() { 52 | globalSessions, _ = session.NewManager( 53 | "mysql", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"username:password@protocol(address)/dbname?param=value"}`) 54 | go globalSessions.GC() 55 | } 56 | 57 | * Use **Cookie** as provider: 58 | 59 | func init() { 60 | globalSessions, _ = session.NewManager( 61 | "cookie", `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}`) 62 | go globalSessions.GC() 63 | } 64 | 65 | 66 | Finally in the handlerfunc you can use it like this 67 | 68 | func login(w http.ResponseWriter, r *http.Request) { 69 | sess := globalSessions.SessionStart(w, r) 70 | defer sess.SessionRelease(w) 71 | username := sess.Get("username") 72 | fmt.Println(username) 73 | if r.Method == "GET" { 74 | t, _ := template.ParseFiles("login.gtpl") 75 | t.Execute(w, nil) 76 | } else { 77 | fmt.Println("username:", r.Form["username"]) 78 | sess.Set("username", r.Form["username"]) 79 | fmt.Println("password:", r.Form["password"]) 80 | } 81 | } 82 | 83 | 84 | ## How to write own provider? 85 | 86 | When you develop a web app, maybe you want to write own provider because you must meet the requirements. 87 | 88 | Writing a provider is easy. You only need to define two struct types 89 | (Session and Provider), which satisfy the interface definition. 90 | Maybe you will find the **memory** provider is a good example. 91 | 92 | type SessionStore interface { 93 | Set(key, value interface{}) error //set session value 94 | Get(key interface{}) interface{} //get session value 95 | Delete(key interface{}) error //delete session value 96 | SessionID() string //back current sessionID 97 | SessionRelease(w http.ResponseWriter) // release the resource & save data to provider & return the data 98 | Flush() error //delete all data 99 | } 100 | 101 | type Provider interface { 102 | SessionInit(gclifetime int64, config string) error 103 | SessionRead(sid string) (SessionStore, error) 104 | SessionExist(sid string) bool 105 | SessionRegenerate(oldsid, sid string) (SessionStore, error) 106 | SessionDestroy(sid string) error 107 | SessionAll() int //get all active session 108 | SessionGC() 109 | } 110 | 111 | 112 | ## LICENSE 113 | 114 | BSD License http://creativecommons.org/licenses/BSD/ 115 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/session/sess_cookie.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package session 16 | 17 | import ( 18 | "crypto/aes" 19 | "crypto/cipher" 20 | "encoding/json" 21 | "net/http" 22 | "net/url" 23 | "sync" 24 | ) 25 | 26 | var cookiepder = &CookieProvider{} 27 | 28 | // CookieSessionStore Cookie SessionStore 29 | type CookieSessionStore struct { 30 | sid string 31 | values map[interface{}]interface{} // session data 32 | lock sync.RWMutex 33 | } 34 | 35 | // Set value to cookie session. 36 | // the value are encoded as gob with hash block string. 37 | func (st *CookieSessionStore) Set(key, value interface{}) error { 38 | st.lock.Lock() 39 | defer st.lock.Unlock() 40 | st.values[key] = value 41 | return nil 42 | } 43 | 44 | // Get value from cookie session 45 | func (st *CookieSessionStore) Get(key interface{}) interface{} { 46 | st.lock.RLock() 47 | defer st.lock.RUnlock() 48 | if v, ok := st.values[key]; ok { 49 | return v 50 | } 51 | return nil 52 | } 53 | 54 | // Delete value in cookie session 55 | func (st *CookieSessionStore) Delete(key interface{}) error { 56 | st.lock.Lock() 57 | defer st.lock.Unlock() 58 | delete(st.values, key) 59 | return nil 60 | } 61 | 62 | // Flush Clean all values in cookie session 63 | func (st *CookieSessionStore) Flush() error { 64 | st.lock.Lock() 65 | defer st.lock.Unlock() 66 | st.values = make(map[interface{}]interface{}) 67 | return nil 68 | } 69 | 70 | // SessionID Return id of this cookie session 71 | func (st *CookieSessionStore) SessionID() string { 72 | return st.sid 73 | } 74 | 75 | // SessionRelease Write cookie session to http response cookie 76 | func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { 77 | str, err := encodeCookie(cookiepder.block, 78 | cookiepder.config.SecurityKey, 79 | cookiepder.config.SecurityName, 80 | st.values) 81 | if err != nil { 82 | return 83 | } 84 | cookie := &http.Cookie{Name: cookiepder.config.CookieName, 85 | Value: url.QueryEscape(str), 86 | Path: "/", 87 | HttpOnly: true, 88 | Secure: cookiepder.config.Secure, 89 | MaxAge: cookiepder.config.Maxage} 90 | http.SetCookie(w, cookie) 91 | return 92 | } 93 | 94 | type cookieConfig struct { 95 | SecurityKey string `json:"securityKey"` 96 | BlockKey string `json:"blockKey"` 97 | SecurityName string `json:"securityName"` 98 | CookieName string `json:"cookieName"` 99 | Secure bool `json:"secure"` 100 | Maxage int `json:"maxage"` 101 | } 102 | 103 | // CookieProvider Cookie session provider 104 | type CookieProvider struct { 105 | maxlifetime int64 106 | config *cookieConfig 107 | block cipher.Block 108 | } 109 | 110 | // SessionInit Init cookie session provider with max lifetime and config json. 111 | // maxlifetime is ignored. 112 | // json config: 113 | // securityKey - hash string 114 | // blockKey - gob encode hash string. it's saved as aes crypto. 115 | // securityName - recognized name in encoded cookie string 116 | // cookieName - cookie name 117 | // maxage - cookie max life time. 118 | func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { 119 | pder.config = &cookieConfig{} 120 | err := json.Unmarshal([]byte(config), pder.config) 121 | if err != nil { 122 | return err 123 | } 124 | if pder.config.BlockKey == "" { 125 | pder.config.BlockKey = string(generateRandomKey(16)) 126 | } 127 | if pder.config.SecurityName == "" { 128 | pder.config.SecurityName = string(generateRandomKey(20)) 129 | } 130 | pder.block, err = aes.NewCipher([]byte(pder.config.BlockKey)) 131 | if err != nil { 132 | return err 133 | } 134 | pder.maxlifetime = maxlifetime 135 | return nil 136 | } 137 | 138 | // SessionRead Get SessionStore in cooke. 139 | // decode cooke string to map and put into SessionStore with sid. 140 | func (pder *CookieProvider) SessionRead(sid string) (Store, error) { 141 | maps, _ := decodeCookie(pder.block, 142 | pder.config.SecurityKey, 143 | pder.config.SecurityName, 144 | sid, pder.maxlifetime) 145 | if maps == nil { 146 | maps = make(map[interface{}]interface{}) 147 | } 148 | rs := &CookieSessionStore{sid: sid, values: maps} 149 | return rs, nil 150 | } 151 | 152 | // SessionExist Cookie session is always existed 153 | func (pder *CookieProvider) SessionExist(sid string) bool { 154 | return true 155 | } 156 | 157 | // SessionRegenerate Implement method, no used. 158 | func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (Store, error) { 159 | return nil, nil 160 | } 161 | 162 | // SessionDestroy Implement method, no used. 163 | func (pder *CookieProvider) SessionDestroy(sid string) error { 164 | return nil 165 | } 166 | 167 | // SessionGC Implement method, no used. 168 | func (pder *CookieProvider) SessionGC() { 169 | return 170 | } 171 | 172 | // SessionAll Implement method, return 0. 173 | func (pder *CookieProvider) SessionAll() int { 174 | return 0 175 | } 176 | 177 | // SessionUpdate Implement method, no used. 178 | func (pder *CookieProvider) SessionUpdate(sid string) error { 179 | return nil 180 | } 181 | 182 | func init() { 183 | Register("cookie", cookiepder) 184 | } 185 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/session/sess_mem.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package session 16 | 17 | import ( 18 | "container/list" 19 | "net/http" 20 | "sync" 21 | "time" 22 | ) 23 | 24 | var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)} 25 | 26 | // MemSessionStore memory session store. 27 | // it saved sessions in a map in memory. 28 | type MemSessionStore struct { 29 | sid string //session id 30 | timeAccessed time.Time //last access time 31 | value map[interface{}]interface{} //session store 32 | lock sync.RWMutex 33 | } 34 | 35 | // Set value to memory session 36 | func (st *MemSessionStore) Set(key, value interface{}) error { 37 | st.lock.Lock() 38 | defer st.lock.Unlock() 39 | st.value[key] = value 40 | return nil 41 | } 42 | 43 | // Get value from memory session by key 44 | func (st *MemSessionStore) Get(key interface{}) interface{} { 45 | st.lock.RLock() 46 | defer st.lock.RUnlock() 47 | if v, ok := st.value[key]; ok { 48 | return v 49 | } 50 | return nil 51 | } 52 | 53 | // Delete in memory session by key 54 | func (st *MemSessionStore) Delete(key interface{}) error { 55 | st.lock.Lock() 56 | defer st.lock.Unlock() 57 | delete(st.value, key) 58 | return nil 59 | } 60 | 61 | // Flush clear all values in memory session 62 | func (st *MemSessionStore) Flush() error { 63 | st.lock.Lock() 64 | defer st.lock.Unlock() 65 | st.value = make(map[interface{}]interface{}) 66 | return nil 67 | } 68 | 69 | // SessionID get this id of memory session store 70 | func (st *MemSessionStore) SessionID() string { 71 | return st.sid 72 | } 73 | 74 | // SessionRelease Implement method, no used. 75 | func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) { 76 | } 77 | 78 | // MemProvider Implement the provider interface 79 | type MemProvider struct { 80 | lock sync.RWMutex // locker 81 | sessions map[string]*list.Element // map in memory 82 | list *list.List // for gc 83 | maxlifetime int64 84 | savePath string 85 | } 86 | 87 | // SessionInit init memory session 88 | func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error { 89 | pder.maxlifetime = maxlifetime 90 | pder.savePath = savePath 91 | return nil 92 | } 93 | 94 | // SessionRead get memory session store by sid 95 | func (pder *MemProvider) SessionRead(sid string) (Store, error) { 96 | pder.lock.RLock() 97 | if element, ok := pder.sessions[sid]; ok { 98 | go pder.SessionUpdate(sid) 99 | pder.lock.RUnlock() 100 | return element.Value.(*MemSessionStore), nil 101 | } 102 | pder.lock.RUnlock() 103 | pder.lock.Lock() 104 | newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} 105 | element := pder.list.PushFront(newsess) 106 | pder.sessions[sid] = element 107 | pder.lock.Unlock() 108 | return newsess, nil 109 | } 110 | 111 | // SessionExist check session store exist in memory session by sid 112 | func (pder *MemProvider) SessionExist(sid string) bool { 113 | pder.lock.RLock() 114 | defer pder.lock.RUnlock() 115 | if _, ok := pder.sessions[sid]; ok { 116 | return true 117 | } 118 | return false 119 | } 120 | 121 | // SessionRegenerate generate new sid for session store in memory session 122 | func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) { 123 | pder.lock.RLock() 124 | if element, ok := pder.sessions[oldsid]; ok { 125 | go pder.SessionUpdate(oldsid) 126 | pder.lock.RUnlock() 127 | pder.lock.Lock() 128 | element.Value.(*MemSessionStore).sid = sid 129 | pder.sessions[sid] = element 130 | delete(pder.sessions, oldsid) 131 | pder.lock.Unlock() 132 | return element.Value.(*MemSessionStore), nil 133 | } 134 | pder.lock.RUnlock() 135 | pder.lock.Lock() 136 | newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} 137 | element := pder.list.PushFront(newsess) 138 | pder.sessions[sid] = element 139 | pder.lock.Unlock() 140 | return newsess, nil 141 | } 142 | 143 | // SessionDestroy delete session store in memory session by id 144 | func (pder *MemProvider) SessionDestroy(sid string) error { 145 | pder.lock.Lock() 146 | defer pder.lock.Unlock() 147 | if element, ok := pder.sessions[sid]; ok { 148 | delete(pder.sessions, sid) 149 | pder.list.Remove(element) 150 | return nil 151 | } 152 | return nil 153 | } 154 | 155 | // SessionGC clean expired session stores in memory session 156 | func (pder *MemProvider) SessionGC() { 157 | pder.lock.RLock() 158 | for { 159 | element := pder.list.Back() 160 | if element == nil { 161 | break 162 | } 163 | if (element.Value.(*MemSessionStore).timeAccessed.Unix() + pder.maxlifetime) < time.Now().Unix() { 164 | pder.lock.RUnlock() 165 | pder.lock.Lock() 166 | pder.list.Remove(element) 167 | delete(pder.sessions, element.Value.(*MemSessionStore).sid) 168 | pder.lock.Unlock() 169 | pder.lock.RLock() 170 | } else { 171 | break 172 | } 173 | } 174 | pder.lock.RUnlock() 175 | } 176 | 177 | // SessionAll get count number of memory session 178 | func (pder *MemProvider) SessionAll() int { 179 | return pder.list.Len() 180 | } 181 | 182 | // SessionUpdate expand time of session store by id in memory session 183 | func (pder *MemProvider) SessionUpdate(sid string) error { 184 | pder.lock.Lock() 185 | defer pder.lock.Unlock() 186 | if element, ok := pder.sessions[sid]; ok { 187 | element.Value.(*MemSessionStore).timeAccessed = time.Now() 188 | pder.list.MoveToFront(element) 189 | return nil 190 | } 191 | return nil 192 | } 193 | 194 | func init() { 195 | Register("memory", mempder) 196 | } 197 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/toolbox/healthcheck.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package toolbox healthcheck 16 | // 17 | // type DatabaseCheck struct { 18 | // } 19 | // 20 | // func (dc *DatabaseCheck) Check() error { 21 | // if dc.isConnected() { 22 | // return nil 23 | // } else { 24 | // return errors.New("can't connect database") 25 | // } 26 | // } 27 | // 28 | // AddHealthCheck("database",&DatabaseCheck{}) 29 | // 30 | // more docs: http://beego.me/docs/module/toolbox.md 31 | package toolbox 32 | 33 | // AdminCheckList holds health checker map 34 | var AdminCheckList map[string]HealthChecker 35 | 36 | // HealthChecker health checker interface 37 | type HealthChecker interface { 38 | Check() error 39 | } 40 | 41 | // AddHealthCheck add health checker with name string 42 | func AddHealthCheck(name string, hc HealthChecker) { 43 | AdminCheckList[name] = hc 44 | } 45 | 46 | func init() { 47 | AdminCheckList = make(map[string]HealthChecker) 48 | } 49 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/toolbox/profile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package toolbox 16 | 17 | import ( 18 | "fmt" 19 | "io" 20 | "log" 21 | "os" 22 | "path" 23 | "runtime" 24 | "runtime/debug" 25 | "runtime/pprof" 26 | "strconv" 27 | "time" 28 | ) 29 | 30 | var startTime = time.Now() 31 | var pid int 32 | 33 | func init() { 34 | pid = os.Getpid() 35 | } 36 | 37 | // ProcessInput parse input command string 38 | func ProcessInput(input string, w io.Writer) { 39 | switch input { 40 | case "lookup goroutine": 41 | p := pprof.Lookup("goroutine") 42 | p.WriteTo(w, 2) 43 | case "lookup heap": 44 | p := pprof.Lookup("heap") 45 | p.WriteTo(w, 2) 46 | case "lookup threadcreate": 47 | p := pprof.Lookup("threadcreate") 48 | p.WriteTo(w, 2) 49 | case "lookup block": 50 | p := pprof.Lookup("block") 51 | p.WriteTo(w, 2) 52 | case "get cpuprof": 53 | GetCPUProfile(w) 54 | case "get memprof": 55 | MemProf(w) 56 | case "gc summary": 57 | PrintGCSummary(w) 58 | } 59 | } 60 | 61 | // MemProf record memory profile in pprof 62 | func MemProf(w io.Writer) { 63 | filename := "mem-" + strconv.Itoa(pid) + ".memprof" 64 | if f, err := os.Create(filename); err != nil { 65 | fmt.Fprintf(w, "create file %s error %s\n", filename, err.Error()) 66 | log.Fatal("record heap profile failed: ", err) 67 | } else { 68 | runtime.GC() 69 | pprof.WriteHeapProfile(f) 70 | f.Close() 71 | fmt.Fprintf(w, "create heap profile %s \n", filename) 72 | _, fl := path.Split(os.Args[0]) 73 | fmt.Fprintf(w, "Now you can use this to check it: go tool pprof %s %s\n", fl, filename) 74 | } 75 | } 76 | 77 | // GetCPUProfile start cpu profile monitor 78 | func GetCPUProfile(w io.Writer) { 79 | sec := 30 80 | filename := "cpu-" + strconv.Itoa(pid) + ".pprof" 81 | f, err := os.Create(filename) 82 | if err != nil { 83 | fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err) 84 | log.Fatal("record cpu profile failed: ", err) 85 | } 86 | pprof.StartCPUProfile(f) 87 | time.Sleep(time.Duration(sec) * time.Second) 88 | pprof.StopCPUProfile() 89 | 90 | fmt.Fprintf(w, "create cpu profile %s \n", filename) 91 | _, fl := path.Split(os.Args[0]) 92 | fmt.Fprintf(w, "Now you can use this to check it: go tool pprof %s %s\n", fl, filename) 93 | } 94 | 95 | // PrintGCSummary print gc information to io.Writer 96 | func PrintGCSummary(w io.Writer) { 97 | memStats := &runtime.MemStats{} 98 | runtime.ReadMemStats(memStats) 99 | gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)} 100 | debug.ReadGCStats(gcstats) 101 | 102 | printGC(memStats, gcstats, w) 103 | } 104 | 105 | func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats, w io.Writer) { 106 | 107 | if gcstats.NumGC > 0 { 108 | lastPause := gcstats.Pause[0] 109 | elapsed := time.Now().Sub(startTime) 110 | overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100 111 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() 112 | 113 | fmt.Fprintf(w, "NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n", 114 | gcstats.NumGC, 115 | toS(lastPause), 116 | toS(avg(gcstats.Pause)), 117 | overhead, 118 | toH(memStats.Alloc), 119 | toH(memStats.Sys), 120 | toH(uint64(allocatedRate)), 121 | toS(gcstats.PauseQuantiles[94]), 122 | toS(gcstats.PauseQuantiles[98]), 123 | toS(gcstats.PauseQuantiles[99])) 124 | } else { 125 | // while GC has disabled 126 | elapsed := time.Now().Sub(startTime) 127 | allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds() 128 | 129 | fmt.Fprintf(w, "Alloc:%s Sys:%s Alloc(Rate):%s/s\n", 130 | toH(memStats.Alloc), 131 | toH(memStats.Sys), 132 | toH(uint64(allocatedRate))) 133 | } 134 | } 135 | 136 | func avg(items []time.Duration) time.Duration { 137 | var sum time.Duration 138 | for _, item := range items { 139 | sum += item 140 | } 141 | return time.Duration(int64(sum) / int64(len(items))) 142 | } 143 | 144 | // format bytes number friendly 145 | func toH(bytes uint64) string { 146 | switch { 147 | case bytes < 1024: 148 | return fmt.Sprintf("%dB", bytes) 149 | case bytes < 1024*1024: 150 | return fmt.Sprintf("%.2fK", float64(bytes)/1024) 151 | case bytes < 1024*1024*1024: 152 | return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024) 153 | default: 154 | return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024) 155 | } 156 | } 157 | 158 | // short string format 159 | func toS(d time.Duration) string { 160 | 161 | u := uint64(d) 162 | if u < uint64(time.Second) { 163 | switch { 164 | case u == 0: 165 | return "0" 166 | case u < uint64(time.Microsecond): 167 | return fmt.Sprintf("%.2fns", float64(u)) 168 | case u < uint64(time.Millisecond): 169 | return fmt.Sprintf("%.2fus", float64(u)/1000) 170 | default: 171 | return fmt.Sprintf("%.2fms", float64(u)/1000/1000) 172 | } 173 | } else { 174 | switch { 175 | case u < uint64(time.Minute): 176 | return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000) 177 | case u < uint64(time.Hour): 178 | return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60) 179 | default: 180 | return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60) 181 | } 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/toolbox/statistics.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package toolbox 16 | 17 | import ( 18 | "fmt" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | // Statistics struct 24 | type Statistics struct { 25 | RequestURL string 26 | RequestController string 27 | RequestNum int64 28 | MinTime time.Duration 29 | MaxTime time.Duration 30 | TotalTime time.Duration 31 | } 32 | 33 | // URLMap contains several statistics struct to log different data 34 | type URLMap struct { 35 | lock sync.RWMutex 36 | LengthLimit int //limit the urlmap's length if it's equal to 0 there's no limit 37 | urlmap map[string]map[string]*Statistics 38 | } 39 | 40 | // AddStatistics add statistics task. 41 | // it needs request method, request url, request controller and statistics time duration 42 | func (m *URLMap) AddStatistics(requestMethod, requestURL, requestController string, requesttime time.Duration) { 43 | m.lock.Lock() 44 | defer m.lock.Unlock() 45 | if method, ok := m.urlmap[requestURL]; ok { 46 | if s, ok := method[requestMethod]; ok { 47 | s.RequestNum++ 48 | if s.MaxTime < requesttime { 49 | s.MaxTime = requesttime 50 | } 51 | if s.MinTime > requesttime { 52 | s.MinTime = requesttime 53 | } 54 | s.TotalTime += requesttime 55 | } else { 56 | nb := &Statistics{ 57 | RequestURL: requestURL, 58 | RequestController: requestController, 59 | RequestNum: 1, 60 | MinTime: requesttime, 61 | MaxTime: requesttime, 62 | TotalTime: requesttime, 63 | } 64 | m.urlmap[requestURL][requestMethod] = nb 65 | } 66 | 67 | } else { 68 | if m.LengthLimit > 0 && m.LengthLimit <= len(m.urlmap) { 69 | return 70 | } 71 | methodmap := make(map[string]*Statistics) 72 | nb := &Statistics{ 73 | RequestURL: requestURL, 74 | RequestController: requestController, 75 | RequestNum: 1, 76 | MinTime: requesttime, 77 | MaxTime: requesttime, 78 | TotalTime: requesttime, 79 | } 80 | methodmap[requestMethod] = nb 81 | m.urlmap[requestURL] = methodmap 82 | } 83 | } 84 | 85 | // GetMap put url statistics result in io.Writer 86 | func (m *URLMap) GetMap() map[string]interface{} { 87 | m.lock.RLock() 88 | defer m.lock.RUnlock() 89 | 90 | var fields = []string{"requestUrl", "method", "times", "used", "max used", "min used", "avg used"} 91 | 92 | var resultLists [][]string 93 | content := make(map[string]interface{}) 94 | content["Fields"] = fields 95 | 96 | for k, v := range m.urlmap { 97 | for kk, vv := range v { 98 | result := []string{ 99 | fmt.Sprintf("% -50s", k), 100 | fmt.Sprintf("% -10s", kk), 101 | fmt.Sprintf("% -16d", vv.RequestNum), 102 | fmt.Sprintf("% -16s", toS(vv.TotalTime)), 103 | fmt.Sprintf("% -16s", toS(vv.MaxTime)), 104 | fmt.Sprintf("% -16s", toS(vv.MinTime)), 105 | fmt.Sprintf("% -16s", toS(time.Duration(int64(vv.TotalTime)/vv.RequestNum))), 106 | } 107 | resultLists = append(resultLists, result) 108 | } 109 | } 110 | content["Data"] = resultLists 111 | return content 112 | } 113 | 114 | // GetMapData return all mapdata 115 | func (m *URLMap) GetMapData() []map[string]interface{} { 116 | 117 | var resultLists []map[string]interface{} 118 | 119 | for k, v := range m.urlmap { 120 | for kk, vv := range v { 121 | result := map[string]interface{}{ 122 | "request_url": k, 123 | "method": kk, 124 | "times": vv.RequestNum, 125 | "total_time": toS(vv.TotalTime), 126 | "max_time": toS(vv.MaxTime), 127 | "min_time": toS(vv.MinTime), 128 | "avg_time": toS(time.Duration(int64(vv.TotalTime) / vv.RequestNum)), 129 | } 130 | resultLists = append(resultLists, result) 131 | } 132 | } 133 | return resultLists 134 | } 135 | 136 | // StatisticsMap hosld global statistics data map 137 | var StatisticsMap *URLMap 138 | 139 | func init() { 140 | StatisticsMap = &URLMap{ 141 | urlmap: make(map[string]map[string]*Statistics), 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/utils/caller.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils 16 | 17 | import ( 18 | "reflect" 19 | "runtime" 20 | ) 21 | 22 | // GetFuncName get function name 23 | func GetFuncName(i interface{}) string { 24 | return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name() 25 | } 26 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/utils/file.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils 16 | 17 | import ( 18 | "bufio" 19 | "errors" 20 | "io" 21 | "os" 22 | "path/filepath" 23 | "regexp" 24 | ) 25 | 26 | // SelfPath gets compiled executable file absolute path 27 | func SelfPath() string { 28 | path, _ := filepath.Abs(os.Args[0]) 29 | return path 30 | } 31 | 32 | // SelfDir gets compiled executable file directory 33 | func SelfDir() string { 34 | return filepath.Dir(SelfPath()) 35 | } 36 | 37 | // FileExists reports whether the named file or directory exists. 38 | func FileExists(name string) bool { 39 | if _, err := os.Stat(name); err != nil { 40 | if os.IsNotExist(err) { 41 | return false 42 | } 43 | } 44 | return true 45 | } 46 | 47 | // SearchFile Search a file in paths. 48 | // this is often used in search config file in /etc ~/ 49 | func SearchFile(filename string, paths ...string) (fullpath string, err error) { 50 | for _, path := range paths { 51 | if fullpath = filepath.Join(path, filename); FileExists(fullpath) { 52 | return 53 | } 54 | } 55 | err = errors.New(fullpath + " not found in paths") 56 | return 57 | } 58 | 59 | // GrepFile like command grep -E 60 | // for example: GrepFile(`^hello`, "hello.txt") 61 | // \n is striped while read 62 | func GrepFile(patten string, filename string) (lines []string, err error) { 63 | re, err := regexp.Compile(patten) 64 | if err != nil { 65 | return 66 | } 67 | 68 | fd, err := os.Open(filename) 69 | if err != nil { 70 | return 71 | } 72 | lines = make([]string, 0) 73 | reader := bufio.NewReader(fd) 74 | prefix := "" 75 | isLongLine := false 76 | for { 77 | byteLine, isPrefix, er := reader.ReadLine() 78 | if er != nil && er != io.EOF { 79 | return nil, er 80 | } 81 | if er == io.EOF { 82 | break 83 | } 84 | line := string(byteLine) 85 | if isPrefix { 86 | prefix += line 87 | continue 88 | } else { 89 | isLongLine = true 90 | } 91 | 92 | line = prefix + line 93 | if isLongLine { 94 | prefix = "" 95 | } 96 | if re.MatchString(line) { 97 | lines = append(lines, line) 98 | } 99 | } 100 | return lines, nil 101 | } 102 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/utils/rand.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils 16 | 17 | import ( 18 | "crypto/rand" 19 | r "math/rand" 20 | "time" 21 | ) 22 | 23 | // RandomCreateBytes generate random []byte by specify chars. 24 | func RandomCreateBytes(n int, alphabets ...byte) []byte { 25 | const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 26 | var bytes = make([]byte, n) 27 | var randby bool 28 | if num, err := rand.Read(bytes); num != n || err != nil { 29 | r.Seed(time.Now().UnixNano()) 30 | randby = true 31 | } 32 | for i, b := range bytes { 33 | if len(alphabets) == 0 { 34 | if randby { 35 | bytes[i] = alphanum[r.Intn(len(alphanum))] 36 | } else { 37 | bytes[i] = alphanum[b%byte(len(alphanum))] 38 | } 39 | } else { 40 | if randby { 41 | bytes[i] = alphabets[r.Intn(len(alphabets))] 42 | } else { 43 | bytes[i] = alphabets[b%byte(len(alphabets))] 44 | } 45 | } 46 | } 47 | return bytes 48 | } 49 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/utils/safemap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils 16 | 17 | import ( 18 | "sync" 19 | ) 20 | 21 | // BeeMap is a map with lock 22 | type BeeMap struct { 23 | lock *sync.RWMutex 24 | bm map[interface{}]interface{} 25 | } 26 | 27 | // NewBeeMap return new safemap 28 | func NewBeeMap() *BeeMap { 29 | return &BeeMap{ 30 | lock: new(sync.RWMutex), 31 | bm: make(map[interface{}]interface{}), 32 | } 33 | } 34 | 35 | // Get from maps return the k's value 36 | func (m *BeeMap) Get(k interface{}) interface{} { 37 | m.lock.RLock() 38 | defer m.lock.RUnlock() 39 | if val, ok := m.bm[k]; ok { 40 | return val 41 | } 42 | return nil 43 | } 44 | 45 | // Set Maps the given key and value. Returns false 46 | // if the key is already in the map and changes nothing. 47 | func (m *BeeMap) Set(k interface{}, v interface{}) bool { 48 | m.lock.Lock() 49 | defer m.lock.Unlock() 50 | if val, ok := m.bm[k]; !ok { 51 | m.bm[k] = v 52 | } else if val != v { 53 | m.bm[k] = v 54 | } else { 55 | return false 56 | } 57 | return true 58 | } 59 | 60 | // Check Returns true if k is exist in the map. 61 | func (m *BeeMap) Check(k interface{}) bool { 62 | m.lock.RLock() 63 | defer m.lock.RUnlock() 64 | if _, ok := m.bm[k]; !ok { 65 | return false 66 | } 67 | return true 68 | } 69 | 70 | // Delete the given key and value. 71 | func (m *BeeMap) Delete(k interface{}) { 72 | m.lock.Lock() 73 | defer m.lock.Unlock() 74 | delete(m.bm, k) 75 | } 76 | 77 | // Items returns all items in safemap. 78 | func (m *BeeMap) Items() map[interface{}]interface{} { 79 | m.lock.RLock() 80 | defer m.lock.RUnlock() 81 | r := make(map[interface{}]interface{}) 82 | for k, v := range m.bm { 83 | r[k] = v 84 | } 85 | return r 86 | } 87 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/astaxie/beego/utils/slice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils 16 | 17 | import ( 18 | "math/rand" 19 | "time" 20 | ) 21 | 22 | type reducetype func(interface{}) interface{} 23 | type filtertype func(interface{}) bool 24 | 25 | // InSlice checks given string in string slice or not. 26 | func InSlice(v string, sl []string) bool { 27 | for _, vv := range sl { 28 | if vv == v { 29 | return true 30 | } 31 | } 32 | return false 33 | } 34 | 35 | // InSliceIface checks given interface in interface slice. 36 | func InSliceIface(v interface{}, sl []interface{}) bool { 37 | for _, vv := range sl { 38 | if vv == v { 39 | return true 40 | } 41 | } 42 | return false 43 | } 44 | 45 | // SliceRandList generate an int slice from min to max. 46 | func SliceRandList(min, max int) []int { 47 | if max < min { 48 | min, max = max, min 49 | } 50 | length := max - min + 1 51 | t0 := time.Now() 52 | rand.Seed(int64(t0.Nanosecond())) 53 | list := rand.Perm(length) 54 | for index := range list { 55 | list[index] += min 56 | } 57 | return list 58 | } 59 | 60 | // SliceMerge merges interface slices to one slice. 61 | func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) { 62 | c = append(slice1, slice2...) 63 | return 64 | } 65 | 66 | // SliceReduce generates a new slice after parsing every value by reduce function 67 | func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) { 68 | for _, v := range slice { 69 | dslice = append(dslice, a(v)) 70 | } 71 | return 72 | } 73 | 74 | // SliceRand returns random one from slice. 75 | func SliceRand(a []interface{}) (b interface{}) { 76 | randnum := rand.Intn(len(a)) 77 | b = a[randnum] 78 | return 79 | } 80 | 81 | // SliceSum sums all values in int64 slice. 82 | func SliceSum(intslice []int64) (sum int64) { 83 | for _, v := range intslice { 84 | sum += v 85 | } 86 | return 87 | } 88 | 89 | // SliceFilter generates a new slice after filter function. 90 | func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) { 91 | for _, v := range slice { 92 | if a(v) { 93 | ftslice = append(ftslice, v) 94 | } 95 | } 96 | return 97 | } 98 | 99 | // SliceDiff returns diff slice of slice1 - slice2. 100 | func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) { 101 | for _, v := range slice1 { 102 | if !InSliceIface(v, slice2) { 103 | diffslice = append(diffslice, v) 104 | } 105 | } 106 | return 107 | } 108 | 109 | // SliceIntersect returns slice that are present in all the slice1 and slice2. 110 | func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) { 111 | for _, v := range slice1 { 112 | if InSliceIface(v, slice2) { 113 | diffslice = append(diffslice, v) 114 | } 115 | } 116 | return 117 | } 118 | 119 | // SliceChunk separates one slice to some sized slice. 120 | func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) { 121 | if size >= len(slice) { 122 | chunkslice = append(chunkslice, slice) 123 | return 124 | } 125 | end := size 126 | for i := 0; i <= (len(slice) - size); i += size { 127 | chunkslice = append(chunkslice, slice[i:end]) 128 | end += size 129 | } 130 | return 131 | } 132 | 133 | // SliceRange generates a new slice from begin to end with step duration of int64 number. 134 | func SliceRange(start, end, step int64) (intslice []int64) { 135 | for i := start; i <= end; i += step { 136 | intslice = append(intslice, i) 137 | } 138 | return 139 | } 140 | 141 | // SlicePad prepends size number of val into slice. 142 | func SlicePad(slice []interface{}, size int, val interface{}) []interface{} { 143 | if size <= len(slice) { 144 | return slice 145 | } 146 | for i := 0; i < (size - len(slice)); i++ { 147 | slice = append(slice, val) 148 | } 149 | return slice 150 | } 151 | 152 | // SliceUnique cleans repeated values in slice. 153 | func SliceUnique(slice []interface{}) (uniqueslice []interface{}) { 154 | for _, v := range slice { 155 | if !InSliceIface(v, uniqueslice) { 156 | uniqueslice = append(uniqueslice, v) 157 | } 158 | } 159 | return 160 | } 161 | 162 | // SliceShuffle shuffles a slice. 163 | func SliceShuffle(slice []interface{}) []interface{} { 164 | for i := 0; i < len(slice); i++ { 165 | a := rand.Intn(len(slice)) 166 | b := rand.Intn(len(slice)) 167 | slice[a], slice[b] = slice[b], slice[a] 168 | } 169 | return slice 170 | } 171 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/garyburd/redigo/internal/commandinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package internal 16 | 17 | import ( 18 | "strings" 19 | ) 20 | 21 | const ( 22 | WatchState = 1 << iota 23 | MultiState 24 | SubscribeState 25 | MonitorState 26 | ) 27 | 28 | type CommandInfo struct { 29 | Set, Clear int 30 | } 31 | 32 | var commandInfos = map[string]CommandInfo{ 33 | "WATCH": {Set: WatchState}, 34 | "UNWATCH": {Clear: WatchState}, 35 | "MULTI": {Set: MultiState}, 36 | "EXEC": {Clear: WatchState | MultiState}, 37 | "DISCARD": {Clear: WatchState | MultiState}, 38 | "PSUBSCRIBE": {Set: SubscribeState}, 39 | "SUBSCRIBE": {Set: SubscribeState}, 40 | "MONITOR": {Set: MonitorState}, 41 | } 42 | 43 | func init() { 44 | for n, ci := range commandInfos { 45 | commandInfos[strings.ToLower(n)] = ci 46 | } 47 | } 48 | 49 | func LookupCommandInfo(commandName string) CommandInfo { 50 | if ci, ok := commandInfos[commandName]; ok { 51 | return ci 52 | } 53 | return commandInfos[strings.ToUpper(commandName)] 54 | } 55 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/garyburd/redigo/redis/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "bytes" 19 | "fmt" 20 | "log" 21 | ) 22 | 23 | // NewLoggingConn returns a logging wrapper around a connection. 24 | func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn { 25 | if prefix != "" { 26 | prefix = prefix + "." 27 | } 28 | return &loggingConn{conn, logger, prefix} 29 | } 30 | 31 | type loggingConn struct { 32 | Conn 33 | logger *log.Logger 34 | prefix string 35 | } 36 | 37 | func (c *loggingConn) Close() error { 38 | err := c.Conn.Close() 39 | var buf bytes.Buffer 40 | fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err) 41 | c.logger.Output(2, buf.String()) 42 | return err 43 | } 44 | 45 | func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) { 46 | const chop = 32 47 | switch v := v.(type) { 48 | case []byte: 49 | if len(v) > chop { 50 | fmt.Fprintf(buf, "%q...", v[:chop]) 51 | } else { 52 | fmt.Fprintf(buf, "%q", v) 53 | } 54 | case string: 55 | if len(v) > chop { 56 | fmt.Fprintf(buf, "%q...", v[:chop]) 57 | } else { 58 | fmt.Fprintf(buf, "%q", v) 59 | } 60 | case []interface{}: 61 | if len(v) == 0 { 62 | buf.WriteString("[]") 63 | } else { 64 | sep := "[" 65 | fin := "]" 66 | if len(v) > chop { 67 | v = v[:chop] 68 | fin = "...]" 69 | } 70 | for _, vv := range v { 71 | buf.WriteString(sep) 72 | c.printValue(buf, vv) 73 | sep = ", " 74 | } 75 | buf.WriteString(fin) 76 | } 77 | default: 78 | fmt.Fprint(buf, v) 79 | } 80 | } 81 | 82 | func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) { 83 | var buf bytes.Buffer 84 | fmt.Fprintf(&buf, "%s%s(", c.prefix, method) 85 | if method != "Receive" { 86 | buf.WriteString(commandName) 87 | for _, arg := range args { 88 | buf.WriteString(", ") 89 | c.printValue(&buf, arg) 90 | } 91 | } 92 | buf.WriteString(") -> (") 93 | if method != "Send" { 94 | c.printValue(&buf, reply) 95 | buf.WriteString(", ") 96 | } 97 | fmt.Fprintf(&buf, "%v)", err) 98 | c.logger.Output(3, buf.String()) 99 | } 100 | 101 | func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) { 102 | reply, err := c.Conn.Do(commandName, args...) 103 | c.print("Do", commandName, args, reply, err) 104 | return reply, err 105 | } 106 | 107 | func (c *loggingConn) Send(commandName string, args ...interface{}) error { 108 | err := c.Conn.Send(commandName, args...) 109 | c.print("Send", commandName, args, nil, err) 110 | return err 111 | } 112 | 113 | func (c *loggingConn) Receive() (interface{}, error) { 114 | reply, err := c.Conn.Receive() 115 | c.print("Receive", "", nil, reply, err) 116 | return reply, err 117 | } 118 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/garyburd/redigo/redis/pubsub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import "errors" 18 | 19 | // Subscription represents a subscribe or unsubscribe notification. 20 | type Subscription struct { 21 | 22 | // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe" 23 | Kind string 24 | 25 | // The channel that was changed. 26 | Channel string 27 | 28 | // The current number of subscriptions for connection. 29 | Count int 30 | } 31 | 32 | // Message represents a message notification. 33 | type Message struct { 34 | 35 | // The originating channel. 36 | Channel string 37 | 38 | // The message data. 39 | Data []byte 40 | } 41 | 42 | // PMessage represents a pmessage notification. 43 | type PMessage struct { 44 | 45 | // The matched pattern. 46 | Pattern string 47 | 48 | // The originating channel. 49 | Channel string 50 | 51 | // The message data. 52 | Data []byte 53 | } 54 | 55 | // Pong represents a pubsub pong notification. 56 | type Pong struct { 57 | Data string 58 | } 59 | 60 | // PubSubConn wraps a Conn with convenience methods for subscribers. 61 | type PubSubConn struct { 62 | Conn Conn 63 | } 64 | 65 | // Close closes the connection. 66 | func (c PubSubConn) Close() error { 67 | return c.Conn.Close() 68 | } 69 | 70 | // Subscribe subscribes the connection to the specified channels. 71 | func (c PubSubConn) Subscribe(channel ...interface{}) error { 72 | c.Conn.Send("SUBSCRIBE", channel...) 73 | return c.Conn.Flush() 74 | } 75 | 76 | // PSubscribe subscribes the connection to the given patterns. 77 | func (c PubSubConn) PSubscribe(channel ...interface{}) error { 78 | c.Conn.Send("PSUBSCRIBE", channel...) 79 | return c.Conn.Flush() 80 | } 81 | 82 | // Unsubscribe unsubscribes the connection from the given channels, or from all 83 | // of them if none is given. 84 | func (c PubSubConn) Unsubscribe(channel ...interface{}) error { 85 | c.Conn.Send("UNSUBSCRIBE", channel...) 86 | return c.Conn.Flush() 87 | } 88 | 89 | // PUnsubscribe unsubscribes the connection from the given patterns, or from all 90 | // of them if none is given. 91 | func (c PubSubConn) PUnsubscribe(channel ...interface{}) error { 92 | c.Conn.Send("PUNSUBSCRIBE", channel...) 93 | return c.Conn.Flush() 94 | } 95 | 96 | // Ping sends a PING to the server with the specified data. 97 | func (c PubSubConn) Ping(data string) error { 98 | c.Conn.Send("PING", data) 99 | return c.Conn.Flush() 100 | } 101 | 102 | // Receive returns a pushed message as a Subscription, Message, PMessage, Pong 103 | // or error. The return value is intended to be used directly in a type switch 104 | // as illustrated in the PubSubConn example. 105 | func (c PubSubConn) Receive() interface{} { 106 | reply, err := Values(c.Conn.Receive()) 107 | if err != nil { 108 | return err 109 | } 110 | 111 | var kind string 112 | reply, err = Scan(reply, &kind) 113 | if err != nil { 114 | return err 115 | } 116 | 117 | switch kind { 118 | case "message": 119 | var m Message 120 | if _, err := Scan(reply, &m.Channel, &m.Data); err != nil { 121 | return err 122 | } 123 | return m 124 | case "pmessage": 125 | var pm PMessage 126 | if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil { 127 | return err 128 | } 129 | return pm 130 | case "subscribe", "psubscribe", "unsubscribe", "punsubscribe": 131 | s := Subscription{Kind: kind} 132 | if _, err := Scan(reply, &s.Channel, &s.Count); err != nil { 133 | return err 134 | } 135 | return s 136 | case "pong": 137 | var p Pong 138 | if _, err := Scan(reply, &p.Data); err != nil { 139 | return err 140 | } 141 | return p 142 | } 143 | return errors.New("redigo: unknown pubsub notification") 144 | } 145 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/garyburd/redigo/redis/redis.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | // Error represents an error returned in a command reply. 18 | type Error string 19 | 20 | func (err Error) Error() string { return string(err) } 21 | 22 | // Conn represents a connection to a Redis server. 23 | type Conn interface { 24 | // Close closes the connection. 25 | Close() error 26 | 27 | // Err returns a non-nil value if the connection is broken. The returned 28 | // value is either the first non-nil value returned from the underlying 29 | // network connection or a protocol parsing error. Applications should 30 | // close broken connections. 31 | Err() error 32 | 33 | // Do sends a command to the server and returns the received reply. 34 | Do(commandName string, args ...interface{}) (reply interface{}, err error) 35 | 36 | // Send writes the command to the client's output buffer. 37 | Send(commandName string, args ...interface{}) error 38 | 39 | // Flush flushes the output buffer to the Redis server. 40 | Flush() error 41 | 42 | // Receive receives a single reply from the Redis server 43 | Receive() (reply interface{}, err error) 44 | } 45 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/garyburd/redigo/redis/script.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "crypto/sha1" 19 | "encoding/hex" 20 | "io" 21 | "strings" 22 | ) 23 | 24 | // Script encapsulates the source, hash and key count for a Lua script. See 25 | // http://redis.io/commands/eval for information on scripts in Redis. 26 | type Script struct { 27 | keyCount int 28 | src string 29 | hash string 30 | } 31 | 32 | // NewScript returns a new script object. If keyCount is greater than or equal 33 | // to zero, then the count is automatically inserted in the EVAL command 34 | // argument list. If keyCount is less than zero, then the application supplies 35 | // the count as the first value in the keysAndArgs argument to the Do, Send and 36 | // SendHash methods. 37 | func NewScript(keyCount int, src string) *Script { 38 | h := sha1.New() 39 | io.WriteString(h, src) 40 | return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))} 41 | } 42 | 43 | func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} { 44 | var args []interface{} 45 | if s.keyCount < 0 { 46 | args = make([]interface{}, 1+len(keysAndArgs)) 47 | args[0] = spec 48 | copy(args[1:], keysAndArgs) 49 | } else { 50 | args = make([]interface{}, 2+len(keysAndArgs)) 51 | args[0] = spec 52 | args[1] = s.keyCount 53 | copy(args[2:], keysAndArgs) 54 | } 55 | return args 56 | } 57 | 58 | // Do evaluates the script. Under the covers, Do optimistically evaluates the 59 | // script using the EVALSHA command. If the command fails because the script is 60 | // not loaded, then Do evaluates the script using the EVAL command (thus 61 | // causing the script to load). 62 | func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) { 63 | v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...) 64 | if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") { 65 | v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...) 66 | } 67 | return v, err 68 | } 69 | 70 | // SendHash evaluates the script without waiting for the reply. The script is 71 | // evaluated with the EVALSHA command. The application must ensure that the 72 | // script is loaded by a previous call to Send, Do or Load methods. 73 | func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error { 74 | return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...) 75 | } 76 | 77 | // Send evaluates the script without waiting for the reply. 78 | func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error { 79 | return c.Send("EVAL", s.args(s.src, keysAndArgs)...) 80 | } 81 | 82 | // Load loads the script without evaluating it. 83 | func (s *Script) Load(c Conn) error { 84 | _, err := c.Do("SCRIPT", "LOAD", s.src) 85 | return err 86 | } 87 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go: 4 | - 1.2 5 | - 1.3 6 | - 1.4 7 | - 1.5 8 | - 1.6 9 | - tip 10 | 11 | before_script: 12 | - mysql -e 'create database gotest;' 13 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Go-MySQL-Driver authors for copyright purposes. 2 | 3 | # If you are submitting a patch, please add your name or the name of the 4 | # organization which holds the copyright to this list in alphabetical order. 5 | 6 | # Names should be added to this file as 7 | # Name 8 | # The email address is not required for organizations. 9 | # Please keep the list sorted. 10 | 11 | 12 | # Individual Persons 13 | 14 | Aaron Hopkins 15 | Arne Hormann 16 | Carlos Nieto 17 | Chris Moos 18 | Daniel Nichter 19 | Daniël van Eeden 20 | DisposaBoy 21 | Frederick Mayle 22 | Gustavo Kristic 23 | Hanno Braun 24 | Henri Yandell 25 | Hirotaka Yamamoto 26 | INADA Naoki 27 | James Harr 28 | Jian Zhen 29 | Joshua Prunier 30 | Julien Lefevre 31 | Julien Schmidt 32 | Kamil Dziedzic 33 | Kevin Malachowski 34 | Leonardo YongUk Kim 35 | Luca Looz 36 | Lucas Liu 37 | Luke Scott 38 | Michael Woolnough 39 | Nicola Peduzzi 40 | Paul Bonser 41 | Runrioter Wung 42 | Soroush Pour 43 | Stan Putrya 44 | Stanley Gunawan 45 | Xiaobing Jiang 46 | Xiuming Chen 47 | 48 | # Organizations 49 | 50 | Barracuda Networks, Inc. 51 | Google Inc. 52 | Stripe Inc. 53 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## HEAD 2 | 3 | Changes: 4 | 5 | - Go 1.1 is no longer supported 6 | - Use decimals field from MySQL to format time types (#249) 7 | - Buffer optimizations (#269) 8 | - TLS ServerName defaults to the host (#283) 9 | 10 | Bugfixes: 11 | 12 | - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249) 13 | - Fixed handling of queries without columns and rows (#255) 14 | - Fixed a panic when SetKeepAlive() failed (#298) 15 | - Support receiving ERR packet while reading rows (#321) 16 | - Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349) 17 | - Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356) 18 | - Actually zero out bytes in handshake response (#378) 19 | - Fixed race condition in registering LOAD DATA INFILE handler (#383) 20 | - Fixed tests with MySQL 5.7.9+ (#380) 21 | - QueryUnescape TLS config names (#397) 22 | - Fixed "broken pipe" error by writing to closed socket (#390) 23 | 24 | New Features: 25 | - Support for returning table alias on Columns() (#289, #359, #382) 26 | - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318) 27 | - Support for uint64 parameters with high bit set (#332, #345) 28 | - Cleartext authentication plugin support (#327) 29 | 30 | 31 | 32 | ## Version 1.2 (2014-06-03) 33 | 34 | Changes: 35 | 36 | - We switched back to a "rolling release". `go get` installs the current master branch again 37 | - Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver 38 | - Exported errors to allow easy checking from application code 39 | - Enabled TCP Keepalives on TCP connections 40 | - Optimized INFILE handling (better buffer size calculation, lazy init, ...) 41 | - The DSN parser also checks for a missing separating slash 42 | - Faster binary date / datetime to string formatting 43 | - Also exported the MySQLWarning type 44 | - mysqlConn.Close returns the first error encountered instead of ignoring all errors 45 | - writePacket() automatically writes the packet size to the header 46 | - readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets 47 | 48 | New Features: 49 | 50 | - `RegisterDial` allows the usage of a custom dial function to establish the network connection 51 | - Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter 52 | - Logging of critical errors is configurable with `SetLogger` 53 | - Google CloudSQL support 54 | 55 | Bugfixes: 56 | 57 | - Allow more than 32 parameters in prepared statements 58 | - Various old_password fixes 59 | - Fixed TestConcurrent test to pass Go's race detection 60 | - Fixed appendLengthEncodedInteger for large numbers 61 | - Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo) 62 | 63 | 64 | ## Version 1.1 (2013-11-02) 65 | 66 | Changes: 67 | 68 | - Go-MySQL-Driver now requires Go 1.1 69 | - Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore 70 | - Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors 71 | - `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")` 72 | - DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'. 73 | - Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries 74 | - Optimized the buffer for reading 75 | - stmt.Query now caches column metadata 76 | - New Logo 77 | - Changed the copyright header to include all contributors 78 | - Improved the LOAD INFILE documentation 79 | - The driver struct is now exported to make the driver directly accessible 80 | - Refactored the driver tests 81 | - Added more benchmarks and moved all to a separate file 82 | - Other small refactoring 83 | 84 | New Features: 85 | 86 | - Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure 87 | - Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs 88 | - Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used 89 | 90 | Bugfixes: 91 | 92 | - Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification 93 | - Convert to DB timezone when inserting `time.Time` 94 | - Splitted packets (more than 16MB) are now merged correctly 95 | - Fixed false positive `io.EOF` errors when the data was fully read 96 | - Avoid panics on reuse of closed connections 97 | - Fixed empty string producing false nil values 98 | - Fixed sign byte for positive TIME fields 99 | 100 | 101 | ## Version 1.0 (2013-05-14) 102 | 103 | Initial Release 104 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | ## Reporting Issues 4 | 5 | Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed). 6 | 7 | ## Contributing Code 8 | 9 | By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file. 10 | Don't forget to add yourself to the AUTHORS file. 11 | 12 | ### Code Review 13 | 14 | Everyone is invited to review and comment on pull requests. 15 | If it looks fine to you, comment with "LGTM" (Looks good to me). 16 | 17 | If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes. 18 | 19 | Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM". 20 | 21 | ## Development Ideas 22 | 23 | If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page. 24 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Issue description 2 | Tell us what should happen and what happens instead 3 | 4 | ### Example code 5 | ```go 6 | If possible, please enter some example code here to reproduce the issue. 7 | ``` 8 | 9 | ### Error log 10 | ``` 11 | If you have an error log, please paste it here. 12 | ``` 13 | 14 | ### Configuration 15 | *Driver version (or git SHA):* 16 | 17 | *Go version:* run `go version` in your console 18 | 19 | *Server version:* E.g. MySQL 5.6, MariaDB 10.0.20 20 | 21 | *Server OS:* E.g. Debian 8.1 (Jessie), Windows 10 22 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | Please explain the changes you made here. 3 | 4 | ### Checklist 5 | - [ ] Code compiles correctly 6 | - [ ] Created tests which fail without the change (if possible) 7 | - [ ] All tests passing 8 | - [ ] Extended the README / documentation, if necessary 9 | - [ ] Added myself / the copyright holder to the AUTHORS file 10 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/appengine.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | // +build appengine 10 | 11 | package mysql 12 | 13 | import ( 14 | "appengine/cloudsql" 15 | ) 16 | 17 | func init() { 18 | RegisterDial("cloudsql", cloudsql.Dial) 19 | } 20 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/buffer.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "io" 13 | "net" 14 | "time" 15 | ) 16 | 17 | const defaultBufSize = 4096 18 | 19 | // A buffer which is used for both reading and writing. 20 | // This is possible since communication on each connection is synchronous. 21 | // In other words, we can't write and read simultaneously on the same connection. 22 | // The buffer is similar to bufio.Reader / Writer but zero-copy-ish 23 | // Also highly optimized for this particular use case. 24 | type buffer struct { 25 | buf []byte 26 | nc net.Conn 27 | idx int 28 | length int 29 | timeout time.Duration 30 | } 31 | 32 | func newBuffer(nc net.Conn) buffer { 33 | var b [defaultBufSize]byte 34 | return buffer{ 35 | buf: b[:], 36 | nc: nc, 37 | } 38 | } 39 | 40 | // fill reads into the buffer until at least _need_ bytes are in it 41 | func (b *buffer) fill(need int) error { 42 | n := b.length 43 | 44 | // move existing data to the beginning 45 | if n > 0 && b.idx > 0 { 46 | copy(b.buf[0:n], b.buf[b.idx:]) 47 | } 48 | 49 | // grow buffer if necessary 50 | // TODO: let the buffer shrink again at some point 51 | // Maybe keep the org buf slice and swap back? 52 | if need > len(b.buf) { 53 | // Round up to the next multiple of the default size 54 | newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize) 55 | copy(newBuf, b.buf) 56 | b.buf = newBuf 57 | } 58 | 59 | b.idx = 0 60 | 61 | for { 62 | if b.timeout > 0 { 63 | if err := b.nc.SetReadDeadline(time.Now().Add(b.timeout)); err != nil { 64 | return err 65 | } 66 | } 67 | 68 | nn, err := b.nc.Read(b.buf[n:]) 69 | n += nn 70 | 71 | switch err { 72 | case nil: 73 | if n < need { 74 | continue 75 | } 76 | b.length = n 77 | return nil 78 | 79 | case io.EOF: 80 | if n >= need { 81 | b.length = n 82 | return nil 83 | } 84 | return io.ErrUnexpectedEOF 85 | 86 | default: 87 | return err 88 | } 89 | } 90 | } 91 | 92 | // returns next N bytes from buffer. 93 | // The returned slice is only guaranteed to be valid until the next read 94 | func (b *buffer) readNext(need int) ([]byte, error) { 95 | if b.length < need { 96 | // refill 97 | if err := b.fill(need); err != nil { 98 | return nil, err 99 | } 100 | } 101 | 102 | offset := b.idx 103 | b.idx += need 104 | b.length -= need 105 | return b.buf[offset:b.idx], nil 106 | } 107 | 108 | // returns a buffer with the requested size. 109 | // If possible, a slice from the existing buffer is returned. 110 | // Otherwise a bigger buffer is made. 111 | // Only one buffer (total) can be used at a time. 112 | func (b *buffer) takeBuffer(length int) []byte { 113 | if b.length > 0 { 114 | return nil 115 | } 116 | 117 | // test (cheap) general case first 118 | if length <= defaultBufSize || length <= cap(b.buf) { 119 | return b.buf[:length] 120 | } 121 | 122 | if length < maxPacketSize { 123 | b.buf = make([]byte, length) 124 | return b.buf 125 | } 126 | return make([]byte, length) 127 | } 128 | 129 | // shortcut which can be used if the requested buffer is guaranteed to be 130 | // smaller than defaultBufSize 131 | // Only one buffer (total) can be used at a time. 132 | func (b *buffer) takeSmallBuffer(length int) []byte { 133 | if b.length == 0 { 134 | return b.buf[:length] 135 | } 136 | return nil 137 | } 138 | 139 | // takeCompleteBuffer returns the complete existing buffer. 140 | // This can be used if the necessary buffer size is unknown. 141 | // Only one buffer (total) can be used at a time. 142 | func (b *buffer) takeCompleteBuffer() []byte { 143 | if b.length == 0 { 144 | return b.buf 145 | } 146 | return nil 147 | } 148 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/const.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | const ( 12 | minProtocolVersion byte = 10 13 | maxPacketSize = 1<<24 - 1 14 | timeFormat = "2006-01-02 15:04:05.999999" 15 | ) 16 | 17 | // MySQL constants documentation: 18 | // http://dev.mysql.com/doc/internals/en/client-server-protocol.html 19 | 20 | const ( 21 | iOK byte = 0x00 22 | iLocalInFile byte = 0xfb 23 | iEOF byte = 0xfe 24 | iERR byte = 0xff 25 | ) 26 | 27 | // https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags 28 | type clientFlag uint32 29 | 30 | const ( 31 | clientLongPassword clientFlag = 1 << iota 32 | clientFoundRows 33 | clientLongFlag 34 | clientConnectWithDB 35 | clientNoSchema 36 | clientCompress 37 | clientODBC 38 | clientLocalFiles 39 | clientIgnoreSpace 40 | clientProtocol41 41 | clientInteractive 42 | clientSSL 43 | clientIgnoreSIGPIPE 44 | clientTransactions 45 | clientReserved 46 | clientSecureConn 47 | clientMultiStatements 48 | clientMultiResults 49 | clientPSMultiResults 50 | clientPluginAuth 51 | clientConnectAttrs 52 | clientPluginAuthLenEncClientData 53 | clientCanHandleExpiredPasswords 54 | clientSessionTrack 55 | clientDeprecateEOF 56 | ) 57 | 58 | const ( 59 | comQuit byte = iota + 1 60 | comInitDB 61 | comQuery 62 | comFieldList 63 | comCreateDB 64 | comDropDB 65 | comRefresh 66 | comShutdown 67 | comStatistics 68 | comProcessInfo 69 | comConnect 70 | comProcessKill 71 | comDebug 72 | comPing 73 | comTime 74 | comDelayedInsert 75 | comChangeUser 76 | comBinlogDump 77 | comTableDump 78 | comConnectOut 79 | comRegisterSlave 80 | comStmtPrepare 81 | comStmtExecute 82 | comStmtSendLongData 83 | comStmtClose 84 | comStmtReset 85 | comSetOption 86 | comStmtFetch 87 | ) 88 | 89 | // https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnType 90 | const ( 91 | fieldTypeDecimal byte = iota 92 | fieldTypeTiny 93 | fieldTypeShort 94 | fieldTypeLong 95 | fieldTypeFloat 96 | fieldTypeDouble 97 | fieldTypeNULL 98 | fieldTypeTimestamp 99 | fieldTypeLongLong 100 | fieldTypeInt24 101 | fieldTypeDate 102 | fieldTypeTime 103 | fieldTypeDateTime 104 | fieldTypeYear 105 | fieldTypeNewDate 106 | fieldTypeVarChar 107 | fieldTypeBit 108 | ) 109 | const ( 110 | fieldTypeJSON byte = iota + 0xf5 111 | fieldTypeNewDecimal 112 | fieldTypeEnum 113 | fieldTypeSet 114 | fieldTypeTinyBLOB 115 | fieldTypeMediumBLOB 116 | fieldTypeLongBLOB 117 | fieldTypeBLOB 118 | fieldTypeVarString 119 | fieldTypeString 120 | fieldTypeGeometry 121 | ) 122 | 123 | type fieldFlag uint16 124 | 125 | const ( 126 | flagNotNULL fieldFlag = 1 << iota 127 | flagPriKey 128 | flagUniqueKey 129 | flagMultipleKey 130 | flagBLOB 131 | flagUnsigned 132 | flagZeroFill 133 | flagBinary 134 | flagEnum 135 | flagAutoIncrement 136 | flagTimestamp 137 | flagSet 138 | flagUnknown1 139 | flagUnknown2 140 | flagUnknown3 141 | flagUnknown4 142 | ) 143 | 144 | // http://dev.mysql.com/doc/internals/en/status-flags.html 145 | type statusFlag uint16 146 | 147 | const ( 148 | statusInTrans statusFlag = 1 << iota 149 | statusInAutocommit 150 | statusReserved // Not in documentation 151 | statusMoreResultsExists 152 | statusNoGoodIndexUsed 153 | statusNoIndexUsed 154 | statusCursorExists 155 | statusLastRowSent 156 | statusDbDropped 157 | statusNoBackslashEscapes 158 | statusMetadataChanged 159 | statusQueryWasSlow 160 | statusPsOutParams 161 | statusInTransReadonly 162 | statusSessionStateChanged 163 | ) 164 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 2 | // 3 | // This Source Code Form is subject to the terms of the Mozilla Public 4 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 | // You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | // Package mysql provides a MySQL driver for Go's database/sql package 8 | // 9 | // The driver should be used via the database/sql package: 10 | // 11 | // import "database/sql" 12 | // import _ "github.com/go-sql-driver/mysql" 13 | // 14 | // db, err := sql.Open("mysql", "user:password@/dbname") 15 | // 16 | // See https://github.com/go-sql-driver/mysql#usage for details 17 | package mysql 18 | 19 | import ( 20 | "database/sql" 21 | "database/sql/driver" 22 | "net" 23 | ) 24 | 25 | // MySQLDriver is exported to make the driver directly accessible. 26 | // In general the driver is used via the database/sql package. 27 | type MySQLDriver struct{} 28 | 29 | // DialFunc is a function which can be used to establish the network connection. 30 | // Custom dial functions must be registered with RegisterDial 31 | type DialFunc func(addr string) (net.Conn, error) 32 | 33 | var dials map[string]DialFunc 34 | 35 | // RegisterDial registers a custom dial function. It can then be used by the 36 | // network address mynet(addr), where mynet is the registered new network. 37 | // addr is passed as a parameter to the dial function. 38 | func RegisterDial(net string, dial DialFunc) { 39 | if dials == nil { 40 | dials = make(map[string]DialFunc) 41 | } 42 | dials[net] = dial 43 | } 44 | 45 | // Open new Connection. 46 | // See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how 47 | // the DSN string is formated 48 | func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { 49 | var err error 50 | 51 | // New mysqlConn 52 | mc := &mysqlConn{ 53 | maxPacketAllowed: maxPacketSize, 54 | maxWriteSize: maxPacketSize - 1, 55 | } 56 | mc.cfg, err = ParseDSN(dsn) 57 | if err != nil { 58 | return nil, err 59 | } 60 | mc.parseTime = mc.cfg.ParseTime 61 | mc.strict = mc.cfg.Strict 62 | 63 | // Connect to Server 64 | if dial, ok := dials[mc.cfg.Net]; ok { 65 | mc.netConn, err = dial(mc.cfg.Addr) 66 | } else { 67 | nd := net.Dialer{Timeout: mc.cfg.Timeout} 68 | mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr) 69 | } 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | // Enable TCP Keepalives on TCP connections 75 | if tc, ok := mc.netConn.(*net.TCPConn); ok { 76 | if err := tc.SetKeepAlive(true); err != nil { 77 | // Don't send COM_QUIT before handshake. 78 | mc.netConn.Close() 79 | mc.netConn = nil 80 | return nil, err 81 | } 82 | } 83 | 84 | mc.buf = newBuffer(mc.netConn) 85 | 86 | // Set I/O timeouts 87 | mc.buf.timeout = mc.cfg.ReadTimeout 88 | mc.writeTimeout = mc.cfg.WriteTimeout 89 | 90 | // Reading Handshake Initialization Packet 91 | cipher, err := mc.readInitPacket() 92 | if err != nil { 93 | mc.cleanup() 94 | return nil, err 95 | } 96 | 97 | // Send Client Authentication Packet 98 | if err = mc.writeAuthPacket(cipher); err != nil { 99 | mc.cleanup() 100 | return nil, err 101 | } 102 | 103 | // Handle response to auth packet, switch methods if possible 104 | if err = handleAuthResult(mc, cipher); err != nil { 105 | // Authentication failed and MySQL has already closed the connection 106 | // (https://dev.mysql.com/doc/internals/en/authentication-fails.html). 107 | // Do not send COM_QUIT, just cleanup and return the error. 108 | mc.cleanup() 109 | return nil, err 110 | } 111 | 112 | // Get max allowed packet size 113 | maxap, err := mc.getSystemVar("max_allowed_packet") 114 | if err != nil { 115 | mc.Close() 116 | return nil, err 117 | } 118 | mc.maxPacketAllowed = stringToInt(maxap) - 1 119 | if mc.maxPacketAllowed < maxPacketSize { 120 | mc.maxWriteSize = mc.maxPacketAllowed 121 | } 122 | 123 | // Handle DSN Params 124 | err = mc.handleParams() 125 | if err != nil { 126 | mc.Close() 127 | return nil, err 128 | } 129 | 130 | return mc, nil 131 | } 132 | 133 | func handleAuthResult(mc *mysqlConn, cipher []byte) error { 134 | // Read Result Packet 135 | err := mc.readResultOK() 136 | if err == nil { 137 | return nil // auth successful 138 | } 139 | 140 | if mc.cfg == nil { 141 | return err // auth failed and retry not possible 142 | } 143 | 144 | // Retry auth if configured to do so. 145 | if mc.cfg.AllowOldPasswords && err == ErrOldPassword { 146 | // Retry with old authentication method. Note: there are edge cases 147 | // where this should work but doesn't; this is currently "wontfix": 148 | // https://github.com/go-sql-driver/mysql/issues/184 149 | if err = mc.writeOldAuthPacket(cipher); err != nil { 150 | return err 151 | } 152 | err = mc.readResultOK() 153 | } else if mc.cfg.AllowCleartextPasswords && err == ErrCleartextPassword { 154 | // Retry with clear text password for 155 | // http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html 156 | // http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html 157 | if err = mc.writeClearAuthPacket(); err != nil { 158 | return err 159 | } 160 | err = mc.readResultOK() 161 | } 162 | return err 163 | } 164 | 165 | func init() { 166 | sql.Register("mysql", &MySQLDriver{}) 167 | } 168 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/errors.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "errors" 14 | "fmt" 15 | "io" 16 | "log" 17 | "os" 18 | ) 19 | 20 | // Various errors the driver might return. Can change between driver versions. 21 | var ( 22 | ErrInvalidConn = errors.New("invalid connection") 23 | ErrMalformPkt = errors.New("malformed packet") 24 | ErrNoTLS = errors.New("TLS requested but server does not support TLS") 25 | ErrOldPassword = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords") 26 | ErrCleartextPassword = errors.New("this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN") 27 | ErrUnknownPlugin = errors.New("this authentication plugin is not supported") 28 | ErrOldProtocol = errors.New("MySQL server does not support required protocol 41+") 29 | ErrPktSync = errors.New("commands out of sync. You can't run this command now") 30 | ErrPktSyncMul = errors.New("commands out of sync. Did you run multiple statements at once?") 31 | ErrPktTooLarge = errors.New("packet for query is too large. Try adjusting the 'max_allowed_packet' variable on the server") 32 | ErrBusyBuffer = errors.New("busy buffer") 33 | ) 34 | 35 | var errLog = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile)) 36 | 37 | // Logger is used to log critical error messages. 38 | type Logger interface { 39 | Print(v ...interface{}) 40 | } 41 | 42 | // SetLogger is used to set the logger for critical errors. 43 | // The initial logger is os.Stderr. 44 | func SetLogger(logger Logger) error { 45 | if logger == nil { 46 | return errors.New("logger is nil") 47 | } 48 | errLog = logger 49 | return nil 50 | } 51 | 52 | // MySQLError is an error type which represents a single MySQL error 53 | type MySQLError struct { 54 | Number uint16 55 | Message string 56 | } 57 | 58 | func (me *MySQLError) Error() string { 59 | return fmt.Sprintf("Error %d: %s", me.Number, me.Message) 60 | } 61 | 62 | // MySQLWarnings is an error type which represents a group of one or more MySQL 63 | // warnings 64 | type MySQLWarnings []MySQLWarning 65 | 66 | func (mws MySQLWarnings) Error() string { 67 | var msg string 68 | for i, warning := range mws { 69 | if i > 0 { 70 | msg += "\r\n" 71 | } 72 | msg += fmt.Sprintf( 73 | "%s %s: %s", 74 | warning.Level, 75 | warning.Code, 76 | warning.Message, 77 | ) 78 | } 79 | return msg 80 | } 81 | 82 | // MySQLWarning is an error type which represents a single MySQL warning. 83 | // Warnings are returned in groups only. See MySQLWarnings 84 | type MySQLWarning struct { 85 | Level string 86 | Code string 87 | Message string 88 | } 89 | 90 | func (mc *mysqlConn) getWarnings() (err error) { 91 | rows, err := mc.Query("SHOW WARNINGS", nil) 92 | if err != nil { 93 | return 94 | } 95 | 96 | var warnings = MySQLWarnings{} 97 | var values = make([]driver.Value, 3) 98 | 99 | for { 100 | err = rows.Next(values) 101 | switch err { 102 | case nil: 103 | warning := MySQLWarning{} 104 | 105 | if raw, ok := values[0].([]byte); ok { 106 | warning.Level = string(raw) 107 | } else { 108 | warning.Level = fmt.Sprintf("%s", values[0]) 109 | } 110 | if raw, ok := values[1].([]byte); ok { 111 | warning.Code = string(raw) 112 | } else { 113 | warning.Code = fmt.Sprintf("%s", values[1]) 114 | } 115 | if raw, ok := values[2].([]byte); ok { 116 | warning.Message = string(raw) 117 | } else { 118 | warning.Message = fmt.Sprintf("%s", values[0]) 119 | } 120 | 121 | warnings = append(warnings, warning) 122 | 123 | case io.EOF: 124 | return warnings 125 | 126 | default: 127 | rows.Close() 128 | return 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/infile.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "fmt" 13 | "io" 14 | "os" 15 | "strings" 16 | "sync" 17 | ) 18 | 19 | var ( 20 | fileRegister map[string]bool 21 | fileRegisterLock sync.RWMutex 22 | readerRegister map[string]func() io.Reader 23 | readerRegisterLock sync.RWMutex 24 | ) 25 | 26 | // RegisterLocalFile adds the given file to the file whitelist, 27 | // so that it can be used by "LOAD DATA LOCAL INFILE ". 28 | // Alternatively you can allow the use of all local files with 29 | // the DSN parameter 'allowAllFiles=true' 30 | // 31 | // filePath := "/home/gopher/data.csv" 32 | // mysql.RegisterLocalFile(filePath) 33 | // err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo") 34 | // if err != nil { 35 | // ... 36 | // 37 | func RegisterLocalFile(filePath string) { 38 | fileRegisterLock.Lock() 39 | // lazy map init 40 | if fileRegister == nil { 41 | fileRegister = make(map[string]bool) 42 | } 43 | 44 | fileRegister[strings.Trim(filePath, `"`)] = true 45 | fileRegisterLock.Unlock() 46 | } 47 | 48 | // DeregisterLocalFile removes the given filepath from the whitelist. 49 | func DeregisterLocalFile(filePath string) { 50 | fileRegisterLock.Lock() 51 | delete(fileRegister, strings.Trim(filePath, `"`)) 52 | fileRegisterLock.Unlock() 53 | } 54 | 55 | // RegisterReaderHandler registers a handler function which is used 56 | // to receive a io.Reader. 57 | // The Reader can be used by "LOAD DATA LOCAL INFILE Reader::". 58 | // If the handler returns a io.ReadCloser Close() is called when the 59 | // request is finished. 60 | // 61 | // mysql.RegisterReaderHandler("data", func() io.Reader { 62 | // var csvReader io.Reader // Some Reader that returns CSV data 63 | // ... // Open Reader here 64 | // return csvReader 65 | // }) 66 | // err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo") 67 | // if err != nil { 68 | // ... 69 | // 70 | func RegisterReaderHandler(name string, handler func() io.Reader) { 71 | readerRegisterLock.Lock() 72 | // lazy map init 73 | if readerRegister == nil { 74 | readerRegister = make(map[string]func() io.Reader) 75 | } 76 | 77 | readerRegister[name] = handler 78 | readerRegisterLock.Unlock() 79 | } 80 | 81 | // DeregisterReaderHandler removes the ReaderHandler function with 82 | // the given name from the registry. 83 | func DeregisterReaderHandler(name string) { 84 | readerRegisterLock.Lock() 85 | delete(readerRegister, name) 86 | readerRegisterLock.Unlock() 87 | } 88 | 89 | func deferredClose(err *error, closer io.Closer) { 90 | closeErr := closer.Close() 91 | if *err == nil { 92 | *err = closeErr 93 | } 94 | } 95 | 96 | func (mc *mysqlConn) handleInFileRequest(name string) (err error) { 97 | var rdr io.Reader 98 | var data []byte 99 | packetSize := 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP 100 | if mc.maxWriteSize < packetSize { 101 | packetSize = mc.maxWriteSize 102 | } 103 | 104 | if idx := strings.Index(name, "Reader::"); idx == 0 || (idx > 0 && name[idx-1] == '/') { // io.Reader 105 | // The server might return an an absolute path. See issue #355. 106 | name = name[idx+8:] 107 | 108 | readerRegisterLock.RLock() 109 | handler, inMap := readerRegister[name] 110 | readerRegisterLock.RUnlock() 111 | 112 | if inMap { 113 | rdr = handler() 114 | if rdr != nil { 115 | if cl, ok := rdr.(io.Closer); ok { 116 | defer deferredClose(&err, cl) 117 | } 118 | } else { 119 | err = fmt.Errorf("Reader '%s' is ", name) 120 | } 121 | } else { 122 | err = fmt.Errorf("Reader '%s' is not registered", name) 123 | } 124 | } else { // File 125 | name = strings.Trim(name, `"`) 126 | fileRegisterLock.RLock() 127 | fr := fileRegister[name] 128 | fileRegisterLock.RUnlock() 129 | if mc.cfg.AllowAllFiles || fr { 130 | var file *os.File 131 | var fi os.FileInfo 132 | 133 | if file, err = os.Open(name); err == nil { 134 | defer deferredClose(&err, file) 135 | 136 | // get file size 137 | if fi, err = file.Stat(); err == nil { 138 | rdr = file 139 | if fileSize := int(fi.Size()); fileSize < packetSize { 140 | packetSize = fileSize 141 | } 142 | } 143 | } 144 | } else { 145 | err = fmt.Errorf("local file '%s' is not registered", name) 146 | } 147 | } 148 | 149 | // send content packets 150 | if err == nil { 151 | data := make([]byte, 4+packetSize) 152 | var n int 153 | for err == nil { 154 | n, err = rdr.Read(data[4:]) 155 | if n > 0 { 156 | if ioErr := mc.writePacket(data[:4+n]); ioErr != nil { 157 | return ioErr 158 | } 159 | } 160 | } 161 | if err == io.EOF { 162 | err = nil 163 | } 164 | } 165 | 166 | // send empty packet (termination) 167 | if data == nil { 168 | data = make([]byte, 4) 169 | } 170 | if ioErr := mc.writePacket(data[:4]); ioErr != nil { 171 | return ioErr 172 | } 173 | 174 | // read OK packet 175 | if err == nil { 176 | return mc.readResultOK() 177 | } 178 | 179 | mc.readPacket() 180 | return err 181 | } 182 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/result.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlResult struct { 12 | affectedRows int64 13 | insertId int64 14 | } 15 | 16 | func (res *mysqlResult) LastInsertId() (int64, error) { 17 | return res.insertId, nil 18 | } 19 | 20 | func (res *mysqlResult) RowsAffected() (int64, error) { 21 | return res.affectedRows, nil 22 | } 23 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/rows.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "io" 14 | ) 15 | 16 | type mysqlField struct { 17 | tableName string 18 | name string 19 | flags fieldFlag 20 | fieldType byte 21 | decimals byte 22 | } 23 | 24 | type mysqlRows struct { 25 | mc *mysqlConn 26 | columns []mysqlField 27 | } 28 | 29 | type binaryRows struct { 30 | mysqlRows 31 | } 32 | 33 | type textRows struct { 34 | mysqlRows 35 | } 36 | 37 | type emptyRows struct{} 38 | 39 | func (rows *mysqlRows) Columns() []string { 40 | columns := make([]string, len(rows.columns)) 41 | if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias { 42 | for i := range columns { 43 | if tableName := rows.columns[i].tableName; len(tableName) > 0 { 44 | columns[i] = tableName + "." + rows.columns[i].name 45 | } else { 46 | columns[i] = rows.columns[i].name 47 | } 48 | } 49 | } else { 50 | for i := range columns { 51 | columns[i] = rows.columns[i].name 52 | } 53 | } 54 | return columns 55 | } 56 | 57 | func (rows *mysqlRows) Close() error { 58 | mc := rows.mc 59 | if mc == nil { 60 | return nil 61 | } 62 | if mc.netConn == nil { 63 | return ErrInvalidConn 64 | } 65 | 66 | // Remove unread packets from stream 67 | err := mc.readUntilEOF() 68 | if err == nil { 69 | if err = mc.discardResults(); err != nil { 70 | return err 71 | } 72 | } 73 | 74 | rows.mc = nil 75 | return err 76 | } 77 | 78 | func (rows *binaryRows) Next(dest []driver.Value) error { 79 | if mc := rows.mc; mc != nil { 80 | if mc.netConn == nil { 81 | return ErrInvalidConn 82 | } 83 | 84 | // Fetch next row from stream 85 | return rows.readRow(dest) 86 | } 87 | return io.EOF 88 | } 89 | 90 | func (rows *textRows) Next(dest []driver.Value) error { 91 | if mc := rows.mc; mc != nil { 92 | if mc.netConn == nil { 93 | return ErrInvalidConn 94 | } 95 | 96 | // Fetch next row from stream 97 | return rows.readRow(dest) 98 | } 99 | return io.EOF 100 | } 101 | 102 | func (rows emptyRows) Columns() []string { 103 | return nil 104 | } 105 | 106 | func (rows emptyRows) Close() error { 107 | return nil 108 | } 109 | 110 | func (rows emptyRows) Next(dest []driver.Value) error { 111 | return io.EOF 112 | } 113 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/statement.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "fmt" 14 | "reflect" 15 | "strconv" 16 | ) 17 | 18 | type mysqlStmt struct { 19 | mc *mysqlConn 20 | id uint32 21 | paramCount int 22 | columns []mysqlField // cached from the first query 23 | } 24 | 25 | func (stmt *mysqlStmt) Close() error { 26 | if stmt.mc == nil || stmt.mc.netConn == nil { 27 | errLog.Print(ErrInvalidConn) 28 | return driver.ErrBadConn 29 | } 30 | 31 | err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id) 32 | stmt.mc = nil 33 | return err 34 | } 35 | 36 | func (stmt *mysqlStmt) NumInput() int { 37 | return stmt.paramCount 38 | } 39 | 40 | func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter { 41 | return converter{} 42 | } 43 | 44 | func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { 45 | if stmt.mc.netConn == nil { 46 | errLog.Print(ErrInvalidConn) 47 | return nil, driver.ErrBadConn 48 | } 49 | // Send command 50 | err := stmt.writeExecutePacket(args) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | mc := stmt.mc 56 | 57 | mc.affectedRows = 0 58 | mc.insertId = 0 59 | 60 | // Read Result 61 | resLen, err := mc.readResultSetHeaderPacket() 62 | if err == nil { 63 | if resLen > 0 { 64 | // Columns 65 | err = mc.readUntilEOF() 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | // Rows 71 | err = mc.readUntilEOF() 72 | } 73 | if err == nil { 74 | return &mysqlResult{ 75 | affectedRows: int64(mc.affectedRows), 76 | insertId: int64(mc.insertId), 77 | }, nil 78 | } 79 | } 80 | 81 | return nil, err 82 | } 83 | 84 | func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { 85 | if stmt.mc.netConn == nil { 86 | errLog.Print(ErrInvalidConn) 87 | return nil, driver.ErrBadConn 88 | } 89 | // Send command 90 | err := stmt.writeExecutePacket(args) 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | mc := stmt.mc 96 | 97 | // Read Result 98 | resLen, err := mc.readResultSetHeaderPacket() 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | rows := new(binaryRows) 104 | 105 | if resLen > 0 { 106 | rows.mc = mc 107 | // Columns 108 | // If not cached, read them and cache them 109 | if stmt.columns == nil { 110 | rows.columns, err = mc.readColumns(resLen) 111 | stmt.columns = rows.columns 112 | } else { 113 | rows.columns = stmt.columns 114 | err = mc.readUntilEOF() 115 | } 116 | } 117 | 118 | return rows, err 119 | } 120 | 121 | type converter struct{} 122 | 123 | func (c converter) ConvertValue(v interface{}) (driver.Value, error) { 124 | if driver.IsValue(v) { 125 | return v, nil 126 | } 127 | 128 | rv := reflect.ValueOf(v) 129 | switch rv.Kind() { 130 | case reflect.Ptr: 131 | // indirect pointers 132 | if rv.IsNil() { 133 | return nil, nil 134 | } 135 | return c.ConvertValue(rv.Elem().Interface()) 136 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 137 | return rv.Int(), nil 138 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: 139 | return int64(rv.Uint()), nil 140 | case reflect.Uint64: 141 | u64 := rv.Uint() 142 | if u64 >= 1<<63 { 143 | return strconv.FormatUint(u64, 10), nil 144 | } 145 | return int64(u64), nil 146 | case reflect.Float32, reflect.Float64: 147 | return rv.Float(), nil 148 | } 149 | return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) 150 | } 151 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/go-sql-driver/mysql/transaction.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlTx struct { 12 | mc *mysqlConn 13 | } 14 | 15 | func (tx *mysqlTx) Commit() (err error) { 16 | if tx.mc == nil || tx.mc.netConn == nil { 17 | return ErrInvalidConn 18 | } 19 | err = tx.mc.exec("COMMIT") 20 | tx.mc = nil 21 | return 22 | } 23 | 24 | func (tx *mysqlTx) Rollback() (err error) { 25 | if tx.mc == nil || tx.mc.netConn == nil { 26 | return ErrInvalidConn 27 | } 28 | err = tx.mc.exec("ROLLBACK") 29 | tx.mc = nil 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: x2wlA1x0X8CK45ybWpZRCVRB4g7vtkhaw 2 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.2 6 | - 1.3 7 | - 1.4 8 | - 1.5 9 | - tip 10 | 11 | install: 12 | - go get golang.org/x/net/html 13 | 14 | script: go test -v ./... 15 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to bluemonday 2 | 3 | Third-party patches are essential for keeping bluemonday secure and offering the features developers want. However there are a few guidelines that we need contributors to follow so that we can maintain the quality of work that developers who use bluemonday expect. 4 | 5 | ## Getting Started 6 | 7 | * Make sure you have a [Github account](https://github.com/signup/free) 8 | 9 | ## Submitting an Issue 10 | 11 | * Submit a ticket for your issue, assuming one does not already exist 12 | * Clearly describe the issue including the steps to reproduce (with sample input and output) if it is a bug 13 | 14 | If you are reporting a security flaw, you may expect that we will provide the code to fix it for you. Otherwise you may want to submit a pull request to ensure the resolution is applied sooner rather than later: 15 | 16 | * Fork the repository on Github 17 | * Issue a pull request containing code to resolve the issue 18 | 19 | ## Submitting a Pull Request 20 | 21 | * Submit a ticket for your issue, assuming one does not already exist 22 | * Describe the reason for the pull request and if applicable show some example inputs and outputs to demonstrate what the patch does 23 | * Fork the repository on Github 24 | * Before submitting the pull request you should 25 | 1. Include tests for your patch, 1 test should encapsulate the entire patch and should refer to the Github issue 26 | 1. If you have added new exposed/public functionality, you should ensure it is documented appropriately 27 | 1. If you have added new exposed/public functionality, you should consider demonstrating how to use it within one of the helpers or shipped policies if appropriate or within a test if modifying a helper or policy is not appropriate 28 | 1. Run all of the tests `go test -v ./...` or `make test` and ensure all tests pass 29 | 1. Run gofmt `gofmt -w ./$*` or `make fmt` 30 | 1. Run vet `go tool vet *.go` or `make vet` and resolve any issues 31 | 1. Install golint using `go get -u github.com/golang/lint/golint` and run vet `golint *.go` or `make lint` and resolve every warning 32 | * When submitting the pull request you should 33 | 1. Note the issue(s) it resolves, i.e. `Closes #6` in the pull request comment to close issue #6 when the pull request is accepted 34 | 35 | Once you have submitted a pull request, we *may* merge it without changes. If we have any comments or feedback, or need you to make changes to your pull request we will update the Github pull request or the associated issue. We expect responses from you within two weeks, and we may close the pull request is there is no activity. 36 | 37 | ### Contributor Licence Agreement 38 | 39 | We haven't gone for the formal "Sign a Contributor Licence Agreement" thing that projects like [puppet](https://cla.puppetlabs.com/), [Mojito](https://developer.yahoo.com/cocktails/mojito/cla/) and companies like [Google](http://code.google.com/legal/individual-cla-v1.0.html) are using. 40 | 41 | But we do need to know that we can accept and merge your contributions, so for now the act of contributing a pull request should be considered equivalent to agreeing to a contributor licence agreement, specifically: 42 | 43 | You accept that the act of submitting code to the bluemonday project is to grant a copyright licence to the project that is perpetual, worldwide, non-exclusive, no-charge, royalty free and irrevocable. 44 | 45 | You accept that all who comply with the licence of the project (BSD 3-clause) are permitted to use your contributions to the project. 46 | 47 | You accept, and by submitting code do declare, that you have the legal right to grant such a licence to the project and that each of the contributions is your own original creation. 48 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/CREDITS.md: -------------------------------------------------------------------------------- 1 | 2 | 1. John Graham-Cumming http://jgc.org/ 3 | 1. Mike Samuel mikesamuel@gmail.com 4 | 1. Dmitri Shuralyov shurcooL@gmail.com 5 | 1. https://github.com/opennota 6 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/LICENCE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, David Kitchen 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name of the organisation (Microcosm) nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/Makefile: -------------------------------------------------------------------------------- 1 | # Targets: 2 | # 3 | # all: Builds the code locally after testing 4 | # 5 | # fmt: Formats the source files 6 | # build: Builds the code locally 7 | # vet: Vets the code 8 | # lint: Runs lint over the code (you do not need to fix everything) 9 | # test: Runs the tests 10 | # cover: Gives you the URL to a nice test coverage report 11 | # clean: Deletes the built file (if it exists) 12 | # 13 | # install: Builds, tests and installs the code locally 14 | 15 | .PHONY: all fmt build vet lint test cover clean install 16 | 17 | # The first target is always the default action if `make` is called without 18 | # args we clean, build and install into $GOPATH so that it can just be run 19 | 20 | all: clean fmt vet test install 21 | 22 | fmt: 23 | @gofmt -w ./$* 24 | 25 | build: clean 26 | @go build 27 | 28 | vet: 29 | @vet *.go 30 | 31 | lint: 32 | @golint *.go 33 | 34 | test: 35 | @go test -v ./... 36 | 37 | cover: COVERAGE_FILE := coverage.out 38 | cover: 39 | @go test -coverprofile=$(COVERAGE_FILE) && \ 40 | cover -html=$(COVERAGE_FILE) && rm $(COVERAGE_FILE) 41 | 42 | clean: 43 | @find $(GOPATH)/pkg/*/github.com/microcosm-cc -name bluemonday.a -delete 44 | 45 | install: clean 46 | @go install 47 | -------------------------------------------------------------------------------- /src/api/vendor/github.com/microcosm-cc/bluemonday/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, David Kitchen 2 | // 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this 9 | // list of conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // * Neither the name of the organisation (Microcosm) nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | /* 31 | Package bluemonday provides a way of describing a whitelist of HTML elements 32 | and attributes as a policy, and for that policy to be applied to untrusted 33 | strings from users that may contain markup. All elements and attributes not on 34 | the whitelist will be stripped. 35 | 36 | The default bluemonday.UGCPolicy().Sanitize() turns this: 37 | 38 | Hello World 39 | 40 | Into the more harmless: 41 | 42 | Hello World 43 | 44 | And it turns this: 45 | 46 | XSS 47 | 48 | Into this: 49 | 50 | XSS 51 | 52 | Whilst still allowing this: 53 | 54 | 55 | 56 | 57 | 58 | To pass through mostly unaltered (it gained a rel="nofollow"): 59 | 60 | 61 | 62 | 63 | 64 | The primary purpose of bluemonday is to take potentially unsafe user generated 65 | content (from things like Markdown, HTML WYSIWYG tools, etc) and make it safe 66 | for you to put on your website. 67 | 68 | It protects sites against XSS (http://en.wikipedia.org/wiki/Cross-site_scripting) 69 | and other malicious content that a user interface may deliver. There are many 70 | vectors for an XSS attack (https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet) 71 | and the safest thing to do is to sanitize user input against a known safe list 72 | of HTML elements and attributes. 73 | 74 | Note: You should always run bluemonday after any other processing. 75 | 76 | If you use blackfriday (https://github.com/russross/blackfriday) or 77 | Pandoc (http://johnmacfarlane.net/pandoc/) then bluemonday should be run after 78 | these steps. This ensures that no insecure HTML is introduced later in your 79 | process. 80 | 81 | bluemonday is heavily inspired by both the OWASP Java HTML Sanitizer 82 | (https://code.google.com/p/owasp-java-html-sanitizer/) and the HTML Purifier 83 | (http://htmlpurifier.org/). 84 | 85 | We ship two default policies, one is bluemonday.StrictPolicy() and can be 86 | thought of as equivalent to stripping all HTML elements and their attributes as 87 | it has nothing on it's whitelist. 88 | 89 | The other is bluemonday.UGCPolicy() and allows a broad selection of HTML 90 | elements and attributes that are safe for user generated content. Note that 91 | this policy does not whitelist iframes, object, embed, styles, script, etc. 92 | 93 | The essence of building a policy is to determine which HTML elements and 94 | attributes are considered safe for your scenario. OWASP provide an XSS 95 | prevention cheat sheet ( https://www.google.com/search?q=xss+prevention+cheat+sheet ) 96 | to help explain the risks, but essentially: 97 | 98 | 1. Avoid whitelisting anything other than plain HTML elements 99 | 2. Avoid whitelisting `script`, `style`, `iframe`, `object`, `embed`, `base` 100 | elements 101 | 3. Avoid whitelisting anything other than plain HTML elements with simple 102 | values that you can match to a regexp 103 | */ 104 | package bluemonday 105 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/html/atom/atom.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package atom provides integer codes (also known as atoms) for a fixed set of 6 | // frequently occurring HTML strings: tag names and attribute keys such as "p" 7 | // and "id". 8 | // 9 | // Sharing an atom's name between all elements with the same tag can result in 10 | // fewer string allocations when tokenizing and parsing HTML. Integer 11 | // comparisons are also generally faster than string comparisons. 12 | // 13 | // The value of an atom's particular code is not guaranteed to stay the same 14 | // between versions of this package. Neither is any ordering guaranteed: 15 | // whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to 16 | // be dense. The only guarantees are that e.g. looking up "div" will yield 17 | // atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. 18 | package atom 19 | 20 | // Atom is an integer code for a string. The zero value maps to "". 21 | type Atom uint32 22 | 23 | // String returns the atom's name. 24 | func (a Atom) String() string { 25 | start := uint32(a >> 8) 26 | n := uint32(a & 0xff) 27 | if start+n > uint32(len(atomText)) { 28 | return "" 29 | } 30 | return atomText[start : start+n] 31 | } 32 | 33 | func (a Atom) string() string { 34 | return atomText[a>>8 : a>>8+a&0xff] 35 | } 36 | 37 | // fnv computes the FNV hash with an arbitrary starting value h. 38 | func fnv(h uint32, s []byte) uint32 { 39 | for i := range s { 40 | h ^= uint32(s[i]) 41 | h *= 16777619 42 | } 43 | return h 44 | } 45 | 46 | func match(s string, t []byte) bool { 47 | for i, c := range t { 48 | if s[i] != c { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | // Lookup returns the atom whose name is s. It returns zero if there is no 56 | // such atom. The lookup is case sensitive. 57 | func Lookup(s []byte) Atom { 58 | if len(s) == 0 || len(s) > maxAtomLen { 59 | return 0 60 | } 61 | h := fnv(hash0, s) 62 | if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 63 | return a 64 | } 65 | if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 66 | return a 67 | } 68 | return 0 69 | } 70 | 71 | // String returns a string whose contents are equal to s. In that sense, it is 72 | // equivalent to string(s) but may be more efficient. 73 | func String(s []byte) string { 74 | if a := Lookup(s); a != 0 { 75 | return a.String() 76 | } 77 | return string(s) 78 | } 79 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/html/const.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | // Section 12.2.3.2 of the HTML5 specification says "The following elements 8 | // have varying levels of special parsing rules". 9 | // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements 10 | var isSpecialElementMap = map[string]bool{ 11 | "address": true, 12 | "applet": true, 13 | "area": true, 14 | "article": true, 15 | "aside": true, 16 | "base": true, 17 | "basefont": true, 18 | "bgsound": true, 19 | "blockquote": true, 20 | "body": true, 21 | "br": true, 22 | "button": true, 23 | "caption": true, 24 | "center": true, 25 | "col": true, 26 | "colgroup": true, 27 | "dd": true, 28 | "details": true, 29 | "dir": true, 30 | "div": true, 31 | "dl": true, 32 | "dt": true, 33 | "embed": true, 34 | "fieldset": true, 35 | "figcaption": true, 36 | "figure": true, 37 | "footer": true, 38 | "form": true, 39 | "frame": true, 40 | "frameset": true, 41 | "h1": true, 42 | "h2": true, 43 | "h3": true, 44 | "h4": true, 45 | "h5": true, 46 | "h6": true, 47 | "head": true, 48 | "header": true, 49 | "hgroup": true, 50 | "hr": true, 51 | "html": true, 52 | "iframe": true, 53 | "img": true, 54 | "input": true, 55 | "isindex": true, 56 | "li": true, 57 | "link": true, 58 | "listing": true, 59 | "marquee": true, 60 | "menu": true, 61 | "meta": true, 62 | "nav": true, 63 | "noembed": true, 64 | "noframes": true, 65 | "noscript": true, 66 | "object": true, 67 | "ol": true, 68 | "p": true, 69 | "param": true, 70 | "plaintext": true, 71 | "pre": true, 72 | "script": true, 73 | "section": true, 74 | "select": true, 75 | "source": true, 76 | "style": true, 77 | "summary": true, 78 | "table": true, 79 | "tbody": true, 80 | "td": true, 81 | "template": true, 82 | "textarea": true, 83 | "tfoot": true, 84 | "th": true, 85 | "thead": true, 86 | "title": true, 87 | "tr": true, 88 | "track": true, 89 | "ul": true, 90 | "wbr": true, 91 | "xmp": true, 92 | } 93 | 94 | func isSpecialElement(element *Node) bool { 95 | switch element.Namespace { 96 | case "", "html": 97 | return isSpecialElementMap[element.Data] 98 | case "svg": 99 | return element.Data == "foreignObject" 100 | } 101 | return false 102 | } 103 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/html/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package html implements an HTML5-compliant tokenizer and parser. 7 | 8 | Tokenization is done by creating a Tokenizer for an io.Reader r. It is the 9 | caller's responsibility to ensure that r provides UTF-8 encoded HTML. 10 | 11 | z := html.NewTokenizer(r) 12 | 13 | Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), 14 | which parses the next token and returns its type, or an error: 15 | 16 | for { 17 | tt := z.Next() 18 | if tt == html.ErrorToken { 19 | // ... 20 | return ... 21 | } 22 | // Process the current token. 23 | } 24 | 25 | There are two APIs for retrieving the current token. The high-level API is to 26 | call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs 27 | allow optionally calling Raw after Next but before Token, Text, TagName, or 28 | TagAttr. In EBNF notation, the valid call sequence per token is: 29 | 30 | Next {Raw} [ Token | Text | TagName {TagAttr} ] 31 | 32 | Token returns an independent data structure that completely describes a token. 33 | Entities (such as "<") are unescaped, tag names and attribute keys are 34 | lower-cased, and attributes are collected into a []Attribute. For example: 35 | 36 | for { 37 | if z.Next() == html.ErrorToken { 38 | // Returning io.EOF indicates success. 39 | return z.Err() 40 | } 41 | emitToken(z.Token()) 42 | } 43 | 44 | The low-level API performs fewer allocations and copies, but the contents of 45 | the []byte values returned by Text, TagName and TagAttr may change on the next 46 | call to Next. For example, to extract an HTML page's anchor text: 47 | 48 | depth := 0 49 | for { 50 | tt := z.Next() 51 | switch tt { 52 | case ErrorToken: 53 | return z.Err() 54 | case TextToken: 55 | if depth > 0 { 56 | // emitBytes should copy the []byte it receives, 57 | // if it doesn't process it immediately. 58 | emitBytes(z.Text()) 59 | } 60 | case StartTagToken, EndTagToken: 61 | tn, _ := z.TagName() 62 | if len(tn) == 1 && tn[0] == 'a' { 63 | if tt == StartTagToken { 64 | depth++ 65 | } else { 66 | depth-- 67 | } 68 | } 69 | } 70 | } 71 | 72 | Parsing is done by calling Parse with an io.Reader, which returns the root of 73 | the parse tree (the document element) as a *Node. It is the caller's 74 | responsibility to ensure that the Reader provides UTF-8 encoded HTML. For 75 | example, to process each anchor node in depth-first order: 76 | 77 | doc, err := html.Parse(r) 78 | if err != nil { 79 | // ... 80 | } 81 | var f func(*html.Node) 82 | f = func(n *html.Node) { 83 | if n.Type == html.ElementNode && n.Data == "a" { 84 | // Do something with n... 85 | } 86 | for c := n.FirstChild; c != nil; c = c.NextSibling { 87 | f(c) 88 | } 89 | } 90 | f(doc) 91 | 92 | The relevant specifications include: 93 | https://html.spec.whatwg.org/multipage/syntax.html and 94 | https://html.spec.whatwg.org/multipage/syntax.html#tokenization 95 | */ 96 | package html 97 | 98 | // The tokenization algorithm implemented by this package is not a line-by-line 99 | // transliteration of the relatively verbose state-machine in the WHATWG 100 | // specification. A more direct approach is used instead, where the program 101 | // counter implies the state, such as whether it is tokenizing a tag or a text 102 | // node. Specification compliance is verified by checking expected and actual 103 | // outputs over a test suite rather than aiming for algorithmic fidelity. 104 | 105 | // TODO(nigeltao): Does a DOM API belong in this package or a separate one? 106 | // TODO(nigeltao): How does parsing interact with a JavaScript engine? 107 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/html/doctype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // parseDoctype parses the data from a DoctypeToken into a name, 12 | // public identifier, and system identifier. It returns a Node whose Type 13 | // is DoctypeNode, whose Data is the name, and which has attributes 14 | // named "system" and "public" for the two identifiers if they were present. 15 | // quirks is whether the document should be parsed in "quirks mode". 16 | func parseDoctype(s string) (n *Node, quirks bool) { 17 | n = &Node{Type: DoctypeNode} 18 | 19 | // Find the name. 20 | space := strings.IndexAny(s, whitespace) 21 | if space == -1 { 22 | space = len(s) 23 | } 24 | n.Data = s[:space] 25 | // The comparison to "html" is case-sensitive. 26 | if n.Data != "html" { 27 | quirks = true 28 | } 29 | n.Data = strings.ToLower(n.Data) 30 | s = strings.TrimLeft(s[space:], whitespace) 31 | 32 | if len(s) < 6 { 33 | // It can't start with "PUBLIC" or "SYSTEM". 34 | // Ignore the rest of the string. 35 | return n, quirks || s != "" 36 | } 37 | 38 | key := strings.ToLower(s[:6]) 39 | s = s[6:] 40 | for key == "public" || key == "system" { 41 | s = strings.TrimLeft(s, whitespace) 42 | if s == "" { 43 | break 44 | } 45 | quote := s[0] 46 | if quote != '"' && quote != '\'' { 47 | break 48 | } 49 | s = s[1:] 50 | q := strings.IndexRune(s, rune(quote)) 51 | var id string 52 | if q == -1 { 53 | id = s 54 | s = "" 55 | } else { 56 | id = s[:q] 57 | s = s[q+1:] 58 | } 59 | n.Attr = append(n.Attr, Attribute{Key: key, Val: id}) 60 | if key == "public" { 61 | key = "system" 62 | } else { 63 | key = "" 64 | } 65 | } 66 | 67 | if key != "" || s != "" { 68 | quirks = true 69 | } else if len(n.Attr) > 0 { 70 | if n.Attr[0].Key == "public" { 71 | public := strings.ToLower(n.Attr[0].Val) 72 | switch public { 73 | case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html": 74 | quirks = true 75 | default: 76 | for _, q := range quirkyIDs { 77 | if strings.HasPrefix(public, q) { 78 | quirks = true 79 | break 80 | } 81 | } 82 | } 83 | // The following two public IDs only cause quirks mode if there is no system ID. 84 | if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") || 85 | strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) { 86 | quirks = true 87 | } 88 | } 89 | if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && 90 | strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { 91 | quirks = true 92 | } 93 | } 94 | 95 | return n, quirks 96 | } 97 | 98 | // quirkyIDs is a list of public doctype identifiers that cause a document 99 | // to be interpreted in quirks mode. The identifiers should be in lower case. 100 | var quirkyIDs = []string{ 101 | "+//silmaril//dtd html pro v0r11 19970101//", 102 | "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", 103 | "-//as//dtd html 3.0 aswedit + extensions//", 104 | "-//ietf//dtd html 2.0 level 1//", 105 | "-//ietf//dtd html 2.0 level 2//", 106 | "-//ietf//dtd html 2.0 strict level 1//", 107 | "-//ietf//dtd html 2.0 strict level 2//", 108 | "-//ietf//dtd html 2.0 strict//", 109 | "-//ietf//dtd html 2.0//", 110 | "-//ietf//dtd html 2.1e//", 111 | "-//ietf//dtd html 3.0//", 112 | "-//ietf//dtd html 3.2 final//", 113 | "-//ietf//dtd html 3.2//", 114 | "-//ietf//dtd html 3//", 115 | "-//ietf//dtd html level 0//", 116 | "-//ietf//dtd html level 1//", 117 | "-//ietf//dtd html level 2//", 118 | "-//ietf//dtd html level 3//", 119 | "-//ietf//dtd html strict level 0//", 120 | "-//ietf//dtd html strict level 1//", 121 | "-//ietf//dtd html strict level 2//", 122 | "-//ietf//dtd html strict level 3//", 123 | "-//ietf//dtd html strict//", 124 | "-//ietf//dtd html//", 125 | "-//metrius//dtd metrius presentational//", 126 | "-//microsoft//dtd internet explorer 2.0 html strict//", 127 | "-//microsoft//dtd internet explorer 2.0 html//", 128 | "-//microsoft//dtd internet explorer 2.0 tables//", 129 | "-//microsoft//dtd internet explorer 3.0 html strict//", 130 | "-//microsoft//dtd internet explorer 3.0 html//", 131 | "-//microsoft//dtd internet explorer 3.0 tables//", 132 | "-//netscape comm. corp.//dtd html//", 133 | "-//netscape comm. corp.//dtd strict html//", 134 | "-//o'reilly and associates//dtd html 2.0//", 135 | "-//o'reilly and associates//dtd html extended 1.0//", 136 | "-//o'reilly and associates//dtd html extended relaxed 1.0//", 137 | "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", 138 | "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", 139 | "-//spyglass//dtd html 2.0 extended//", 140 | "-//sq//dtd html 2.0 hotmetal + extensions//", 141 | "-//sun microsystems corp.//dtd hotjava html//", 142 | "-//sun microsystems corp.//dtd hotjava strict html//", 143 | "-//w3c//dtd html 3 1995-03-24//", 144 | "-//w3c//dtd html 3.2 draft//", 145 | "-//w3c//dtd html 3.2 final//", 146 | "-//w3c//dtd html 3.2//", 147 | "-//w3c//dtd html 3.2s draft//", 148 | "-//w3c//dtd html 4.0 frameset//", 149 | "-//w3c//dtd html 4.0 transitional//", 150 | "-//w3c//dtd html experimental 19960712//", 151 | "-//w3c//dtd html experimental 970421//", 152 | "-//w3c//dtd w3 html//", 153 | "-//w3o//dtd w3 html 3.0//", 154 | "-//webtechs//dtd mozilla html 2.0//", 155 | "-//webtechs//dtd mozilla html//", 156 | } 157 | -------------------------------------------------------------------------------- /src/api/vendor/golang.org/x/net/html/node.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "golang.org/x/net/html/atom" 9 | ) 10 | 11 | // A NodeType is the type of a Node. 12 | type NodeType uint32 13 | 14 | const ( 15 | ErrorNode NodeType = iota 16 | TextNode 17 | DocumentNode 18 | ElementNode 19 | CommentNode 20 | DoctypeNode 21 | scopeMarkerNode 22 | ) 23 | 24 | // Section 12.2.3.3 says "scope markers are inserted when entering applet 25 | // elements, buttons, object elements, marquees, table cells, and table 26 | // captions, and are used to prevent formatting from 'leaking'". 27 | var scopeMarker = Node{Type: scopeMarkerNode} 28 | 29 | // A Node consists of a NodeType and some Data (tag name for element nodes, 30 | // content for text) and are part of a tree of Nodes. Element nodes may also 31 | // have a Namespace and contain a slice of Attributes. Data is unescaped, so 32 | // that it looks like "a 0 { 160 | return (*s)[i-1] 161 | } 162 | return nil 163 | } 164 | 165 | // index returns the index of the top-most occurrence of n in the stack, or -1 166 | // if n is not present. 167 | func (s *nodeStack) index(n *Node) int { 168 | for i := len(*s) - 1; i >= 0; i-- { 169 | if (*s)[i] == n { 170 | return i 171 | } 172 | } 173 | return -1 174 | } 175 | 176 | // insert inserts a node at the given index. 177 | func (s *nodeStack) insert(i int, n *Node) { 178 | (*s) = append(*s, nil) 179 | copy((*s)[i+1:], (*s)[i:]) 180 | (*s)[i] = n 181 | } 182 | 183 | // remove removes a node from the stack. It is a no-op if n is not present. 184 | func (s *nodeStack) remove(n *Node) { 185 | i := s.index(n) 186 | if i == -1 { 187 | return 188 | } 189 | copy((*s)[i:], (*s)[i+1:]) 190 | j := len(*s) - 1 191 | (*s)[j] = nil 192 | *s = (*s)[:j] 193 | } 194 | --------------------------------------------------------------------------------