├── .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 | [](https://travis-ci.org/astaxie/beego)
4 | [](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 |
--------------------------------------------------------------------------------