mirror of
https://github.com/fatedier/frp.git
synced 2026-01-11 22:23:12 +00:00
using glide
This commit is contained in:
17
vendor/github.com/fatedier/beego/.github/ISSUE_TEMPLATE
generated
vendored
Normal file
17
vendor/github.com/fatedier/beego/.github/ISSUE_TEMPLATE
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
|
||||
1. What version of Go and beego are you using (`bee version`)?
|
||||
|
||||
|
||||
2. What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
|
||||
3. What did you do?
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
|
||||
|
||||
4. What did you expect to see?
|
||||
|
||||
|
||||
5. What did you see instead?
|
||||
6
vendor/github.com/fatedier/beego/.gitignore
generated
vendored
Normal file
6
vendor/github.com/fatedier/beego/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.idea
|
||||
.vscode
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.swo
|
||||
beego.iml
|
||||
51
vendor/github.com/fatedier/beego/.travis.yml
generated
vendored
Normal file
51
vendor/github.com/fatedier/beego/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- 1.5.3
|
||||
- 1.4.3
|
||||
services:
|
||||
- redis-server
|
||||
- mysql
|
||||
- postgresql
|
||||
- memcached
|
||||
env:
|
||||
- ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db
|
||||
- ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8"
|
||||
- ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
|
||||
before_install:
|
||||
- git clone git://github.com/ideawu/ssdb.git
|
||||
- cd ssdb
|
||||
- make
|
||||
- cd ..
|
||||
install:
|
||||
- go get github.com/lib/pq
|
||||
- go get github.com/go-sql-driver/mysql
|
||||
- go get github.com/mattn/go-sqlite3
|
||||
- go get github.com/bradfitz/gomemcache/memcache
|
||||
- go get github.com/garyburd/redigo/redis
|
||||
- go get github.com/beego/x2j
|
||||
- go get github.com/couchbase/go-couchbase
|
||||
- go get github.com/beego/goyaml2
|
||||
- go get github.com/belogik/goes
|
||||
- go get github.com/siddontang/ledisdb/config
|
||||
- go get github.com/siddontang/ledisdb/ledis
|
||||
- go get github.com/ssdb/gossdb/ssdb
|
||||
- go get github.com/cloudflare/golz4
|
||||
- go get github.com/gogo/protobuf/proto
|
||||
before_script:
|
||||
- psql --version
|
||||
- sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
|
||||
- sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi"
|
||||
- sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi"
|
||||
- sh -c "if [ $(go version) == *1.[5-9]* ]; then go get github.com/golang/lint/golint; golint ./...; fi"
|
||||
- sh -c "if [ $(go version) == *1.[5-9]* ]; then go tool vet .; fi"
|
||||
- mkdir -p res/var
|
||||
- ./ssdb/ssdb-server ./ssdb/ssdb.conf -d
|
||||
after_script:
|
||||
-killall -w ssdb-server
|
||||
- rm -rf ./res/var/*
|
||||
script:
|
||||
- go test -v ./...
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
52
vendor/github.com/fatedier/beego/CONTRIBUTING.md
generated
vendored
Normal file
52
vendor/github.com/fatedier/beego/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# Contributing to beego
|
||||
|
||||
beego is an open source project.
|
||||
|
||||
It is the work of hundreds of contributors. We appreciate your help!
|
||||
|
||||
Here are instructions to get you started. They are probably not perfect,
|
||||
please let us know if anything feels wrong or incomplete.
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
### Pull requests
|
||||
|
||||
First of all. beego follow the gitflow. So please send you pull request
|
||||
to **develop** branch. We will close the pull request to master branch.
|
||||
|
||||
We are always happy to receive pull requests, and do our best to
|
||||
review them as fast as possible. Not sure if that typo is worth a pull
|
||||
request? Do it! We will appreciate it.
|
||||
|
||||
If your pull request is not accepted on the first try, don't be
|
||||
discouraged! Sometimes we can make a mistake, please do more explaining
|
||||
for us. We will appreciate it.
|
||||
|
||||
We're trying very hard to keep beego simple and fast. We don't want it
|
||||
to do everything for everybody. This means that we might decide against
|
||||
incorporating a new feature. But we will give you some advice on how to
|
||||
do it in other way.
|
||||
|
||||
### Create issues
|
||||
|
||||
Any significant improvement should be documented as [a GitHub
|
||||
issue](https://github.com/astaxie/beego/issues) before anybody
|
||||
starts working on it.
|
||||
|
||||
Also when filing an issue, make sure to answer these five questions:
|
||||
|
||||
- What version of beego are you using (bee version)?
|
||||
- What operating system and processor architecture are you using?
|
||||
- What did you do?
|
||||
- What did you expect to see?
|
||||
- What did you see instead?
|
||||
|
||||
### but check existing issues and docs first!
|
||||
|
||||
Please take a moment to check that an issue doesn't already exist
|
||||
documenting your bug report or improvement proposal. If it does, it
|
||||
never hurts to add a quick "+1" or "I have this problem too". This will
|
||||
help prioritize the most common problems and requests.
|
||||
|
||||
Also if you don't know how to use it. please make sure you have read though
|
||||
the docs in http://beego.me/docs
|
||||
62
vendor/github.com/fatedier/beego/README.md
generated
vendored
Normal file
62
vendor/github.com/fatedier/beego/README.md
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
## Beego
|
||||
|
||||
[](https://travis-ci.org/astaxie/beego)
|
||||
[](http://godoc.org/github.com/astaxie/beego)
|
||||
[](http://golangfoundation.org)
|
||||
|
||||
beego is used for rapid development of RESTful APIs, web apps and backend services in Go.
|
||||
It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific features such as interfaces and struct embedding.
|
||||
|
||||
More info [beego.me](http://beego.me)
|
||||
|
||||
##Quick Start
|
||||
######Download and install
|
||||
|
||||
go get github.com/astaxie/beego
|
||||
|
||||
######Create file `hello.go`
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/astaxie/beego"
|
||||
|
||||
func main(){
|
||||
beego.Run()
|
||||
}
|
||||
```
|
||||
######Build and run
|
||||
```bash
|
||||
go build hello.go
|
||||
./hello
|
||||
```
|
||||
######Congratulations!
|
||||
You just built your first beego app.
|
||||
Open your browser and visit `http://localhost:8080`.
|
||||
Please see [Documentation](http://beego.me/docs) for more.
|
||||
|
||||
## Features
|
||||
|
||||
* RESTful support
|
||||
* MVC architecture
|
||||
* Modularity
|
||||
* Auto API documents
|
||||
* Annotation router
|
||||
* Namespace
|
||||
* Powerful development tools
|
||||
* Full stack for Web & API
|
||||
|
||||
## Documentation
|
||||
|
||||
* [English](http://beego.me/docs/intro/)
|
||||
* [中文文档](http://beego.me/docs/intro/)
|
||||
* [Русский](http://beego.me/docs/intro/)
|
||||
|
||||
## Community
|
||||
|
||||
* [http://beego.me/community](http://beego.me/community)
|
||||
* 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)
|
||||
|
||||
## LICENSE
|
||||
|
||||
beego source code is licensed under the Apache Licence, Version 2.0
|
||||
(http://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
401
vendor/github.com/fatedier/beego/admin.go
generated
vendored
Normal file
401
vendor/github.com/fatedier/beego/admin.go
generated
vendored
Normal file
@@ -0,0 +1,401 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"reflect"
|
||||
|
||||
"github.com/astaxie/beego/grace"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/astaxie/beego/toolbox"
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
// BeeAdminApp is the default adminApp used by admin module.
|
||||
var beeAdminApp *adminApp
|
||||
|
||||
// FilterMonitorFunc is default monitor filter when admin module is enable.
|
||||
// if this func returns, admin module records qbs for this request by condition of this function logic.
|
||||
// usage:
|
||||
// func MyFilterMonitor(method, requestPath string, t time.Duration) bool {
|
||||
// if method == "POST" {
|
||||
// return false
|
||||
// }
|
||||
// if t.Nanoseconds() < 100 {
|
||||
// return false
|
||||
// }
|
||||
// if strings.HasPrefix(requestPath, "/astaxie") {
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
// beego.FilterMonitorFunc = MyFilterMonitor.
|
||||
var FilterMonitorFunc func(string, string, time.Duration) bool
|
||||
|
||||
func init() {
|
||||
beeAdminApp = &adminApp{
|
||||
routers: make(map[string]http.HandlerFunc),
|
||||
}
|
||||
beeAdminApp.Route("/", adminIndex)
|
||||
beeAdminApp.Route("/qps", qpsIndex)
|
||||
beeAdminApp.Route("/prof", profIndex)
|
||||
beeAdminApp.Route("/healthcheck", healthcheck)
|
||||
beeAdminApp.Route("/task", taskStatus)
|
||||
beeAdminApp.Route("/listconf", listConf)
|
||||
FilterMonitorFunc = func(string, string, time.Duration) bool { return true }
|
||||
}
|
||||
|
||||
// AdminIndex is the default http.Handler for admin module.
|
||||
// it matches url pattern "/".
|
||||
func adminIndex(rw http.ResponseWriter, r *http.Request) {
|
||||
execTpl(rw, map[interface{}]interface{}{}, indexTpl, defaultScriptsTpl)
|
||||
}
|
||||
|
||||
// QpsIndex is the http.Handler for writing qbs statistics map result info in http.ResponseWriter.
|
||||
// it's registered with url pattern "/qbs" in admin module.
|
||||
func qpsIndex(rw http.ResponseWriter, r *http.Request) {
|
||||
data := make(map[interface{}]interface{})
|
||||
data["Content"] = toolbox.StatisticsMap.GetMap()
|
||||
execTpl(rw, data, qpsTpl, defaultScriptsTpl)
|
||||
}
|
||||
|
||||
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
|
||||
// it's registered with url pattern "/listconf" in admin module.
|
||||
func listConf(rw http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
command := r.Form.Get("command")
|
||||
if command == "" {
|
||||
rw.Write([]byte("command not support"))
|
||||
return
|
||||
}
|
||||
|
||||
data := make(map[interface{}]interface{})
|
||||
switch command {
|
||||
case "conf":
|
||||
m := make(map[string]interface{})
|
||||
list("BConfig", BConfig, m)
|
||||
m["AppConfigPath"] = appConfigPath
|
||||
m["AppConfigProvider"] = appConfigProvider
|
||||
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
||||
tmpl = template.Must(tmpl.Parse(configTpl))
|
||||
tmpl = template.Must(tmpl.Parse(defaultScriptsTpl))
|
||||
|
||||
data["Content"] = m
|
||||
|
||||
tmpl.Execute(rw, data)
|
||||
|
||||
case "router":
|
||||
var (
|
||||
content = map[string]interface{}{
|
||||
"Fields": []string{
|
||||
"Router Pattern",
|
||||
"Methods",
|
||||
"Controller",
|
||||
},
|
||||
}
|
||||
methods = []string{}
|
||||
methodsData = make(map[string]interface{})
|
||||
)
|
||||
for method, t := range BeeApp.Handlers.routers {
|
||||
|
||||
resultList := new([][]string)
|
||||
|
||||
printTree(resultList, t)
|
||||
|
||||
methods = append(methods, method)
|
||||
methodsData[method] = resultList
|
||||
}
|
||||
|
||||
content["Data"] = methodsData
|
||||
content["Methods"] = methods
|
||||
data["Content"] = content
|
||||
data["Title"] = "Routers"
|
||||
execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
||||
case "filter":
|
||||
var (
|
||||
content = map[string]interface{}{
|
||||
"Fields": []string{
|
||||
"Router Pattern",
|
||||
"Filter Function",
|
||||
},
|
||||
}
|
||||
filterTypes = []string{}
|
||||
filterTypeData = make(map[string]interface{})
|
||||
)
|
||||
|
||||
if BeeApp.Handlers.enableFilter {
|
||||
var filterType string
|
||||
for k, fr := range map[int]string{
|
||||
BeforeStatic: "Before Static",
|
||||
BeforeRouter: "Before Router",
|
||||
BeforeExec: "Before Exec",
|
||||
AfterExec: "After Exec",
|
||||
FinishRouter: "Finish Router"} {
|
||||
if bf := BeeApp.Handlers.filters[k]; len(bf) > 0 {
|
||||
filterType = fr
|
||||
filterTypes = append(filterTypes, filterType)
|
||||
resultList := new([][]string)
|
||||
for _, f := range bf {
|
||||
var result = []string{
|
||||
fmt.Sprintf("%s", f.pattern),
|
||||
fmt.Sprintf("%s", utils.GetFuncName(f.filterFunc)),
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
}
|
||||
filterTypeData[filterType] = resultList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content["Data"] = filterTypeData
|
||||
content["Methods"] = filterTypes
|
||||
|
||||
data["Content"] = content
|
||||
data["Title"] = "Filters"
|
||||
execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
||||
default:
|
||||
rw.Write([]byte("command not support"))
|
||||
}
|
||||
}
|
||||
|
||||
func list(root string, p interface{}, m map[string]interface{}) {
|
||||
pt := reflect.TypeOf(p)
|
||||
pv := reflect.ValueOf(p)
|
||||
if pt.Kind() == reflect.Ptr {
|
||||
pt = pt.Elem()
|
||||
pv = pv.Elem()
|
||||
}
|
||||
for i := 0; i < pv.NumField(); i++ {
|
||||
var key string
|
||||
if root == "" {
|
||||
key = pt.Field(i).Name
|
||||
} else {
|
||||
key = root + "." + pt.Field(i).Name
|
||||
}
|
||||
if pv.Field(i).Kind() == reflect.Struct {
|
||||
list(key, pv.Field(i).Interface(), m)
|
||||
} else {
|
||||
m[key] = pv.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printTree(resultList *[][]string, t *Tree) {
|
||||
for _, tr := range t.fixrouters {
|
||||
printTree(resultList, tr)
|
||||
}
|
||||
if t.wildcard != nil {
|
||||
printTree(resultList, t.wildcard)
|
||||
}
|
||||
for _, l := range t.leaves {
|
||||
if v, ok := l.runObject.(*controllerInfo); ok {
|
||||
if v.routerType == routerTypeBeego {
|
||||
var result = []string{
|
||||
v.pattern,
|
||||
fmt.Sprintf("%s", v.methods),
|
||||
fmt.Sprintf("%s", v.controllerType),
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
} else if v.routerType == routerTypeRESTFul {
|
||||
var result = []string{
|
||||
v.pattern,
|
||||
fmt.Sprintf("%s", v.methods),
|
||||
"",
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
} else if v.routerType == routerTypeHandler {
|
||||
var result = []string{
|
||||
v.pattern,
|
||||
"",
|
||||
"",
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ProfIndex is a http.Handler for showing profile command.
|
||||
// it's in url pattern "/prof" in admin module.
|
||||
func profIndex(rw http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
command := r.Form.Get("command")
|
||||
if command == "" {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
format = r.Form.Get("format")
|
||||
data = make(map[interface{}]interface{})
|
||||
result bytes.Buffer
|
||||
)
|
||||
toolbox.ProcessInput(command, &result)
|
||||
data["Content"] = result.String()
|
||||
|
||||
if format == "json" && command == "gc summary" {
|
||||
dataJSON, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.Write(dataJSON)
|
||||
return
|
||||
}
|
||||
|
||||
data["Title"] = command
|
||||
defaultTpl := defaultScriptsTpl
|
||||
if command == "gc summary" {
|
||||
defaultTpl = gcAjaxTpl
|
||||
}
|
||||
execTpl(rw, data, profillingTpl, defaultTpl)
|
||||
}
|
||||
|
||||
// Healthcheck is a http.Handler calling health checking and showing the result.
|
||||
// it's in "/healthcheck" pattern in admin module.
|
||||
func healthcheck(rw http.ResponseWriter, req *http.Request) {
|
||||
var (
|
||||
data = make(map[interface{}]interface{})
|
||||
result = []string{}
|
||||
resultList = new([][]string)
|
||||
content = map[string]interface{}{
|
||||
"Fields": []string{"Name", "Message", "Status"},
|
||||
}
|
||||
)
|
||||
|
||||
for name, h := range toolbox.AdminCheckList {
|
||||
if err := h.Check(); err != nil {
|
||||
result = []string{
|
||||
fmt.Sprintf("error"),
|
||||
fmt.Sprintf("%s", name),
|
||||
fmt.Sprintf("%s", err.Error()),
|
||||
}
|
||||
|
||||
} else {
|
||||
result = []string{
|
||||
fmt.Sprintf("success"),
|
||||
fmt.Sprintf("%s", name),
|
||||
fmt.Sprintf("OK"),
|
||||
}
|
||||
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
}
|
||||
content["Data"] = resultList
|
||||
data["Content"] = content
|
||||
data["Title"] = "Health Check"
|
||||
execTpl(rw, data, healthCheckTpl, defaultScriptsTpl)
|
||||
}
|
||||
|
||||
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
||||
// it's in "/task" pattern in admin module.
|
||||
func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
||||
data := make(map[interface{}]interface{})
|
||||
|
||||
// Run Task
|
||||
req.ParseForm()
|
||||
taskname := req.Form.Get("taskname")
|
||||
if taskname != "" {
|
||||
if t, ok := toolbox.AdminTaskList[taskname]; ok {
|
||||
if err := t.Run(); err != nil {
|
||||
data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
|
||||
}
|
||||
data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is <br>%s", taskname, t.GetStatus())}
|
||||
} else {
|
||||
data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)}
|
||||
}
|
||||
}
|
||||
|
||||
// List Tasks
|
||||
content := make(map[string]interface{})
|
||||
resultList := new([][]string)
|
||||
var result = []string{}
|
||||
var fields = []string{
|
||||
"Task Name",
|
||||
"Task Spec",
|
||||
"Task Status",
|
||||
"Last Time",
|
||||
"",
|
||||
}
|
||||
for tname, tk := range toolbox.AdminTaskList {
|
||||
result = []string{
|
||||
tname,
|
||||
fmt.Sprintf("%s", tk.GetSpec()),
|
||||
fmt.Sprintf("%s", tk.GetStatus()),
|
||||
tk.GetPrev().String(),
|
||||
}
|
||||
*resultList = append(*resultList, result)
|
||||
}
|
||||
|
||||
content["Fields"] = fields
|
||||
content["Data"] = resultList
|
||||
data["Content"] = content
|
||||
data["Title"] = "Tasks"
|
||||
execTpl(rw, data, tasksTpl, defaultScriptsTpl)
|
||||
}
|
||||
|
||||
func execTpl(rw http.ResponseWriter, data map[interface{}]interface{}, tpls ...string) {
|
||||
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
||||
for _, tpl := range tpls {
|
||||
tmpl = template.Must(tmpl.Parse(tpl))
|
||||
}
|
||||
tmpl.Execute(rw, data)
|
||||
}
|
||||
|
||||
// adminApp is an http.HandlerFunc map used as beeAdminApp.
|
||||
type adminApp struct {
|
||||
routers map[string]http.HandlerFunc
|
||||
}
|
||||
|
||||
// Route adds http.HandlerFunc to adminApp with url pattern.
|
||||
func (admin *adminApp) Route(pattern string, f http.HandlerFunc) {
|
||||
admin.routers[pattern] = f
|
||||
}
|
||||
|
||||
// Run adminApp http server.
|
||||
// Its addr is defined in configuration file as adminhttpaddr and adminhttpport.
|
||||
func (admin *adminApp) Run() {
|
||||
if len(toolbox.AdminTaskList) > 0 {
|
||||
toolbox.StartTask()
|
||||
}
|
||||
addr := BConfig.Listen.AdminAddr
|
||||
|
||||
if BConfig.Listen.AdminPort != 0 {
|
||||
addr = fmt.Sprintf("%s:%d", BConfig.Listen.AdminAddr, BConfig.Listen.AdminPort)
|
||||
}
|
||||
for p, f := range admin.routers {
|
||||
http.Handle(p, f)
|
||||
}
|
||||
logs.Info("Admin server Running on %s", addr)
|
||||
|
||||
var err error
|
||||
if BConfig.Listen.Graceful {
|
||||
err = grace.ListenAndServe(addr, nil)
|
||||
} else {
|
||||
err = http.ListenAndServe(addr, nil)
|
||||
}
|
||||
if err != nil {
|
||||
logs.Critical("Admin ListenAndServe: ", err, fmt.Sprintf("%d", os.Getpid()))
|
||||
}
|
||||
}
|
||||
73
vendor/github.com/fatedier/beego/admin_test.go
generated
vendored
Normal file
73
vendor/github.com/fatedier/beego/admin_test.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
package beego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestList_01(t *testing.T) {
|
||||
m := make(map[string]interface{})
|
||||
list("BConfig", BConfig, m)
|
||||
t.Log(m)
|
||||
om := oldMap()
|
||||
for k, v := range om {
|
||||
if fmt.Sprint(m[k]) != fmt.Sprint(v) {
|
||||
t.Log(k, "old-key", v, "new-key", m[k])
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func oldMap() map[string]interface{} {
|
||||
m := make(map[string]interface{})
|
||||
m["BConfig.AppName"] = BConfig.AppName
|
||||
m["BConfig.RunMode"] = BConfig.RunMode
|
||||
m["BConfig.RouterCaseSensitive"] = BConfig.RouterCaseSensitive
|
||||
m["BConfig.ServerName"] = BConfig.ServerName
|
||||
m["BConfig.RecoverPanic"] = BConfig.RecoverPanic
|
||||
m["BConfig.CopyRequestBody"] = BConfig.CopyRequestBody
|
||||
m["BConfig.EnableGzip"] = BConfig.EnableGzip
|
||||
m["BConfig.MaxMemory"] = BConfig.MaxMemory
|
||||
m["BConfig.EnableErrorsShow"] = BConfig.EnableErrorsShow
|
||||
m["BConfig.Listen.Graceful"] = BConfig.Listen.Graceful
|
||||
m["BConfig.Listen.ServerTimeOut"] = BConfig.Listen.ServerTimeOut
|
||||
m["BConfig.Listen.ListenTCP4"] = BConfig.Listen.ListenTCP4
|
||||
m["BConfig.Listen.EnableHTTP"] = BConfig.Listen.EnableHTTP
|
||||
m["BConfig.Listen.HTTPAddr"] = BConfig.Listen.HTTPAddr
|
||||
m["BConfig.Listen.HTTPPort"] = BConfig.Listen.HTTPPort
|
||||
m["BConfig.Listen.EnableHTTPS"] = BConfig.Listen.EnableHTTPS
|
||||
m["BConfig.Listen.HTTPSAddr"] = BConfig.Listen.HTTPSAddr
|
||||
m["BConfig.Listen.HTTPSPort"] = BConfig.Listen.HTTPSPort
|
||||
m["BConfig.Listen.HTTPSCertFile"] = BConfig.Listen.HTTPSCertFile
|
||||
m["BConfig.Listen.HTTPSKeyFile"] = BConfig.Listen.HTTPSKeyFile
|
||||
m["BConfig.Listen.EnableAdmin"] = BConfig.Listen.EnableAdmin
|
||||
m["BConfig.Listen.AdminAddr"] = BConfig.Listen.AdminAddr
|
||||
m["BConfig.Listen.AdminPort"] = BConfig.Listen.AdminPort
|
||||
m["BConfig.Listen.EnableFcgi"] = BConfig.Listen.EnableFcgi
|
||||
m["BConfig.Listen.EnableStdIo"] = BConfig.Listen.EnableStdIo
|
||||
m["BConfig.WebConfig.AutoRender"] = BConfig.WebConfig.AutoRender
|
||||
m["BConfig.WebConfig.EnableDocs"] = BConfig.WebConfig.EnableDocs
|
||||
m["BConfig.WebConfig.FlashName"] = BConfig.WebConfig.FlashName
|
||||
m["BConfig.WebConfig.FlashSeparator"] = BConfig.WebConfig.FlashSeparator
|
||||
m["BConfig.WebConfig.DirectoryIndex"] = BConfig.WebConfig.DirectoryIndex
|
||||
m["BConfig.WebConfig.StaticDir"] = BConfig.WebConfig.StaticDir
|
||||
m["BConfig.WebConfig.StaticExtensionsToGzip"] = BConfig.WebConfig.StaticExtensionsToGzip
|
||||
m["BConfig.WebConfig.TemplateLeft"] = BConfig.WebConfig.TemplateLeft
|
||||
m["BConfig.WebConfig.TemplateRight"] = BConfig.WebConfig.TemplateRight
|
||||
m["BConfig.WebConfig.ViewsPath"] = BConfig.WebConfig.ViewsPath
|
||||
m["BConfig.WebConfig.EnableXSRF"] = BConfig.WebConfig.EnableXSRF
|
||||
m["BConfig.WebConfig.XSRFExpire"] = BConfig.WebConfig.XSRFExpire
|
||||
m["BConfig.WebConfig.Session.SessionOn"] = BConfig.WebConfig.Session.SessionOn
|
||||
m["BConfig.WebConfig.Session.SessionProvider"] = BConfig.WebConfig.Session.SessionProvider
|
||||
m["BConfig.WebConfig.Session.SessionName"] = BConfig.WebConfig.Session.SessionName
|
||||
m["BConfig.WebConfig.Session.SessionGCMaxLifetime"] = BConfig.WebConfig.Session.SessionGCMaxLifetime
|
||||
m["BConfig.WebConfig.Session.SessionProviderConfig"] = BConfig.WebConfig.Session.SessionProviderConfig
|
||||
m["BConfig.WebConfig.Session.SessionCookieLifeTime"] = BConfig.WebConfig.Session.SessionCookieLifeTime
|
||||
m["BConfig.WebConfig.Session.SessionAutoSetCookie"] = BConfig.WebConfig.Session.SessionAutoSetCookie
|
||||
m["BConfig.WebConfig.Session.SessionDomain"] = BConfig.WebConfig.Session.SessionDomain
|
||||
m["BConfig.WebConfig.Session.SessionDisableHTTPOnly"] = BConfig.WebConfig.Session.SessionDisableHTTPOnly
|
||||
m["BConfig.Log.AccessLogs"] = BConfig.Log.AccessLogs
|
||||
m["BConfig.Log.FileLineNum"] = BConfig.Log.FileLineNum
|
||||
m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
|
||||
return m
|
||||
}
|
||||
356
vendor/github.com/fatedier/beego/adminui.go
generated
vendored
Normal file
356
vendor/github.com/fatedier/beego/adminui.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
366
vendor/github.com/fatedier/beego/app.go
generated
vendored
Normal file
366
vendor/github.com/fatedier/beego/app.go
generated
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/fcgi"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/grace"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
// BeeApp is an application instance
|
||||
BeeApp *App
|
||||
)
|
||||
|
||||
func init() {
|
||||
// create beego application
|
||||
BeeApp = NewApp()
|
||||
}
|
||||
|
||||
// App defines beego application with a new PatternServeMux.
|
||||
type App struct {
|
||||
Handlers *ControllerRegister
|
||||
Server *http.Server
|
||||
}
|
||||
|
||||
// NewApp returns a new beego application.
|
||||
func NewApp() *App {
|
||||
cr := NewControllerRegister()
|
||||
app := &App{Handlers: cr, Server: &http.Server{}}
|
||||
return app
|
||||
}
|
||||
|
||||
// Run beego application.
|
||||
func (app *App) Run() {
|
||||
addr := BConfig.Listen.HTTPAddr
|
||||
|
||||
if BConfig.Listen.HTTPPort != 0 {
|
||||
addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPAddr, BConfig.Listen.HTTPPort)
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
l net.Listener
|
||||
endRunning = make(chan bool, 1)
|
||||
)
|
||||
|
||||
// run cgi server
|
||||
if BConfig.Listen.EnableFcgi {
|
||||
if BConfig.Listen.EnableStdIo {
|
||||
if err = fcgi.Serve(nil, app.Handlers); err == nil { // standard I/O
|
||||
logs.Info("Use FCGI via standard I/O")
|
||||
} else {
|
||||
logs.Critical("Cannot use FCGI via standard I/O", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if BConfig.Listen.HTTPPort == 0 {
|
||||
// remove the Socket file before start
|
||||
if utils.FileExists(addr) {
|
||||
os.Remove(addr)
|
||||
}
|
||||
l, err = net.Listen("unix", addr)
|
||||
} else {
|
||||
l, err = net.Listen("tcp", addr)
|
||||
}
|
||||
if err != nil {
|
||||
logs.Critical("Listen: ", err)
|
||||
}
|
||||
if err = fcgi.Serve(l, app.Handlers); err != nil {
|
||||
logs.Critical("fcgi.Serve: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
app.Server.Handler = app.Handlers
|
||||
app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
|
||||
app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
|
||||
app.Server.ErrorLog = logs.GetLogger("HTTP")
|
||||
|
||||
// run graceful mode
|
||||
if BConfig.Listen.Graceful {
|
||||
httpsAddr := BConfig.Listen.HTTPSAddr
|
||||
app.Server.Addr = httpsAddr
|
||||
if BConfig.Listen.EnableHTTPS {
|
||||
go func() {
|
||||
time.Sleep(20 * time.Microsecond)
|
||||
if BConfig.Listen.HTTPSPort != 0 {
|
||||
httpsAddr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
|
||||
app.Server.Addr = httpsAddr
|
||||
}
|
||||
server := grace.NewServer(httpsAddr, app.Handlers)
|
||||
server.Server.ReadTimeout = app.Server.ReadTimeout
|
||||
server.Server.WriteTimeout = app.Server.WriteTimeout
|
||||
if err := server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
|
||||
logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}()
|
||||
}
|
||||
if BConfig.Listen.EnableHTTP {
|
||||
go func() {
|
||||
server := grace.NewServer(addr, app.Handlers)
|
||||
server.Server.ReadTimeout = app.Server.ReadTimeout
|
||||
server.Server.WriteTimeout = app.Server.WriteTimeout
|
||||
if BConfig.Listen.ListenTCP4 {
|
||||
server.Network = "tcp4"
|
||||
}
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
logs.Critical("ListenAndServe: ", err, fmt.Sprintf("%d", os.Getpid()))
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}()
|
||||
}
|
||||
<-endRunning
|
||||
return
|
||||
}
|
||||
|
||||
// run normal mode
|
||||
if BConfig.Listen.EnableHTTPS {
|
||||
go func() {
|
||||
time.Sleep(20 * time.Microsecond)
|
||||
if BConfig.Listen.HTTPSPort != 0 {
|
||||
app.Server.Addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
|
||||
} else if BConfig.Listen.EnableHTTP {
|
||||
BeeLogger.Info("Start https server error, confict with http.Please reset https port")
|
||||
return
|
||||
}
|
||||
logs.Info("https server Running on https://%s", app.Server.Addr)
|
||||
if err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
|
||||
logs.Critical("ListenAndServeTLS: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}()
|
||||
}
|
||||
if BConfig.Listen.EnableHTTP {
|
||||
go func() {
|
||||
app.Server.Addr = addr
|
||||
logs.Info("http server Running on http://%s", app.Server.Addr)
|
||||
if BConfig.Listen.ListenTCP4 {
|
||||
ln, err := net.Listen("tcp4", app.Server.Addr)
|
||||
if err != nil {
|
||||
logs.Critical("ListenAndServe: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
return
|
||||
}
|
||||
if err = app.Server.Serve(ln); err != nil {
|
||||
logs.Critical("ListenAndServe: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := app.Server.ListenAndServe(); err != nil {
|
||||
logs.Critical("ListenAndServe: ", err)
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
endRunning <- true
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
<-endRunning
|
||||
}
|
||||
|
||||
// Router adds a patterned controller handler to BeeApp.
|
||||
// it's an alias method of App.Router.
|
||||
// usage:
|
||||
// simple router
|
||||
// beego.Router("/admin", &admin.UserController{})
|
||||
// beego.Router("/admin/index", &admin.ArticleController{})
|
||||
//
|
||||
// regex router
|
||||
//
|
||||
// beego.Router("/api/:id([0-9]+)", &controllers.RController{})
|
||||
//
|
||||
// custom rules
|
||||
// beego.Router("/api/list",&RestController{},"*:ListFood")
|
||||
// beego.Router("/api/create",&RestController{},"post:CreateFood")
|
||||
// beego.Router("/api/update",&RestController{},"put:UpdateFood")
|
||||
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
|
||||
func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
|
||||
BeeApp.Handlers.Add(rootpath, c, mappingMethods...)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Include will generate router file in the router/xxx.go from the controller's comments
|
||||
// usage:
|
||||
// beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
|
||||
// type BankAccount struct{
|
||||
// beego.Controller
|
||||
// }
|
||||
//
|
||||
// register the function
|
||||
// func (b *BankAccount)Mapping(){
|
||||
// b.Mapping("ShowAccount" , b.ShowAccount)
|
||||
// b.Mapping("ModifyAccount", b.ModifyAccount)
|
||||
//}
|
||||
//
|
||||
// //@router /account/:id [get]
|
||||
// func (b *BankAccount) ShowAccount(){
|
||||
// //logic
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //@router /account/:id [post]
|
||||
// func (b *BankAccount) ModifyAccount(){
|
||||
// //logic
|
||||
// }
|
||||
//
|
||||
// the comments @router url methodlist
|
||||
// url support all the function Router's pattern
|
||||
// methodlist [get post head put delete options *]
|
||||
func Include(cList ...ControllerInterface) *App {
|
||||
BeeApp.Handlers.Include(cList...)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// RESTRouter adds a restful controller handler to BeeApp.
|
||||
// its' controller implements beego.ControllerInterface and
|
||||
// defines a param "pattern/:objectId" to visit each resource.
|
||||
func RESTRouter(rootpath string, c ControllerInterface) *App {
|
||||
Router(rootpath, c)
|
||||
Router(path.Join(rootpath, ":objectId"), c)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// AutoRouter adds defined controller handler to BeeApp.
|
||||
// it's same to App.AutoRouter.
|
||||
// if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
|
||||
// visit the url /main/list to exec List function or /main/page to exec Page function.
|
||||
func AutoRouter(c ControllerInterface) *App {
|
||||
BeeApp.Handlers.AddAuto(c)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// AutoPrefix adds controller handler to BeeApp with prefix.
|
||||
// it's same to App.AutoRouterWithPrefix.
|
||||
// if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
|
||||
// visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
|
||||
func AutoPrefix(prefix string, c ControllerInterface) *App {
|
||||
BeeApp.Handlers.AddAutoPrefix(prefix, c)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Get used to register router for Get method
|
||||
// usage:
|
||||
// beego.Get("/", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Get(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Get(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Post used to register router for Post method
|
||||
// usage:
|
||||
// beego.Post("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Post(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Post(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Delete used to register router for Delete method
|
||||
// usage:
|
||||
// beego.Delete("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Delete(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Delete(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Put used to register router for Put method
|
||||
// usage:
|
||||
// beego.Put("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Put(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Put(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Head used to register router for Head method
|
||||
// usage:
|
||||
// beego.Head("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Head(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Head(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Options used to register router for Options method
|
||||
// usage:
|
||||
// beego.Options("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Options(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Options(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Patch used to register router for Patch method
|
||||
// usage:
|
||||
// beego.Patch("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Patch(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Patch(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Any used to register router for all methods
|
||||
// usage:
|
||||
// beego.Any("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Any(rootpath string, f FilterFunc) *App {
|
||||
BeeApp.Handlers.Any(rootpath, f)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Handler used to register a Handler router
|
||||
// usage:
|
||||
// beego.Handler("/api", func(ctx *context.Context){
|
||||
// ctx.Output.Body("hello world")
|
||||
// })
|
||||
func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
|
||||
BeeApp.Handlers.Handler(rootpath, h, options...)
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// InsertFilter adds a FilterFunc with pattern condition and action constant.
|
||||
// The pos means action constant including
|
||||
// beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
|
||||
// The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
|
||||
func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App {
|
||||
BeeApp.Handlers.InsertFilter(pattern, pos, filter, params...)
|
||||
return BeeApp
|
||||
}
|
||||
100
vendor/github.com/fatedier/beego/beego.go
generated
vendored
Normal file
100
vendor/github.com/fatedier/beego/beego.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// VERSION represent beego web framework version.
|
||||
VERSION = "1.8.0"
|
||||
|
||||
// DEV is for develop
|
||||
DEV = "dev"
|
||||
// PROD is for production
|
||||
PROD = "prod"
|
||||
)
|
||||
|
||||
//hook function to run
|
||||
type hookfunc func() error
|
||||
|
||||
var (
|
||||
hooks = make([]hookfunc, 0) //hook function slice to store the hookfunc
|
||||
)
|
||||
|
||||
// AddAPPStartHook is used to register the hookfunc
|
||||
// The hookfuncs will run in beego.Run()
|
||||
// such as sessionInit, middlerware start, buildtemplate, admin start
|
||||
func AddAPPStartHook(hf hookfunc) {
|
||||
hooks = append(hooks, hf)
|
||||
}
|
||||
|
||||
// Run beego application.
|
||||
// beego.Run() default run on HttpPort
|
||||
// beego.Run("localhost")
|
||||
// beego.Run(":8089")
|
||||
// beego.Run("127.0.0.1:8089")
|
||||
func Run(params ...string) {
|
||||
|
||||
initBeforeHTTPRun()
|
||||
|
||||
if len(params) > 0 && params[0] != "" {
|
||||
strs := strings.Split(params[0], ":")
|
||||
if len(strs) > 0 && strs[0] != "" {
|
||||
BConfig.Listen.HTTPAddr = strs[0]
|
||||
}
|
||||
if len(strs) > 1 && strs[1] != "" {
|
||||
BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1])
|
||||
}
|
||||
}
|
||||
|
||||
BeeApp.Run()
|
||||
}
|
||||
|
||||
func initBeforeHTTPRun() {
|
||||
//init hooks
|
||||
AddAPPStartHook(registerMime)
|
||||
AddAPPStartHook(registerDefaultErrorHandler)
|
||||
AddAPPStartHook(registerSession)
|
||||
AddAPPStartHook(registerTemplate)
|
||||
AddAPPStartHook(registerAdmin)
|
||||
AddAPPStartHook(registerGzip)
|
||||
|
||||
for _, hk := range hooks {
|
||||
if err := hk(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestBeegoInit is for test package init
|
||||
func TestBeegoInit(ap string) {
|
||||
path := filepath.Join(ap, "conf", "app.conf")
|
||||
os.Chdir(ap)
|
||||
InitBeegoBeforeTest(path)
|
||||
}
|
||||
|
||||
// InitBeegoBeforeTest is for test package init
|
||||
func InitBeegoBeforeTest(appConfigPath string) {
|
||||
if err := LoadAppConfig(appConfigProvider, appConfigPath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
BConfig.RunMode = "test"
|
||||
initBeforeHTTPRun()
|
||||
}
|
||||
59
vendor/github.com/fatedier/beego/cache/README.md
generated
vendored
Normal file
59
vendor/github.com/fatedier/beego/cache/README.md
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
## cache
|
||||
cache is a Go cache manager. It can use many cache adapters. The repo is inspired by `database/sql` .
|
||||
|
||||
|
||||
## How to install?
|
||||
|
||||
go get github.com/astaxie/beego/cache
|
||||
|
||||
|
||||
## What adapters are supported?
|
||||
|
||||
As of now this cache support memory, Memcache and Redis.
|
||||
|
||||
|
||||
## How to use it?
|
||||
|
||||
First you must import it
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
Then init a Cache (example with memory adapter)
|
||||
|
||||
bm, err := cache.NewCache("memory", `{"interval":60}`)
|
||||
|
||||
Use it like this:
|
||||
|
||||
bm.Put("astaxie", 1, 10 * time.Second)
|
||||
bm.Get("astaxie")
|
||||
bm.IsExist("astaxie")
|
||||
bm.Delete("astaxie")
|
||||
|
||||
|
||||
## Memory adapter
|
||||
|
||||
Configure memory adapter like this:
|
||||
|
||||
{"interval":60}
|
||||
|
||||
interval means the gc time. The cache will check at each time interval, whether item has expired.
|
||||
|
||||
|
||||
## Memcache adapter
|
||||
|
||||
Memcache adapter use the [gomemcache](http://github.com/bradfitz/gomemcache) client.
|
||||
|
||||
Configure like this:
|
||||
|
||||
{"conn":"127.0.0.1:11211"}
|
||||
|
||||
|
||||
## Redis adapter
|
||||
|
||||
Redis adapter use the [redigo](http://github.com/garyburd/redigo) client.
|
||||
|
||||
Configure like this:
|
||||
|
||||
{"conn":":6039"}
|
||||
103
vendor/github.com/fatedier/beego/cache/cache.go
generated
vendored
Normal file
103
vendor/github.com/fatedier/beego/cache/cache.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package cache provide a Cache interface and some implemetn engine
|
||||
// Usage:
|
||||
//
|
||||
// import(
|
||||
// "github.com/astaxie/beego/cache"
|
||||
// )
|
||||
//
|
||||
// bm, err := cache.NewCache("memory", `{"interval":60}`)
|
||||
//
|
||||
// Use it like this:
|
||||
//
|
||||
// bm.Put("astaxie", 1, 10 * time.Second)
|
||||
// bm.Get("astaxie")
|
||||
// bm.IsExist("astaxie")
|
||||
// bm.Delete("astaxie")
|
||||
//
|
||||
// more docs http://beego.me/docs/module/cache.md
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cache interface contains all behaviors for cache adapter.
|
||||
// usage:
|
||||
// cache.Register("file",cache.NewFileCache) // this operation is run in init method of file.go.
|
||||
// c,err := cache.NewCache("file","{....}")
|
||||
// c.Put("key",value, 3600 * time.Second)
|
||||
// v := c.Get("key")
|
||||
//
|
||||
// c.Incr("counter") // now is 1
|
||||
// c.Incr("counter") // now is 2
|
||||
// count := c.Get("counter").(int)
|
||||
type Cache interface {
|
||||
// get cached value by key.
|
||||
Get(key string) interface{}
|
||||
// GetMulti is a batch version of Get.
|
||||
GetMulti(keys []string) []interface{}
|
||||
// set cached value with key and expire time.
|
||||
Put(key string, val interface{}, timeout time.Duration) error
|
||||
// delete cached value by key.
|
||||
Delete(key string) error
|
||||
// increase cached int value by key, as a counter.
|
||||
Incr(key string) error
|
||||
// decrease cached int value by key, as a counter.
|
||||
Decr(key string) error
|
||||
// check if cached value exists or not.
|
||||
IsExist(key string) bool
|
||||
// clear all cache.
|
||||
ClearAll() error
|
||||
// start gc routine based on config string settings.
|
||||
StartAndGC(config string) error
|
||||
}
|
||||
|
||||
// Instance is a function create a new Cache Instance
|
||||
type Instance func() Cache
|
||||
|
||||
var adapters = make(map[string]Instance)
|
||||
|
||||
// Register makes a cache adapter available by the adapter name.
|
||||
// If Register is called twice with the same name or if driver is nil,
|
||||
// it panics.
|
||||
func Register(name string, adapter Instance) {
|
||||
if adapter == nil {
|
||||
panic("cache: Register adapter is nil")
|
||||
}
|
||||
if _, ok := adapters[name]; ok {
|
||||
panic("cache: Register called twice for adapter " + name)
|
||||
}
|
||||
adapters[name] = adapter
|
||||
}
|
||||
|
||||
// NewCache Create a new cache driver by adapter name and config string.
|
||||
// config need to be correct JSON as string: {"interval":360}.
|
||||
// it will start gc automatically.
|
||||
func NewCache(adapterName, config string) (adapter Cache, err error) {
|
||||
instanceFunc, ok := adapters[adapterName]
|
||||
if !ok {
|
||||
err = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName)
|
||||
return
|
||||
}
|
||||
adapter = instanceFunc()
|
||||
err = adapter.StartAndGC(config)
|
||||
if err != nil {
|
||||
adapter = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
168
vendor/github.com/fatedier/beego/cache/cache_test.go
generated
vendored
Normal file
168
vendor/github.com/fatedier/beego/cache/cache_test.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
bm, err := NewCache("memory", `{"interval":20}`)
|
||||
if err != nil {
|
||||
t.Error("init err")
|
||||
}
|
||||
timeoutDuration := 10 * time.Second
|
||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
time.Sleep(30 * time.Second)
|
||||
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
|
||||
if err = bm.Incr("astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 2 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Decr("astaxie"); err != nil {
|
||||
t.Error("Decr Error", err)
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
bm.Delete("astaxie")
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
//test GetMulti
|
||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
if v := bm.Get("astaxie"); v.(string) != "author" {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||
if len(vv) != 2 {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if vv[0].(string) != "author" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if vv[1].(string) != "author1" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileCache(t *testing.T) {
|
||||
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}`)
|
||||
if err != nil {
|
||||
t.Error("init err")
|
||||
}
|
||||
timeoutDuration := 10 * time.Second
|
||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Incr("astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 2 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Decr("astaxie"); err != nil {
|
||||
t.Error("Decr Error", err)
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie"); v.(int) != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
bm.Delete("astaxie")
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
//test string
|
||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
if v := bm.Get("astaxie"); v.(string) != "author" {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
//test GetMulti
|
||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||
if len(vv) != 2 {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if vv[0].(string) != "author" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if vv[1].(string) != "author1" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
|
||||
os.RemoveAll("cache")
|
||||
}
|
||||
100
vendor/github.com/fatedier/beego/cache/conv.go
generated
vendored
Normal file
100
vendor/github.com/fatedier/beego/cache/conv.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// GetString convert interface to string.
|
||||
func GetString(v interface{}) string {
|
||||
switch result := v.(type) {
|
||||
case string:
|
||||
return result
|
||||
case []byte:
|
||||
return string(result)
|
||||
default:
|
||||
if v != nil {
|
||||
return fmt.Sprintf("%v", result)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetInt convert interface to int.
|
||||
func GetInt(v interface{}) int {
|
||||
switch result := v.(type) {
|
||||
case int:
|
||||
return result
|
||||
case int32:
|
||||
return int(result)
|
||||
case int64:
|
||||
return int(result)
|
||||
default:
|
||||
if d := GetString(v); d != "" {
|
||||
value, _ := strconv.Atoi(d)
|
||||
return value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInt64 convert interface to int64.
|
||||
func GetInt64(v interface{}) int64 {
|
||||
switch result := v.(type) {
|
||||
case int:
|
||||
return int64(result)
|
||||
case int32:
|
||||
return int64(result)
|
||||
case int64:
|
||||
return result
|
||||
default:
|
||||
|
||||
if d := GetString(v); d != "" {
|
||||
value, _ := strconv.ParseInt(d, 10, 64)
|
||||
return value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetFloat64 convert interface to float64.
|
||||
func GetFloat64(v interface{}) float64 {
|
||||
switch result := v.(type) {
|
||||
case float64:
|
||||
return result
|
||||
default:
|
||||
if d := GetString(v); d != "" {
|
||||
value, _ := strconv.ParseFloat(d, 64)
|
||||
return value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetBool convert interface to bool.
|
||||
func GetBool(v interface{}) bool {
|
||||
switch result := v.(type) {
|
||||
case bool:
|
||||
return result
|
||||
default:
|
||||
if d := GetString(v); d != "" {
|
||||
value, _ := strconv.ParseBool(d)
|
||||
return value
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
143
vendor/github.com/fatedier/beego/cache/conv_test.go
generated
vendored
Normal file
143
vendor/github.com/fatedier/beego/cache/conv_test.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetString(t *testing.T) {
|
||||
var t1 = "test1"
|
||||
if "test1" != GetString(t1) {
|
||||
t.Error("get string from string error")
|
||||
}
|
||||
var t2 = []byte("test2")
|
||||
if "test2" != GetString(t2) {
|
||||
t.Error("get string from byte array error")
|
||||
}
|
||||
var t3 = 1
|
||||
if "1" != GetString(t3) {
|
||||
t.Error("get string from int error")
|
||||
}
|
||||
var t4 int64 = 1
|
||||
if "1" != GetString(t4) {
|
||||
t.Error("get string from int64 error")
|
||||
}
|
||||
var t5 = 1.1
|
||||
if "1.1" != GetString(t5) {
|
||||
t.Error("get string from float64 error")
|
||||
}
|
||||
|
||||
if "" != GetString(nil) {
|
||||
t.Error("get string from nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInt(t *testing.T) {
|
||||
var t1 = 1
|
||||
if 1 != GetInt(t1) {
|
||||
t.Error("get int from int error")
|
||||
}
|
||||
var t2 int32 = 32
|
||||
if 32 != GetInt(t2) {
|
||||
t.Error("get int from int32 error")
|
||||
}
|
||||
var t3 int64 = 64
|
||||
if 64 != GetInt(t3) {
|
||||
t.Error("get int from int64 error")
|
||||
}
|
||||
var t4 = "128"
|
||||
if 128 != GetInt(t4) {
|
||||
t.Error("get int from num string error")
|
||||
}
|
||||
if 0 != GetInt(nil) {
|
||||
t.Error("get int from nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInt64(t *testing.T) {
|
||||
var i int64 = 1
|
||||
var t1 = 1
|
||||
if i != GetInt64(t1) {
|
||||
t.Error("get int64 from int error")
|
||||
}
|
||||
var t2 int32 = 1
|
||||
if i != GetInt64(t2) {
|
||||
t.Error("get int64 from int32 error")
|
||||
}
|
||||
var t3 int64 = 1
|
||||
if i != GetInt64(t3) {
|
||||
t.Error("get int64 from int64 error")
|
||||
}
|
||||
var t4 = "1"
|
||||
if i != GetInt64(t4) {
|
||||
t.Error("get int64 from num string error")
|
||||
}
|
||||
if 0 != GetInt64(nil) {
|
||||
t.Error("get int64 from nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFloat64(t *testing.T) {
|
||||
var f = 1.11
|
||||
var t1 float32 = 1.11
|
||||
if f != GetFloat64(t1) {
|
||||
t.Error("get float64 from float32 error")
|
||||
}
|
||||
var t2 = 1.11
|
||||
if f != GetFloat64(t2) {
|
||||
t.Error("get float64 from float64 error")
|
||||
}
|
||||
var t3 = "1.11"
|
||||
if f != GetFloat64(t3) {
|
||||
t.Error("get float64 from string error")
|
||||
}
|
||||
|
||||
var f2 float64 = 1
|
||||
var t4 = 1
|
||||
if f2 != GetFloat64(t4) {
|
||||
t.Error("get float64 from int error")
|
||||
}
|
||||
|
||||
if 0 != GetFloat64(nil) {
|
||||
t.Error("get float64 from nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBool(t *testing.T) {
|
||||
var t1 = true
|
||||
if true != GetBool(t1) {
|
||||
t.Error("get bool from bool error")
|
||||
}
|
||||
var t2 = "true"
|
||||
if true != GetBool(t2) {
|
||||
t.Error("get bool from string error")
|
||||
}
|
||||
if false != GetBool(nil) {
|
||||
t.Error("get bool from nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func byteArrayEquals(a []byte, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
255
vendor/github.com/fatedier/beego/cache/file.go
generated
vendored
Normal file
255
vendor/github.com/fatedier/beego/cache/file.go
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/gob"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FileCacheItem is basic unit of file cache adapter.
|
||||
// it contains data and expire time.
|
||||
type FileCacheItem struct {
|
||||
Data interface{}
|
||||
Lastaccess time.Time
|
||||
Expired time.Time
|
||||
}
|
||||
|
||||
// FileCache Config
|
||||
var (
|
||||
FileCachePath = "cache" // cache directory
|
||||
FileCacheFileSuffix = ".bin" // cache file suffix
|
||||
FileCacheDirectoryLevel = 2 // cache file deep level if auto generated cache files.
|
||||
FileCacheEmbedExpiry time.Duration // cache expire time, default is no expire forever.
|
||||
)
|
||||
|
||||
// FileCache is cache adapter for file storage.
|
||||
type FileCache struct {
|
||||
CachePath string
|
||||
FileSuffix string
|
||||
DirectoryLevel int
|
||||
EmbedExpiry int
|
||||
}
|
||||
|
||||
// NewFileCache Create new file cache with no config.
|
||||
// the level and expiry need set in method StartAndGC as config string.
|
||||
func NewFileCache() Cache {
|
||||
// return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix}
|
||||
return &FileCache{}
|
||||
}
|
||||
|
||||
// StartAndGC will start and begin gc for file cache.
|
||||
// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}
|
||||
func (fc *FileCache) StartAndGC(config string) error {
|
||||
|
||||
var cfg map[string]string
|
||||
json.Unmarshal([]byte(config), &cfg)
|
||||
if _, ok := cfg["CachePath"]; !ok {
|
||||
cfg["CachePath"] = FileCachePath
|
||||
}
|
||||
if _, ok := cfg["FileSuffix"]; !ok {
|
||||
cfg["FileSuffix"] = FileCacheFileSuffix
|
||||
}
|
||||
if _, ok := cfg["DirectoryLevel"]; !ok {
|
||||
cfg["DirectoryLevel"] = strconv.Itoa(FileCacheDirectoryLevel)
|
||||
}
|
||||
if _, ok := cfg["EmbedExpiry"]; !ok {
|
||||
cfg["EmbedExpiry"] = strconv.FormatInt(int64(FileCacheEmbedExpiry.Seconds()), 10)
|
||||
}
|
||||
fc.CachePath = cfg["CachePath"]
|
||||
fc.FileSuffix = cfg["FileSuffix"]
|
||||
fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"])
|
||||
fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"])
|
||||
|
||||
fc.Init()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init will make new dir for file cache if not exist.
|
||||
func (fc *FileCache) Init() {
|
||||
if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
|
||||
_ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
|
||||
}
|
||||
}
|
||||
|
||||
// get cached file name. it's md5 encoded.
|
||||
func (fc *FileCache) getCacheFileName(key string) string {
|
||||
m := md5.New()
|
||||
io.WriteString(m, key)
|
||||
keyMd5 := hex.EncodeToString(m.Sum(nil))
|
||||
cachePath := fc.CachePath
|
||||
switch fc.DirectoryLevel {
|
||||
case 2:
|
||||
cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4])
|
||||
case 1:
|
||||
cachePath = filepath.Join(cachePath, keyMd5[0:2])
|
||||
}
|
||||
|
||||
if ok, _ := exists(cachePath); !ok { // todo : error handle
|
||||
_ = os.MkdirAll(cachePath, os.ModePerm) // todo : error handle
|
||||
}
|
||||
|
||||
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix))
|
||||
}
|
||||
|
||||
// Get value from file cache.
|
||||
// if non-exist or expired, return empty string.
|
||||
func (fc *FileCache) Get(key string) interface{} {
|
||||
fileData, err := FileGetContents(fc.getCacheFileName(key))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var to FileCacheItem
|
||||
GobDecode(fileData, &to)
|
||||
if to.Expired.Before(time.Now()) {
|
||||
return ""
|
||||
}
|
||||
return to.Data
|
||||
}
|
||||
|
||||
// GetMulti gets values from file cache.
|
||||
// if non-exist or expired, return empty string.
|
||||
func (fc *FileCache) GetMulti(keys []string) []interface{} {
|
||||
var rc []interface{}
|
||||
for _, key := range keys {
|
||||
rc = append(rc, fc.Get(key))
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
// Put value into file cache.
|
||||
// timeout means how long to keep this file, unit of ms.
|
||||
// if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever.
|
||||
func (fc *FileCache) Put(key string, val interface{}, timeout time.Duration) error {
|
||||
gob.Register(val)
|
||||
|
||||
item := FileCacheItem{Data: val}
|
||||
if timeout == FileCacheEmbedExpiry {
|
||||
item.Expired = time.Now().Add((86400 * 365 * 10) * time.Second) // ten years
|
||||
} else {
|
||||
item.Expired = time.Now().Add(timeout)
|
||||
}
|
||||
item.Lastaccess = time.Now()
|
||||
data, err := GobEncode(item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return FilePutContents(fc.getCacheFileName(key), data)
|
||||
}
|
||||
|
||||
// Delete file cache value.
|
||||
func (fc *FileCache) Delete(key string) error {
|
||||
filename := fc.getCacheFileName(key)
|
||||
if ok, _ := exists(filename); ok {
|
||||
return os.Remove(filename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Incr will increase cached int value.
|
||||
// fc value is saving forever unless Delete.
|
||||
func (fc *FileCache) Incr(key string) error {
|
||||
data := fc.Get(key)
|
||||
var incr int
|
||||
if reflect.TypeOf(data).Name() != "int" {
|
||||
incr = 0
|
||||
} else {
|
||||
incr = data.(int) + 1
|
||||
}
|
||||
fc.Put(key, incr, FileCacheEmbedExpiry)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decr will decrease cached int value.
|
||||
func (fc *FileCache) Decr(key string) error {
|
||||
data := fc.Get(key)
|
||||
var decr int
|
||||
if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 {
|
||||
decr = 0
|
||||
} else {
|
||||
decr = data.(int) - 1
|
||||
}
|
||||
fc.Put(key, decr, FileCacheEmbedExpiry)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsExist check value is exist.
|
||||
func (fc *FileCache) IsExist(key string) bool {
|
||||
ret, _ := exists(fc.getCacheFileName(key))
|
||||
return ret
|
||||
}
|
||||
|
||||
// ClearAll will clean cached files.
|
||||
// not implemented.
|
||||
func (fc *FileCache) ClearAll() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check file exist.
|
||||
func exists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
// FileGetContents Get bytes to file.
|
||||
// if non-exist, create this file.
|
||||
func FileGetContents(filename string) (data []byte, e error) {
|
||||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
|
||||
// FilePutContents Put bytes to file.
|
||||
// if non-exist, create this file.
|
||||
func FilePutContents(filename string, content []byte) error {
|
||||
return ioutil.WriteFile(filename, content, os.ModePerm)
|
||||
}
|
||||
|
||||
// GobEncode Gob encodes file cache item.
|
||||
func GobEncode(data interface{}) ([]byte, error) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
enc := gob.NewEncoder(buf)
|
||||
err := enc.Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// GobDecode Gob decodes file cache item.
|
||||
func GobDecode(data []byte, to *FileCacheItem) error {
|
||||
buf := bytes.NewBuffer(data)
|
||||
dec := gob.NewDecoder(buf)
|
||||
return dec.Decode(&to)
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("file", NewFileCache)
|
||||
}
|
||||
191
vendor/github.com/fatedier/beego/cache/memcache/memcache.go
generated
vendored
Normal file
191
vendor/github.com/fatedier/beego/cache/memcache/memcache.go
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package memcache for cache provider
|
||||
//
|
||||
// depend on github.com/bradfitz/gomemcache/memcache
|
||||
//
|
||||
// go install github.com/bradfitz/gomemcache/memcache
|
||||
//
|
||||
// Usage:
|
||||
// import(
|
||||
// _ "github.com/astaxie/beego/cache/memcache"
|
||||
// "github.com/astaxie/beego/cache"
|
||||
// )
|
||||
//
|
||||
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
|
||||
//
|
||||
// more docs http://beego.me/docs/module/cache.md
|
||||
package memcache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
"github.com/bradfitz/gomemcache/memcache"
|
||||
)
|
||||
|
||||
// Cache Memcache adapter.
|
||||
type Cache struct {
|
||||
conn *memcache.Client
|
||||
conninfo []string
|
||||
}
|
||||
|
||||
// NewMemCache create new memcache adapter.
|
||||
func NewMemCache() cache.Cache {
|
||||
return &Cache{}
|
||||
}
|
||||
|
||||
// Get get value from memcache.
|
||||
func (rc *Cache) Get(key string) interface{} {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if item, err := rc.conn.Get(key); err == nil {
|
||||
return item.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMulti get value from memcache.
|
||||
func (rc *Cache) GetMulti(keys []string) []interface{} {
|
||||
size := len(keys)
|
||||
var rv []interface{}
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
for i := 0; i < size; i++ {
|
||||
rv = append(rv, err)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
}
|
||||
mv, err := rc.conn.GetMulti(keys)
|
||||
if err == nil {
|
||||
for _, v := range mv {
|
||||
rv = append(rv, v.Value)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
rv = append(rv, err)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
// Put put value to memcache.
|
||||
func (rc *Cache) Put(key string, val interface{}, timeout time.Duration) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
item := memcache.Item{Key: key, Expiration: int32(timeout / time.Second)}
|
||||
if v, ok := val.([]byte); ok {
|
||||
item.Value = v
|
||||
} else if str, ok := val.(string); ok {
|
||||
item.Value = []byte(str)
|
||||
} else {
|
||||
return errors.New("val only support string and []byte")
|
||||
}
|
||||
return rc.conn.Set(&item)
|
||||
}
|
||||
|
||||
// Delete delete value in memcache.
|
||||
func (rc *Cache) Delete(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return rc.conn.Delete(key)
|
||||
}
|
||||
|
||||
// Incr increase counter.
|
||||
func (rc *Cache) Incr(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Increment(key, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decr decrease counter.
|
||||
func (rc *Cache) Decr(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Decrement(key, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsExist check value exists in memcache.
|
||||
func (rc *Cache) IsExist(key string) bool {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Get(key)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ClearAll clear all cached in memcache.
|
||||
func (rc *Cache) ClearAll() error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return rc.conn.FlushAll()
|
||||
}
|
||||
|
||||
// StartAndGC start memcache adapter.
|
||||
// config string is like {"conn":"connection info"}.
|
||||
// if connecting error, return.
|
||||
func (rc *Cache) StartAndGC(config string) error {
|
||||
var cf map[string]string
|
||||
json.Unmarshal([]byte(config), &cf)
|
||||
if _, ok := cf["conn"]; !ok {
|
||||
return errors.New("config has no conn key")
|
||||
}
|
||||
rc.conninfo = strings.Split(cf["conn"], ";")
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// connect to memcache and keep the connection.
|
||||
func (rc *Cache) connectInit() error {
|
||||
rc.conn = memcache.New(rc.conninfo...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cache.Register("memcache", NewMemCache)
|
||||
}
|
||||
108
vendor/github.com/fatedier/beego/cache/memcache/memcache_test.go
generated
vendored
Normal file
108
vendor/github.com/fatedier/beego/cache/memcache/memcache_test.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package memcache
|
||||
|
||||
import (
|
||||
_ "github.com/bradfitz/gomemcache/memcache"
|
||||
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
func TestMemcacheCache(t *testing.T) {
|
||||
bm, err := cache.NewCache("memcache", `{"conn": "127.0.0.1:11211"}`)
|
||||
if err != nil {
|
||||
t.Error("init err")
|
||||
}
|
||||
timeoutDuration := 10 * time.Second
|
||||
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
time.Sleep(11 * time.Second)
|
||||
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
|
||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Incr("astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
|
||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 2 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Decr("astaxie"); err != nil {
|
||||
t.Error("Decr Error", err)
|
||||
}
|
||||
|
||||
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
bm.Delete("astaxie")
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
//test string
|
||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
if v := bm.Get("astaxie").([]byte); string(v) != "author" {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
//test GetMulti
|
||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||
if len(vv) != 2 {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if string(vv[0].([]byte)) != "author" && string(vv[0].([]byte)) != "author1" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if string(vv[1].([]byte)) != "author1" && string(vv[1].([]byte)) != "author" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
|
||||
// test clear all
|
||||
if err = bm.ClearAll(); err != nil {
|
||||
t.Error("clear all err")
|
||||
}
|
||||
}
|
||||
244
vendor/github.com/fatedier/beego/cache/memory.go
generated
vendored
Normal file
244
vendor/github.com/fatedier/beego/cache/memory.go
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultEvery means the clock time of recycling the expired cache items in memory.
|
||||
DefaultEvery = 60 // 1 minute
|
||||
)
|
||||
|
||||
// MemoryItem store memory cache item.
|
||||
type MemoryItem struct {
|
||||
val interface{}
|
||||
createdTime time.Time
|
||||
lifespan time.Duration
|
||||
}
|
||||
|
||||
func (mi *MemoryItem) isExpire() bool {
|
||||
// 0 means forever
|
||||
if mi.lifespan == 0 {
|
||||
return false
|
||||
}
|
||||
return time.Now().Sub(mi.createdTime) > mi.lifespan
|
||||
}
|
||||
|
||||
// MemoryCache is Memory cache adapter.
|
||||
// it contains a RW locker for safe map storage.
|
||||
type MemoryCache struct {
|
||||
sync.RWMutex
|
||||
dur time.Duration
|
||||
items map[string]*MemoryItem
|
||||
Every int // run an expiration check Every clock time
|
||||
}
|
||||
|
||||
// NewMemoryCache returns a new MemoryCache.
|
||||
func NewMemoryCache() Cache {
|
||||
cache := MemoryCache{items: make(map[string]*MemoryItem)}
|
||||
return &cache
|
||||
}
|
||||
|
||||
// Get cache from memory.
|
||||
// if non-existed or expired, return nil.
|
||||
func (bc *MemoryCache) Get(name string) interface{} {
|
||||
bc.RLock()
|
||||
defer bc.RUnlock()
|
||||
if itm, ok := bc.items[name]; ok {
|
||||
if itm.isExpire() {
|
||||
return nil
|
||||
}
|
||||
return itm.val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMulti gets caches from memory.
|
||||
// if non-existed or expired, return nil.
|
||||
func (bc *MemoryCache) GetMulti(names []string) []interface{} {
|
||||
var rc []interface{}
|
||||
for _, name := range names {
|
||||
rc = append(rc, bc.Get(name))
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
// Put cache to memory.
|
||||
// if lifespan is 0, it will be forever till restart.
|
||||
func (bc *MemoryCache) Put(name string, value interface{}, lifespan time.Duration) error {
|
||||
bc.Lock()
|
||||
defer bc.Unlock()
|
||||
bc.items[name] = &MemoryItem{
|
||||
val: value,
|
||||
createdTime: time.Now(),
|
||||
lifespan: lifespan,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete cache in memory.
|
||||
func (bc *MemoryCache) Delete(name string) error {
|
||||
bc.Lock()
|
||||
defer bc.Unlock()
|
||||
if _, ok := bc.items[name]; !ok {
|
||||
return errors.New("key not exist")
|
||||
}
|
||||
delete(bc.items, name)
|
||||
if _, ok := bc.items[name]; ok {
|
||||
return errors.New("delete key error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Incr increase cache counter in memory.
|
||||
// it supports int,int32,int64,uint,uint32,uint64.
|
||||
func (bc *MemoryCache) Incr(key string) error {
|
||||
bc.RLock()
|
||||
defer bc.RUnlock()
|
||||
itm, ok := bc.items[key]
|
||||
if !ok {
|
||||
return errors.New("key not exist")
|
||||
}
|
||||
switch itm.val.(type) {
|
||||
case int:
|
||||
itm.val = itm.val.(int) + 1
|
||||
case int32:
|
||||
itm.val = itm.val.(int32) + 1
|
||||
case int64:
|
||||
itm.val = itm.val.(int64) + 1
|
||||
case uint:
|
||||
itm.val = itm.val.(uint) + 1
|
||||
case uint32:
|
||||
itm.val = itm.val.(uint32) + 1
|
||||
case uint64:
|
||||
itm.val = itm.val.(uint64) + 1
|
||||
default:
|
||||
return errors.New("item val is not (u)int (u)int32 (u)int64")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Decr decrease counter in memory.
|
||||
func (bc *MemoryCache) Decr(key string) error {
|
||||
bc.RLock()
|
||||
defer bc.RUnlock()
|
||||
itm, ok := bc.items[key]
|
||||
if !ok {
|
||||
return errors.New("key not exist")
|
||||
}
|
||||
switch itm.val.(type) {
|
||||
case int:
|
||||
itm.val = itm.val.(int) - 1
|
||||
case int64:
|
||||
itm.val = itm.val.(int64) - 1
|
||||
case int32:
|
||||
itm.val = itm.val.(int32) - 1
|
||||
case uint:
|
||||
if itm.val.(uint) > 0 {
|
||||
itm.val = itm.val.(uint) - 1
|
||||
} else {
|
||||
return errors.New("item val is less than 0")
|
||||
}
|
||||
case uint32:
|
||||
if itm.val.(uint32) > 0 {
|
||||
itm.val = itm.val.(uint32) - 1
|
||||
} else {
|
||||
return errors.New("item val is less than 0")
|
||||
}
|
||||
case uint64:
|
||||
if itm.val.(uint64) > 0 {
|
||||
itm.val = itm.val.(uint64) - 1
|
||||
} else {
|
||||
return errors.New("item val is less than 0")
|
||||
}
|
||||
default:
|
||||
return errors.New("item val is not int int64 int32")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsExist check cache exist in memory.
|
||||
func (bc *MemoryCache) IsExist(name string) bool {
|
||||
bc.RLock()
|
||||
defer bc.RUnlock()
|
||||
if v, ok := bc.items[name]; ok {
|
||||
return !v.isExpire()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ClearAll will delete all cache in memory.
|
||||
func (bc *MemoryCache) ClearAll() error {
|
||||
bc.Lock()
|
||||
defer bc.Unlock()
|
||||
bc.items = make(map[string]*MemoryItem)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartAndGC start memory cache. it will check expiration in every clock time.
|
||||
func (bc *MemoryCache) StartAndGC(config string) error {
|
||||
var cf map[string]int
|
||||
json.Unmarshal([]byte(config), &cf)
|
||||
if _, ok := cf["interval"]; !ok {
|
||||
cf = make(map[string]int)
|
||||
cf["interval"] = DefaultEvery
|
||||
}
|
||||
dur := time.Duration(cf["interval"]) * time.Second
|
||||
bc.Every = cf["interval"]
|
||||
bc.dur = dur
|
||||
go bc.vaccuum()
|
||||
return nil
|
||||
}
|
||||
|
||||
// check expiration.
|
||||
func (bc *MemoryCache) vaccuum() {
|
||||
if bc.Every < 1 {
|
||||
return
|
||||
}
|
||||
for {
|
||||
<-time.After(bc.dur)
|
||||
if bc.items == nil {
|
||||
return
|
||||
}
|
||||
for name := range bc.items {
|
||||
bc.itemExpired(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// itemExpired returns true if an item is expired.
|
||||
func (bc *MemoryCache) itemExpired(name string) bool {
|
||||
bc.Lock()
|
||||
defer bc.Unlock()
|
||||
|
||||
itm, ok := bc.items[name]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
if itm.isExpire() {
|
||||
delete(bc.items, name)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("memory", NewMemoryCache)
|
||||
}
|
||||
240
vendor/github.com/fatedier/beego/cache/redis/redis.go
generated
vendored
Normal file
240
vendor/github.com/fatedier/beego/cache/redis/redis.go
generated
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package redis for cache provider
|
||||
//
|
||||
// depend on github.com/garyburd/redigo/redis
|
||||
//
|
||||
// go install github.com/garyburd/redigo/redis
|
||||
//
|
||||
// Usage:
|
||||
// import(
|
||||
// _ "github.com/astaxie/beego/cache/redis"
|
||||
// "github.com/astaxie/beego/cache"
|
||||
// )
|
||||
//
|
||||
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
|
||||
//
|
||||
// more docs http://beego.me/docs/module/cache.md
|
||||
package redis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultKey the collection name of redis for cache adapter.
|
||||
DefaultKey = "beecacheRedis"
|
||||
)
|
||||
|
||||
// Cache is Redis cache adapter.
|
||||
type Cache struct {
|
||||
p *redis.Pool // redis connection pool
|
||||
conninfo string
|
||||
dbNum int
|
||||
key string
|
||||
password string
|
||||
}
|
||||
|
||||
// NewRedisCache create new redis cache with default collection name.
|
||||
func NewRedisCache() cache.Cache {
|
||||
return &Cache{key: DefaultKey}
|
||||
}
|
||||
|
||||
// actually do the redis cmds
|
||||
func (rc *Cache) do(commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||
c := rc.p.Get()
|
||||
defer c.Close()
|
||||
|
||||
return c.Do(commandName, args...)
|
||||
}
|
||||
|
||||
// Get cache from redis.
|
||||
func (rc *Cache) Get(key string) interface{} {
|
||||
if v, err := rc.do("GET", key); err == nil {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMulti get cache from redis.
|
||||
func (rc *Cache) GetMulti(keys []string) []interface{} {
|
||||
size := len(keys)
|
||||
var rv []interface{}
|
||||
c := rc.p.Get()
|
||||
defer c.Close()
|
||||
var err error
|
||||
for _, key := range keys {
|
||||
err = c.Send("GET", key)
|
||||
if err != nil {
|
||||
goto ERROR
|
||||
}
|
||||
}
|
||||
if err = c.Flush(); err != nil {
|
||||
goto ERROR
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
if v, err := c.Receive(); err == nil {
|
||||
rv = append(rv, v.([]byte))
|
||||
} else {
|
||||
rv = append(rv, err)
|
||||
}
|
||||
}
|
||||
return rv
|
||||
ERROR:
|
||||
rv = rv[0:0]
|
||||
for i := 0; i < size; i++ {
|
||||
rv = append(rv, nil)
|
||||
}
|
||||
|
||||
return rv
|
||||
}
|
||||
|
||||
// Put put cache to redis.
|
||||
func (rc *Cache) Put(key string, val interface{}, timeout time.Duration) error {
|
||||
var err error
|
||||
if _, err = rc.do("SETEX", key, int64(timeout/time.Second), val); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = rc.do("HSET", rc.key, key, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete delete cache in redis.
|
||||
func (rc *Cache) Delete(key string) error {
|
||||
var err error
|
||||
if _, err = rc.do("DEL", key); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = rc.do("HDEL", rc.key, key)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsExist check cache's existence in redis.
|
||||
func (rc *Cache) IsExist(key string) bool {
|
||||
v, err := redis.Bool(rc.do("EXISTS", key))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if v == false {
|
||||
if _, err = rc.do("HDEL", rc.key, key); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Incr increase counter in redis.
|
||||
func (rc *Cache) Incr(key string) error {
|
||||
_, err := redis.Bool(rc.do("INCRBY", key, 1))
|
||||
return err
|
||||
}
|
||||
|
||||
// Decr decrease counter in redis.
|
||||
func (rc *Cache) Decr(key string) error {
|
||||
_, err := redis.Bool(rc.do("INCRBY", key, -1))
|
||||
return err
|
||||
}
|
||||
|
||||
// ClearAll clean all cache in redis. delete this redis collection.
|
||||
func (rc *Cache) ClearAll() error {
|
||||
cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, str := range cachedKeys {
|
||||
if _, err = rc.do("DEL", str); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = rc.do("DEL", rc.key)
|
||||
return err
|
||||
}
|
||||
|
||||
// StartAndGC start redis cache adapter.
|
||||
// config is like {"key":"collection key","conn":"connection info","dbNum":"0"}
|
||||
// the cache item in redis are stored forever,
|
||||
// so no gc operation.
|
||||
func (rc *Cache) StartAndGC(config string) error {
|
||||
var cf map[string]string
|
||||
json.Unmarshal([]byte(config), &cf)
|
||||
|
||||
if _, ok := cf["key"]; !ok {
|
||||
cf["key"] = DefaultKey
|
||||
}
|
||||
if _, ok := cf["conn"]; !ok {
|
||||
return errors.New("config has no conn key")
|
||||
}
|
||||
if _, ok := cf["dbNum"]; !ok {
|
||||
cf["dbNum"] = "0"
|
||||
}
|
||||
if _, ok := cf["password"]; !ok {
|
||||
cf["password"] = ""
|
||||
}
|
||||
rc.key = cf["key"]
|
||||
rc.conninfo = cf["conn"]
|
||||
rc.dbNum, _ = strconv.Atoi(cf["dbNum"])
|
||||
rc.password = cf["password"]
|
||||
|
||||
rc.connectInit()
|
||||
|
||||
c := rc.p.Get()
|
||||
defer c.Close()
|
||||
|
||||
return c.Err()
|
||||
}
|
||||
|
||||
// connect to redis.
|
||||
func (rc *Cache) connectInit() {
|
||||
dialFunc := func() (c redis.Conn, err error) {
|
||||
c, err = redis.Dial("tcp", rc.conninfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rc.password != "" {
|
||||
if _, err := c.Do("AUTH", rc.password); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, selecterr := c.Do("SELECT", rc.dbNum)
|
||||
if selecterr != nil {
|
||||
c.Close()
|
||||
return nil, selecterr
|
||||
}
|
||||
return
|
||||
}
|
||||
// initialize a new pool
|
||||
rc.p = &redis.Pool{
|
||||
MaxIdle: 3,
|
||||
IdleTimeout: 180 * time.Second,
|
||||
Dial: dialFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cache.Register("redis", NewRedisCache)
|
||||
}
|
||||
106
vendor/github.com/fatedier/beego/cache/redis/redis_test.go
generated
vendored
Normal file
106
vendor/github.com/fatedier/beego/cache/redis/redis_test.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package redis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
"github.com/garyburd/redigo/redis"
|
||||
)
|
||||
|
||||
func TestRedisCache(t *testing.T) {
|
||||
bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`)
|
||||
if err != nil {
|
||||
t.Error("init err")
|
||||
}
|
||||
timeoutDuration := 10 * time.Second
|
||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
time.Sleep(11 * time.Second)
|
||||
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
|
||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Incr("astaxie"); err != nil {
|
||||
t.Error("Incr Error", err)
|
||||
}
|
||||
|
||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = bm.Decr("astaxie"); err != nil {
|
||||
t.Error("Decr Error", err)
|
||||
}
|
||||
|
||||
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
|
||||
t.Error("get err")
|
||||
}
|
||||
bm.Delete("astaxie")
|
||||
if bm.IsExist("astaxie") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
|
||||
//test string
|
||||
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
//test GetMulti
|
||||
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !bm.IsExist("astaxie1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
|
||||
if len(vv) != 2 {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if v, _ := redis.String(vv[0], nil); v != "author" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
if v, _ := redis.String(vv[1], nil); v != "author1" {
|
||||
t.Error("GetMulti ERROR")
|
||||
}
|
||||
|
||||
// test clear all
|
||||
if err = bm.ClearAll(); err != nil {
|
||||
t.Error("clear all err")
|
||||
}
|
||||
}
|
||||
240
vendor/github.com/fatedier/beego/cache/ssdb/ssdb.go
generated
vendored
Normal file
240
vendor/github.com/fatedier/beego/cache/ssdb/ssdb.go
generated
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
package ssdb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ssdb/gossdb/ssdb"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
// Cache SSDB adapter
|
||||
type Cache struct {
|
||||
conn *ssdb.Client
|
||||
conninfo []string
|
||||
}
|
||||
|
||||
//NewSsdbCache create new ssdb adapter.
|
||||
func NewSsdbCache() cache.Cache {
|
||||
return &Cache{}
|
||||
}
|
||||
|
||||
// Get get value from memcache.
|
||||
func (rc *Cache) Get(key string) interface{} {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
value, err := rc.conn.Get(key)
|
||||
if err == nil {
|
||||
return value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMulti get value from memcache.
|
||||
func (rc *Cache) GetMulti(keys []string) []interface{} {
|
||||
size := len(keys)
|
||||
var values []interface{}
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
for i := 0; i < size; i++ {
|
||||
values = append(values, err)
|
||||
}
|
||||
return values
|
||||
}
|
||||
}
|
||||
res, err := rc.conn.Do("multi_get", keys)
|
||||
resSize := len(res)
|
||||
if err == nil {
|
||||
for i := 1; i < resSize; i += 2 {
|
||||
values = append(values, string(res[i+1]))
|
||||
}
|
||||
return values
|
||||
}
|
||||
for i := 0; i < size; i++ {
|
||||
values = append(values, err)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// DelMulti get value from memcache.
|
||||
func (rc *Cache) DelMulti(keys []string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Do("multi_del", keys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Put put value to memcache. only support string.
|
||||
func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
return errors.New("value must string")
|
||||
}
|
||||
var resp []string
|
||||
var err error
|
||||
ttl := int(timeout / time.Second)
|
||||
if ttl < 0 {
|
||||
resp, err = rc.conn.Do("set", key, v)
|
||||
} else {
|
||||
resp, err = rc.conn.Do("setx", key, v, ttl)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(resp) == 2 && resp[0] == "ok" {
|
||||
return nil
|
||||
}
|
||||
return errors.New("bad response")
|
||||
}
|
||||
|
||||
// Delete delete value in memcache.
|
||||
func (rc *Cache) Delete(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Del(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Incr increase counter.
|
||||
func (rc *Cache) Incr(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Do("incr", key, 1)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decr decrease counter.
|
||||
func (rc *Cache) Decr(key string) error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err := rc.conn.Do("incr", key, -1)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsExist check value exists in memcache.
|
||||
func (rc *Cache) IsExist(key string) bool {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
resp, err := rc.conn.Do("exists", key)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(resp) == 2 && resp[1] == "1" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
// ClearAll clear all cached in memcache.
|
||||
func (rc *Cache) ClearAll() error {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
keyStart, keyEnd, limit := "", "", 50
|
||||
resp, err := rc.Scan(keyStart, keyEnd, limit)
|
||||
for err == nil {
|
||||
size := len(resp)
|
||||
if size == 1 {
|
||||
return nil
|
||||
}
|
||||
keys := []string{}
|
||||
for i := 1; i < size; i += 2 {
|
||||
keys = append(keys, string(resp[i]))
|
||||
}
|
||||
_, e := rc.conn.Do("multi_del", keys)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
keyStart = resp[size-2]
|
||||
resp, err = rc.Scan(keyStart, keyEnd, limit)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Scan key all cached in ssdb.
|
||||
func (rc *Cache) Scan(keyStart string, keyEnd string, limit int) ([]string, error) {
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// StartAndGC start memcache adapter.
|
||||
// config string is like {"conn":"connection info"}.
|
||||
// if connecting error, return.
|
||||
func (rc *Cache) StartAndGC(config string) error {
|
||||
var cf map[string]string
|
||||
json.Unmarshal([]byte(config), &cf)
|
||||
if _, ok := cf["conn"]; !ok {
|
||||
return errors.New("config has no conn key")
|
||||
}
|
||||
rc.conninfo = strings.Split(cf["conn"], ";")
|
||||
if rc.conn == nil {
|
||||
if err := rc.connectInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// connect to memcache and keep the connection.
|
||||
func (rc *Cache) connectInit() error {
|
||||
conninfoArray := strings.Split(rc.conninfo[0], ":")
|
||||
host := conninfoArray[0]
|
||||
port, e := strconv.Atoi(conninfoArray[1])
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
var err error
|
||||
rc.conn, err = ssdb.Connect(host, port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
cache.Register("ssdb", NewSsdbCache)
|
||||
}
|
||||
104
vendor/github.com/fatedier/beego/cache/ssdb/ssdb_test.go
generated
vendored
Normal file
104
vendor/github.com/fatedier/beego/cache/ssdb/ssdb_test.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package ssdb
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/cache"
|
||||
)
|
||||
|
||||
func TestSsdbcacheCache(t *testing.T) {
|
||||
ssdb, err := cache.NewCache("ssdb", `{"conn": "127.0.0.1:8888"}`)
|
||||
if err != nil {
|
||||
t.Error("init err")
|
||||
}
|
||||
|
||||
// test put and exist
|
||||
if ssdb.IsExist("ssdb") {
|
||||
t.Error("check err")
|
||||
}
|
||||
timeoutDuration := 10 * time.Second
|
||||
//timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent
|
||||
if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !ssdb.IsExist("ssdb") {
|
||||
t.Error("check err")
|
||||
}
|
||||
|
||||
// Get test done
|
||||
if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
|
||||
if v := ssdb.Get("ssdb"); v != "ssdb" {
|
||||
t.Error("get Error")
|
||||
}
|
||||
|
||||
//inc/dec test done
|
||||
if err = ssdb.Put("ssdb", "2", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if err = ssdb.Incr("ssdb"); err != nil {
|
||||
t.Error("incr Error", err)
|
||||
}
|
||||
|
||||
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
if err = ssdb.Decr("ssdb"); err != nil {
|
||||
t.Error("decr error")
|
||||
}
|
||||
|
||||
// test del
|
||||
if err = ssdb.Put("ssdb", "3", timeoutDuration); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
|
||||
t.Error("get err")
|
||||
}
|
||||
if err := ssdb.Delete("ssdb"); err == nil {
|
||||
if ssdb.IsExist("ssdb") {
|
||||
t.Error("delete err")
|
||||
}
|
||||
}
|
||||
|
||||
//test string
|
||||
if err = ssdb.Put("ssdb", "ssdb", -10*time.Second); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !ssdb.IsExist("ssdb") {
|
||||
t.Error("check err")
|
||||
}
|
||||
if v := ssdb.Get("ssdb").(string); v != "ssdb" {
|
||||
t.Error("get err")
|
||||
}
|
||||
|
||||
//test GetMulti done
|
||||
if err = ssdb.Put("ssdb1", "ssdb1", -10*time.Second); err != nil {
|
||||
t.Error("set Error", err)
|
||||
}
|
||||
if !ssdb.IsExist("ssdb1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"})
|
||||
if len(vv) != 2 {
|
||||
t.Error("getmulti error")
|
||||
}
|
||||
if vv[0].(string) != "ssdb" {
|
||||
t.Error("getmulti error")
|
||||
}
|
||||
if vv[1].(string) != "ssdb1" {
|
||||
t.Error("getmulti error")
|
||||
}
|
||||
|
||||
// test clear all done
|
||||
if err = ssdb.ClearAll(); err != nil {
|
||||
t.Error("clear all err")
|
||||
}
|
||||
if ssdb.IsExist("ssdb") || ssdb.IsExist("ssdb1") {
|
||||
t.Error("check err")
|
||||
}
|
||||
}
|
||||
489
vendor/github.com/fatedier/beego/config.go
generated
vendored
Normal file
489
vendor/github.com/fatedier/beego/config.go
generated
vendored
Normal file
@@ -0,0 +1,489 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/astaxie/beego/session"
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
// Config is the main struct for BConfig
|
||||
type Config struct {
|
||||
AppName string //Application name
|
||||
RunMode string //Running Mode: dev | prod
|
||||
RouterCaseSensitive bool
|
||||
ServerName string
|
||||
RecoverPanic bool
|
||||
RecoverFunc func(*context.Context)
|
||||
CopyRequestBody bool
|
||||
EnableGzip bool
|
||||
MaxMemory int64
|
||||
EnableErrorsShow bool
|
||||
EnableErrorsRender bool
|
||||
Listen Listen
|
||||
WebConfig WebConfig
|
||||
Log LogConfig
|
||||
}
|
||||
|
||||
// Listen holds for http and https related config
|
||||
type Listen struct {
|
||||
Graceful bool // Graceful means use graceful module to start the server
|
||||
ServerTimeOut int64
|
||||
ListenTCP4 bool
|
||||
EnableHTTP bool
|
||||
HTTPAddr string
|
||||
HTTPPort int
|
||||
EnableHTTPS bool
|
||||
HTTPSAddr string
|
||||
HTTPSPort int
|
||||
HTTPSCertFile string
|
||||
HTTPSKeyFile string
|
||||
EnableAdmin bool
|
||||
AdminAddr string
|
||||
AdminPort int
|
||||
EnableFcgi bool
|
||||
EnableStdIo bool // EnableStdIo works with EnableFcgi Use FCGI via standard I/O
|
||||
}
|
||||
|
||||
// WebConfig holds web related config
|
||||
type WebConfig struct {
|
||||
AutoRender bool
|
||||
EnableDocs bool
|
||||
FlashName string
|
||||
FlashSeparator string
|
||||
DirectoryIndex bool
|
||||
StaticDir map[string]string
|
||||
StaticExtensionsToGzip []string
|
||||
TemplateLeft string
|
||||
TemplateRight string
|
||||
ViewsPath string
|
||||
EnableXSRF bool
|
||||
XSRFKey string
|
||||
XSRFExpire int
|
||||
Session SessionConfig
|
||||
}
|
||||
|
||||
// SessionConfig holds session related config
|
||||
type SessionConfig struct {
|
||||
SessionOn bool
|
||||
SessionProvider string
|
||||
SessionName string
|
||||
SessionGCMaxLifetime int64
|
||||
SessionProviderConfig string
|
||||
SessionCookieLifeTime int
|
||||
SessionAutoSetCookie bool
|
||||
SessionDomain string
|
||||
SessionDisableHTTPOnly bool // used to allow for cross domain cookies/javascript cookies.
|
||||
SessionEnableSidInHTTPHeader bool // enable store/get the sessionId into/from http headers
|
||||
SessionNameInHTTPHeader string
|
||||
SessionEnableSidInURLQuery bool // enable get the sessionId from Url Query params
|
||||
}
|
||||
|
||||
// LogConfig holds Log related config
|
||||
type LogConfig struct {
|
||||
AccessLogs bool
|
||||
FileLineNum bool
|
||||
Outputs map[string]string // Store Adaptor : config
|
||||
}
|
||||
|
||||
var (
|
||||
// BConfig is the default config for Application
|
||||
BConfig *Config
|
||||
// AppConfig is the instance of Config, store the config information from file
|
||||
AppConfig *beegoAppConfig
|
||||
// AppPath is the absolute path to the app
|
||||
AppPath string
|
||||
// GlobalSessions is the instance for the session manager
|
||||
GlobalSessions *session.Manager
|
||||
|
||||
// appConfigPath is the path to the config files
|
||||
appConfigPath string
|
||||
// appConfigProvider is the provider for the config, default is ini
|
||||
appConfigProvider = "ini"
|
||||
)
|
||||
|
||||
func init() {
|
||||
BConfig = newBConfig()
|
||||
var err error
|
||||
if AppPath, err = filepath.Abs(filepath.Dir(os.Args[0])); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
workPath, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
appConfigPath = filepath.Join(workPath, "conf", "app.conf")
|
||||
if !utils.FileExists(appConfigPath) {
|
||||
appConfigPath = filepath.Join(AppPath, "conf", "app.conf")
|
||||
if !utils.FileExists(appConfigPath) {
|
||||
AppConfig = &beegoAppConfig{innerConfig: config.NewFakeConfig()}
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = parseConfig(appConfigPath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func recoverPanic(ctx *context.Context) {
|
||||
if err := recover(); err != nil {
|
||||
if err == ErrAbort {
|
||||
return
|
||||
}
|
||||
if !BConfig.RecoverPanic {
|
||||
panic(err)
|
||||
}
|
||||
if BConfig.EnableErrorsShow {
|
||||
if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
||||
exception(fmt.Sprint(err), ctx)
|
||||
return
|
||||
}
|
||||
}
|
||||
var stack string
|
||||
logs.Critical("the request url is ", ctx.Input.URL())
|
||||
logs.Critical("Handler crashed with error", err)
|
||||
for i := 1; ; i++ {
|
||||
_, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
logs.Critical(fmt.Sprintf("%s:%d", file, line))
|
||||
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
|
||||
}
|
||||
if BConfig.RunMode == DEV && BConfig.EnableErrorsRender {
|
||||
showErr(err, ctx, stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newBConfig() *Config {
|
||||
return &Config{
|
||||
AppName: "beego",
|
||||
RunMode: DEV,
|
||||
RouterCaseSensitive: true,
|
||||
ServerName: "beegoServer:" + VERSION,
|
||||
RecoverPanic: true,
|
||||
RecoverFunc: recoverPanic,
|
||||
CopyRequestBody: false,
|
||||
EnableGzip: false,
|
||||
MaxMemory: 1 << 26, //64MB
|
||||
EnableErrorsShow: true,
|
||||
EnableErrorsRender: true,
|
||||
Listen: Listen{
|
||||
Graceful: false,
|
||||
ServerTimeOut: 0,
|
||||
ListenTCP4: false,
|
||||
EnableHTTP: true,
|
||||
HTTPAddr: "",
|
||||
HTTPPort: 8080,
|
||||
EnableHTTPS: false,
|
||||
HTTPSAddr: "",
|
||||
HTTPSPort: 10443,
|
||||
HTTPSCertFile: "",
|
||||
HTTPSKeyFile: "",
|
||||
EnableAdmin: false,
|
||||
AdminAddr: "",
|
||||
AdminPort: 8088,
|
||||
EnableFcgi: false,
|
||||
EnableStdIo: false,
|
||||
},
|
||||
WebConfig: WebConfig{
|
||||
AutoRender: true,
|
||||
EnableDocs: false,
|
||||
FlashName: "BEEGO_FLASH",
|
||||
FlashSeparator: "BEEGOFLASH",
|
||||
DirectoryIndex: false,
|
||||
StaticDir: map[string]string{"/static": "static"},
|
||||
StaticExtensionsToGzip: []string{".css", ".js"},
|
||||
TemplateLeft: "{{",
|
||||
TemplateRight: "}}",
|
||||
ViewsPath: "views",
|
||||
EnableXSRF: false,
|
||||
XSRFKey: "beegoxsrf",
|
||||
XSRFExpire: 0,
|
||||
Session: SessionConfig{
|
||||
SessionOn: false,
|
||||
SessionProvider: "memory",
|
||||
SessionName: "beegosessionID",
|
||||
SessionGCMaxLifetime: 3600,
|
||||
SessionProviderConfig: "",
|
||||
SessionDisableHTTPOnly: false,
|
||||
SessionCookieLifeTime: 0, //set cookie default is the browser life
|
||||
SessionAutoSetCookie: true,
|
||||
SessionDomain: "",
|
||||
SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
|
||||
SessionNameInHTTPHeader: "Beegosessionid",
|
||||
SessionEnableSidInURLQuery: false, // enable get the sessionId from Url Query params
|
||||
},
|
||||
},
|
||||
Log: LogConfig{
|
||||
AccessLogs: false,
|
||||
FileLineNum: true,
|
||||
Outputs: map[string]string{"console": ""},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// now only support ini, next will support json.
|
||||
func parseConfig(appConfigPath string) (err error) {
|
||||
AppConfig, err = newAppConfig(appConfigProvider, appConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return assignConfig(AppConfig)
|
||||
}
|
||||
|
||||
func assignConfig(ac config.Configer) error {
|
||||
for _, i := range []interface{}{BConfig, &BConfig.Listen, &BConfig.WebConfig, &BConfig.Log, &BConfig.WebConfig.Session} {
|
||||
assignSingleConfig(i, ac)
|
||||
}
|
||||
// set the run mode first
|
||||
if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" {
|
||||
BConfig.RunMode = envRunMode
|
||||
} else if runMode := ac.String("RunMode"); runMode != "" {
|
||||
BConfig.RunMode = runMode
|
||||
}
|
||||
|
||||
if sd := ac.String("StaticDir"); sd != "" {
|
||||
BConfig.WebConfig.StaticDir = map[string]string{}
|
||||
sds := strings.Fields(sd)
|
||||
for _, v := range sds {
|
||||
if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 {
|
||||
BConfig.WebConfig.StaticDir["/"+strings.Trim(url2fsmap[0], "/")] = url2fsmap[1]
|
||||
} else {
|
||||
BConfig.WebConfig.StaticDir["/"+strings.Trim(url2fsmap[0], "/")] = url2fsmap[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sgz := ac.String("StaticExtensionsToGzip"); sgz != "" {
|
||||
extensions := strings.Split(sgz, ",")
|
||||
fileExts := []string{}
|
||||
for _, ext := range extensions {
|
||||
ext = strings.TrimSpace(ext)
|
||||
if ext == "" {
|
||||
continue
|
||||
}
|
||||
if !strings.HasPrefix(ext, ".") {
|
||||
ext = "." + ext
|
||||
}
|
||||
fileExts = append(fileExts, ext)
|
||||
}
|
||||
if len(fileExts) > 0 {
|
||||
BConfig.WebConfig.StaticExtensionsToGzip = fileExts
|
||||
}
|
||||
}
|
||||
|
||||
if lo := ac.String("LogOutputs"); lo != "" {
|
||||
// if lo is not nil or empty
|
||||
// means user has set his own LogOutputs
|
||||
// clear the default setting to BConfig.Log.Outputs
|
||||
BConfig.Log.Outputs = make(map[string]string)
|
||||
los := strings.Split(lo, ";")
|
||||
for _, v := range los {
|
||||
if logType2Config := strings.SplitN(v, ",", 2); len(logType2Config) == 2 {
|
||||
BConfig.Log.Outputs[logType2Config[0]] = logType2Config[1]
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//init log
|
||||
logs.Reset()
|
||||
for adaptor, config := range BConfig.Log.Outputs {
|
||||
err := logs.SetLogger(adaptor, config)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, fmt.Sprintf("%s with the config %q got err:%s", adaptor, config, err.Error()))
|
||||
}
|
||||
}
|
||||
logs.SetLogFuncCall(BConfig.Log.FileLineNum)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func assignSingleConfig(p interface{}, ac config.Configer) {
|
||||
pt := reflect.TypeOf(p)
|
||||
if pt.Kind() != reflect.Ptr {
|
||||
return
|
||||
}
|
||||
pt = pt.Elem()
|
||||
if pt.Kind() != reflect.Struct {
|
||||
return
|
||||
}
|
||||
pv := reflect.ValueOf(p).Elem()
|
||||
|
||||
for i := 0; i < pt.NumField(); i++ {
|
||||
pf := pv.Field(i)
|
||||
if !pf.CanSet() {
|
||||
continue
|
||||
}
|
||||
name := pt.Field(i).Name
|
||||
switch pf.Kind() {
|
||||
case reflect.String:
|
||||
pf.SetString(ac.DefaultString(name, pf.String()))
|
||||
case reflect.Int, reflect.Int64:
|
||||
pf.SetInt(int64(ac.DefaultInt64(name, pf.Int())))
|
||||
case reflect.Bool:
|
||||
pf.SetBool(ac.DefaultBool(name, pf.Bool()))
|
||||
case reflect.Struct:
|
||||
default:
|
||||
//do nothing here
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LoadAppConfig allow developer to apply a config file
|
||||
func LoadAppConfig(adapterName, configPath string) error {
|
||||
absConfigPath, err := filepath.Abs(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !utils.FileExists(absConfigPath) {
|
||||
return fmt.Errorf("the target config file: %s don't exist", configPath)
|
||||
}
|
||||
|
||||
appConfigPath = absConfigPath
|
||||
appConfigProvider = adapterName
|
||||
|
||||
return parseConfig(appConfigPath)
|
||||
}
|
||||
|
||||
type beegoAppConfig struct {
|
||||
innerConfig config.Configer
|
||||
}
|
||||
|
||||
func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) {
|
||||
ac, err := config.NewConfig(appConfigProvider, appConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &beegoAppConfig{ac}, nil
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Set(key, val string) error {
|
||||
if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
return b.innerConfig.Set(key, val)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) String(key string) string {
|
||||
if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" {
|
||||
return v
|
||||
}
|
||||
return b.innerConfig.String(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Strings(key string) []string {
|
||||
if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 {
|
||||
return v
|
||||
}
|
||||
return b.innerConfig.Strings(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Int(key string) (int, error) {
|
||||
if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil {
|
||||
return v, nil
|
||||
}
|
||||
return b.innerConfig.Int(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Int64(key string) (int64, error) {
|
||||
if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil {
|
||||
return v, nil
|
||||
}
|
||||
return b.innerConfig.Int64(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Bool(key string) (bool, error) {
|
||||
if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil {
|
||||
return v, nil
|
||||
}
|
||||
return b.innerConfig.Bool(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) Float(key string) (float64, error) {
|
||||
if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil {
|
||||
return v, nil
|
||||
}
|
||||
return b.innerConfig.Float(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string {
|
||||
if v := b.String(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string {
|
||||
if v := b.Strings(key); len(v) != 0 {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int {
|
||||
if v, err := b.Int(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 {
|
||||
if v, err := b.Int64(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool {
|
||||
if v, err := b.Bool(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 {
|
||||
if v, err := b.Float(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) DIY(key string) (interface{}, error) {
|
||||
return b.innerConfig.DIY(key)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) GetSection(section string) (map[string]string, error) {
|
||||
return b.innerConfig.GetSection(section)
|
||||
}
|
||||
|
||||
func (b *beegoAppConfig) SaveConfigFile(filename string) error {
|
||||
return b.innerConfig.SaveConfigFile(filename)
|
||||
}
|
||||
242
vendor/github.com/fatedier/beego/config/config.go
generated
vendored
Normal file
242
vendor/github.com/fatedier/beego/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package config is used to parse config.
|
||||
// Usage:
|
||||
// import "github.com/astaxie/beego/config"
|
||||
//Examples.
|
||||
//
|
||||
// cnf, err := config.NewConfig("ini", "config.conf")
|
||||
//
|
||||
// cnf APIS:
|
||||
//
|
||||
// cnf.Set(key, val string) error
|
||||
// cnf.String(key string) string
|
||||
// cnf.Strings(key string) []string
|
||||
// cnf.Int(key string) (int, error)
|
||||
// cnf.Int64(key string) (int64, error)
|
||||
// cnf.Bool(key string) (bool, error)
|
||||
// cnf.Float(key string) (float64, error)
|
||||
// cnf.DefaultString(key string, defaultVal string) string
|
||||
// cnf.DefaultStrings(key string, defaultVal []string) []string
|
||||
// cnf.DefaultInt(key string, defaultVal int) int
|
||||
// cnf.DefaultInt64(key string, defaultVal int64) int64
|
||||
// cnf.DefaultBool(key string, defaultVal bool) bool
|
||||
// cnf.DefaultFloat(key string, defaultVal float64) float64
|
||||
// cnf.DIY(key string) (interface{}, error)
|
||||
// cnf.GetSection(section string) (map[string]string, error)
|
||||
// cnf.SaveConfigFile(filename string) error
|
||||
//More docs http://beego.me/docs/module/config.md
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Configer defines how to get and set value from configuration raw data.
|
||||
type Configer interface {
|
||||
Set(key, val string) error //support section::key type in given key when using ini type.
|
||||
String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
|
||||
Strings(key string) []string //get string slice
|
||||
Int(key string) (int, error)
|
||||
Int64(key string) (int64, error)
|
||||
Bool(key string) (bool, error)
|
||||
Float(key string) (float64, error)
|
||||
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.
|
||||
DefaultStrings(key string, defaultVal []string) []string //get string slice
|
||||
DefaultInt(key string, defaultVal int) int
|
||||
DefaultInt64(key string, defaultVal int64) int64
|
||||
DefaultBool(key string, defaultVal bool) bool
|
||||
DefaultFloat(key string, defaultVal float64) float64
|
||||
DIY(key string) (interface{}, error)
|
||||
GetSection(section string) (map[string]string, error)
|
||||
SaveConfigFile(filename string) error
|
||||
}
|
||||
|
||||
// Config is the adapter interface for parsing config file to get raw data to Configer.
|
||||
type Config interface {
|
||||
Parse(key string) (Configer, error)
|
||||
ParseData(data []byte) (Configer, error)
|
||||
}
|
||||
|
||||
var adapters = make(map[string]Config)
|
||||
|
||||
// Register makes a config adapter available by the adapter name.
|
||||
// If Register is called twice with the same name or if driver is nil,
|
||||
// it panics.
|
||||
func Register(name string, adapter Config) {
|
||||
if adapter == nil {
|
||||
panic("config: Register adapter is nil")
|
||||
}
|
||||
if _, ok := adapters[name]; ok {
|
||||
panic("config: Register called twice for adapter " + name)
|
||||
}
|
||||
adapters[name] = adapter
|
||||
}
|
||||
|
||||
// NewConfig adapterName is ini/json/xml/yaml.
|
||||
// filename is the config file path.
|
||||
func NewConfig(adapterName, filename string) (Configer, error) {
|
||||
adapter, ok := adapters[adapterName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
|
||||
}
|
||||
return adapter.Parse(filename)
|
||||
}
|
||||
|
||||
// NewConfigData adapterName is ini/json/xml/yaml.
|
||||
// data is the config data.
|
||||
func NewConfigData(adapterName string, data []byte) (Configer, error) {
|
||||
adapter, ok := adapters[adapterName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
|
||||
}
|
||||
return adapter.ParseData(data)
|
||||
}
|
||||
|
||||
// ExpandValueEnvForMap convert all string value with environment variable.
|
||||
func ExpandValueEnvForMap(m map[string]interface{}) map[string]interface{} {
|
||||
for k, v := range m {
|
||||
switch value := v.(type) {
|
||||
case string:
|
||||
m[k] = ExpandValueEnv(value)
|
||||
case map[string]interface{}:
|
||||
m[k] = ExpandValueEnvForMap(value)
|
||||
case map[string]string:
|
||||
for k2, v2 := range value {
|
||||
value[k2] = ExpandValueEnv(v2)
|
||||
}
|
||||
m[k] = value
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ExpandValueEnv returns value of convert with environment variable.
|
||||
//
|
||||
// Return environment variable if value start with "${" and end with "}".
|
||||
// Return default value if environment variable is empty or not exist.
|
||||
//
|
||||
// It accept value formats "${env}" , "${env||}}" , "${env||defaultValue}" , "defaultvalue".
|
||||
// Examples:
|
||||
// v1 := config.ExpandValueEnv("${GOPATH}") // return the GOPATH environment variable.
|
||||
// v2 := config.ExpandValueEnv("${GOAsta||/usr/local/go}") // return the default value "/usr/local/go/".
|
||||
// v3 := config.ExpandValueEnv("Astaxie") // return the value "Astaxie".
|
||||
func ExpandValueEnv(value string) (realValue string) {
|
||||
realValue = value
|
||||
|
||||
vLen := len(value)
|
||||
// 3 = ${}
|
||||
if vLen < 3 {
|
||||
return
|
||||
}
|
||||
// Need start with "${" and end with "}", then return.
|
||||
if value[0] != '$' || value[1] != '{' || value[vLen-1] != '}' {
|
||||
return
|
||||
}
|
||||
|
||||
key := ""
|
||||
defalutV := ""
|
||||
// value start with "${"
|
||||
for i := 2; i < vLen; i++ {
|
||||
if value[i] == '|' && (i+1 < vLen && value[i+1] == '|') {
|
||||
key = value[2:i]
|
||||
defalutV = value[i+2 : vLen-1] // other string is default value.
|
||||
break
|
||||
} else if value[i] == '}' {
|
||||
key = value[2:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
realValue = os.Getenv(key)
|
||||
if realValue == "" {
|
||||
realValue = defalutV
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ParseBool returns the boolean value represented by the string.
|
||||
//
|
||||
// It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On,
|
||||
// 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off.
|
||||
// Any other value returns an error.
|
||||
func ParseBool(val interface{}) (value bool, err error) {
|
||||
if val != nil {
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
return v, nil
|
||||
case string:
|
||||
switch v {
|
||||
case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
|
||||
return true, nil
|
||||
case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
|
||||
return false, nil
|
||||
}
|
||||
case int8, int32, int64:
|
||||
strV := fmt.Sprintf("%s", v)
|
||||
if strV == "1" {
|
||||
return true, nil
|
||||
} else if strV == "0" {
|
||||
return false, nil
|
||||
}
|
||||
case float64:
|
||||
if v == 1 {
|
||||
return true, nil
|
||||
} else if v == 0 {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return false, fmt.Errorf("parsing %q: invalid syntax", val)
|
||||
}
|
||||
return false, fmt.Errorf("parsing <nil>: invalid syntax")
|
||||
}
|
||||
|
||||
// ToString converts values of any type to string.
|
||||
func ToString(x interface{}) string {
|
||||
switch y := x.(type) {
|
||||
|
||||
// Handle dates with special logic
|
||||
// This needs to come above the fmt.Stringer
|
||||
// test since time.Time's have a .String()
|
||||
// method
|
||||
case time.Time:
|
||||
return y.Format("A Monday")
|
||||
|
||||
// Handle type string
|
||||
case string:
|
||||
return y
|
||||
|
||||
// Handle type with .String() method
|
||||
case fmt.Stringer:
|
||||
return y.String()
|
||||
|
||||
// Handle type with .Error() method
|
||||
case error:
|
||||
return y.Error()
|
||||
|
||||
}
|
||||
|
||||
// Handle named string type
|
||||
if v := reflect.ValueOf(x); v.Kind() == reflect.String {
|
||||
return v.String()
|
||||
}
|
||||
|
||||
// Fallback to fmt package for anything else like numeric types
|
||||
return fmt.Sprint(x)
|
||||
}
|
||||
55
vendor/github.com/fatedier/beego/config/config_test.go
generated
vendored
Normal file
55
vendor/github.com/fatedier/beego/config/config_test.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2016 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExpandValueEnv(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
item string
|
||||
want string
|
||||
}{
|
||||
{"", ""},
|
||||
{"$", "$"},
|
||||
{"{", "{"},
|
||||
{"{}", "{}"},
|
||||
{"${}", ""},
|
||||
{"${|}", ""},
|
||||
{"${}", ""},
|
||||
{"${{}}", ""},
|
||||
{"${{||}}", "}"},
|
||||
{"${pwd||}", ""},
|
||||
{"${pwd||}", ""},
|
||||
{"${pwd||}", ""},
|
||||
{"${pwd||}}", "}"},
|
||||
{"${pwd||{{||}}}", "{{||}}"},
|
||||
{"${GOPATH}", os.Getenv("GOPATH")},
|
||||
{"${GOPATH||}", os.Getenv("GOPATH")},
|
||||
{"${GOPATH||root}", os.Getenv("GOPATH")},
|
||||
{"${GOPATH_NOT||root}", "root"},
|
||||
{"${GOPATH_NOT||||root}", "||root"},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
if got := ExpandValueEnv(c.item); got != c.want {
|
||||
t.Errorf("expand value error, item %q want %q, got %q", c.item, c.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
85
vendor/github.com/fatedier/beego/config/env/env.go
generated
vendored
Normal file
85
vendor/github.com/fatedier/beego/config/env/env.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
// Copyright 2017 Faissal Elamraoui. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
var env *utils.BeeMap
|
||||
|
||||
func init() {
|
||||
env = utils.NewBeeMap()
|
||||
for _, e := range os.Environ() {
|
||||
splits := strings.Split(e, "=")
|
||||
env.Set(splits[0], os.Getenv(splits[0]))
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a value by key.
|
||||
// If the key does not exist, the default value will be returned.
|
||||
func Get(key string, defVal string) string {
|
||||
if val := env.Get(key); val != nil {
|
||||
return val.(string)
|
||||
}
|
||||
return defVal
|
||||
}
|
||||
|
||||
// MustGet returns a value by key.
|
||||
// If the key does not exist, it will return an error.
|
||||
func MustGet(key string) (string, error) {
|
||||
if val := env.Get(key); val != nil {
|
||||
return val.(string), nil
|
||||
}
|
||||
return "", fmt.Errorf("no env variable with %s", key)
|
||||
}
|
||||
|
||||
// Set sets a value in the ENV copy.
|
||||
// This does not affect the child process environment.
|
||||
func Set(key string, value string) {
|
||||
env.Set(key, value)
|
||||
}
|
||||
|
||||
// MustSet sets a value in the ENV copy and the child process environment.
|
||||
// It returns an error in case the set operation failed.
|
||||
func MustSet(key string, value string) error {
|
||||
err := os.Setenv(key, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env.Set(key, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAll returns all keys/values in the current child process environment.
|
||||
func GetAll() map[string]string {
|
||||
items := env.Items()
|
||||
envs := make(map[string]string, env.Count())
|
||||
|
||||
for key, val := range items {
|
||||
switch key := key.(type) {
|
||||
case string:
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
envs[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
return envs
|
||||
}
|
||||
75
vendor/github.com/fatedier/beego/config/env/env_test.go
generated
vendored
Normal file
75
vendor/github.com/fatedier/beego/config/env/env_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
// Copyright 2017 Faissal Elamraoui. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package env
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEnvGet(t *testing.T) {
|
||||
gopath := Get("GOPATH", "")
|
||||
if gopath != os.Getenv("GOPATH") {
|
||||
t.Error("expected GOPATH not empty.")
|
||||
}
|
||||
|
||||
noExistVar := Get("NOEXISTVAR", "foo")
|
||||
if noExistVar != "foo" {
|
||||
t.Errorf("expected NOEXISTVAR to equal foo, got %s.", noExistVar)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvMustGet(t *testing.T) {
|
||||
gopath, err := MustGet("GOPATH")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if gopath != os.Getenv("GOPATH") {
|
||||
t.Errorf("expected GOPATH to be the same, got %s.", gopath)
|
||||
}
|
||||
|
||||
_, err = MustGet("NOEXISTVAR")
|
||||
if err == nil {
|
||||
t.Error("expected error to be non-nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvSet(t *testing.T) {
|
||||
Set("MYVAR", "foo")
|
||||
myVar := Get("MYVAR", "bar")
|
||||
if myVar != "foo" {
|
||||
t.Errorf("expected MYVAR to equal foo, got %s.", myVar)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvMustSet(t *testing.T) {
|
||||
err := MustSet("FOO", "bar")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
fooVar := os.Getenv("FOO")
|
||||
if fooVar != "bar" {
|
||||
t.Errorf("expected FOO variable to equal bar, got %s.", fooVar)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvGetAll(t *testing.T) {
|
||||
envMap := GetAll()
|
||||
if len(envMap) == 0 {
|
||||
t.Error("expected environment not empty.")
|
||||
}
|
||||
}
|
||||
134
vendor/github.com/fatedier/beego/config/fake.go
generated
vendored
Normal file
134
vendor/github.com/fatedier/beego/config/fake.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type fakeConfigContainer struct {
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) getData(key string) string {
|
||||
return c.data[strings.ToLower(key)]
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Set(key, val string) error {
|
||||
c.data[strings.ToLower(key)] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) String(key string) string {
|
||||
return c.getData(key)
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Strings(key string) []string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(v, ";")
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||
v := c.Strings(key)
|
||||
if v == nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Int(key string) (int, error) {
|
||||
return strconv.Atoi(c.getData(key))
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||
v, err := c.Int(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Int64(key string) (int64, error) {
|
||||
return strconv.ParseInt(c.getData(key), 10, 64)
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||
v, err := c.Int64(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Bool(key string) (bool, error) {
|
||||
return ParseBool(c.getData(key))
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||
v, err := c.Bool(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) Float(key string) (float64, error) {
|
||||
return strconv.ParseFloat(c.getData(key), 64)
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||
v, err := c.Float(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
|
||||
if v, ok := c.data[strings.ToLower(key)]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("key not find")
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||
return nil, errors.New("not implement in the fakeConfigContainer")
|
||||
}
|
||||
|
||||
func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
|
||||
return errors.New("not implement in the fakeConfigContainer")
|
||||
}
|
||||
|
||||
var _ Configer = new(fakeConfigContainer)
|
||||
|
||||
// NewFakeConfig return a fake Congiger
|
||||
func NewFakeConfig() Configer {
|
||||
return &fakeConfigContainer{
|
||||
data: make(map[string]string),
|
||||
}
|
||||
}
|
||||
474
vendor/github.com/fatedier/beego/config/ini.go
generated
vendored
Normal file
474
vendor/github.com/fatedier/beego/config/ini.go
generated
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultSection = "default" // default section means if some ini items not in a section, make them in default section,
|
||||
bNumComment = []byte{'#'} // number signal
|
||||
bSemComment = []byte{';'} // semicolon signal
|
||||
bEmpty = []byte{}
|
||||
bEqual = []byte{'='} // equal signal
|
||||
bDQuote = []byte{'"'} // quote signal
|
||||
sectionStart = []byte{'['} // section start signal
|
||||
sectionEnd = []byte{']'} // section end signal
|
||||
lineBreak = "\n"
|
||||
)
|
||||
|
||||
// IniConfig implements Config to parse ini file.
|
||||
type IniConfig struct {
|
||||
}
|
||||
|
||||
// Parse creates a new Config and parses the file configuration from the named file.
|
||||
func (ini *IniConfig) Parse(name string) (Configer, error) {
|
||||
return ini.parseFile(name)
|
||||
}
|
||||
|
||||
func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
|
||||
data, err := ioutil.ReadFile(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ini.parseData(filepath.Dir(name), data)
|
||||
}
|
||||
|
||||
func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, error) {
|
||||
cfg := &IniConfigContainer{
|
||||
data: make(map[string]map[string]string),
|
||||
sectionComment: make(map[string]string),
|
||||
keyComment: make(map[string]string),
|
||||
RWMutex: sync.RWMutex{},
|
||||
}
|
||||
cfg.Lock()
|
||||
defer cfg.Unlock()
|
||||
|
||||
var comment bytes.Buffer
|
||||
buf := bufio.NewReader(bytes.NewBuffer(data))
|
||||
// check the BOM
|
||||
head, err := buf.Peek(3)
|
||||
if err == nil && head[0] == 239 && head[1] == 187 && head[2] == 191 {
|
||||
for i := 1; i <= 3; i++ {
|
||||
buf.ReadByte()
|
||||
}
|
||||
}
|
||||
section := defaultSection
|
||||
for {
|
||||
line, _, err := buf.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
//It might be a good idea to throw a error on all unknonw errors?
|
||||
if _, ok := err.(*os.PathError); ok {
|
||||
return nil, err
|
||||
}
|
||||
line = bytes.TrimSpace(line)
|
||||
if bytes.Equal(line, bEmpty) {
|
||||
continue
|
||||
}
|
||||
var bComment []byte
|
||||
switch {
|
||||
case bytes.HasPrefix(line, bNumComment):
|
||||
bComment = bNumComment
|
||||
case bytes.HasPrefix(line, bSemComment):
|
||||
bComment = bSemComment
|
||||
}
|
||||
if bComment != nil {
|
||||
line = bytes.TrimLeft(line, string(bComment))
|
||||
// Need append to a new line if multi-line comments.
|
||||
if comment.Len() > 0 {
|
||||
comment.WriteByte('\n')
|
||||
}
|
||||
comment.Write(line)
|
||||
continue
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) {
|
||||
section = strings.ToLower(string(line[1 : len(line)-1])) // section name case insensitive
|
||||
if comment.Len() > 0 {
|
||||
cfg.sectionComment[section] = comment.String()
|
||||
comment.Reset()
|
||||
}
|
||||
if _, ok := cfg.data[section]; !ok {
|
||||
cfg.data[section] = make(map[string]string)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := cfg.data[section]; !ok {
|
||||
cfg.data[section] = make(map[string]string)
|
||||
}
|
||||
keyValue := bytes.SplitN(line, bEqual, 2)
|
||||
|
||||
key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive
|
||||
key = strings.ToLower(key)
|
||||
|
||||
// handle include "other.conf"
|
||||
if len(keyValue) == 1 && strings.HasPrefix(key, "include") {
|
||||
|
||||
includefiles := strings.Fields(key)
|
||||
if includefiles[0] == "include" && len(includefiles) == 2 {
|
||||
|
||||
otherfile := strings.Trim(includefiles[1], "\"")
|
||||
if !filepath.IsAbs(otherfile) {
|
||||
otherfile = filepath.Join(dir, otherfile)
|
||||
}
|
||||
|
||||
i, err := ini.parseFile(otherfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for sec, dt := range i.data {
|
||||
if _, ok := cfg.data[sec]; !ok {
|
||||
cfg.data[sec] = make(map[string]string)
|
||||
}
|
||||
for k, v := range dt {
|
||||
cfg.data[sec][k] = v
|
||||
}
|
||||
}
|
||||
|
||||
for sec, comm := range i.sectionComment {
|
||||
cfg.sectionComment[sec] = comm
|
||||
}
|
||||
|
||||
for k, comm := range i.keyComment {
|
||||
cfg.keyComment[k] = comm
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(keyValue) != 2 {
|
||||
return nil, errors.New("read the content error: \"" + string(line) + "\", should key = val")
|
||||
}
|
||||
val := bytes.TrimSpace(keyValue[1])
|
||||
if bytes.HasPrefix(val, bDQuote) {
|
||||
val = bytes.Trim(val, `"`)
|
||||
}
|
||||
|
||||
cfg.data[section][key] = ExpandValueEnv(string(val))
|
||||
if comment.Len() > 0 {
|
||||
cfg.keyComment[section+"."+key] = comment.String()
|
||||
comment.Reset()
|
||||
}
|
||||
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// ParseData parse ini the data
|
||||
// When include other.conf,other.conf is either absolute directory
|
||||
// or under beego in default temporary directory(/tmp/beego).
|
||||
func (ini *IniConfig) ParseData(data []byte) (Configer, error) {
|
||||
dir := filepath.Join(os.TempDir(), "beego")
|
||||
os.MkdirAll(dir, os.ModePerm)
|
||||
|
||||
return ini.parseData(dir, data)
|
||||
}
|
||||
|
||||
// IniConfigContainer A Config represents the ini configuration.
|
||||
// When set and get value, support key as section:name type.
|
||||
type IniConfigContainer struct {
|
||||
data map[string]map[string]string // section=> key:val
|
||||
sectionComment map[string]string // section : comment
|
||||
keyComment map[string]string // id: []{comment, key...}; id 1 is for main comment.
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// Bool returns the boolean value for a given key.
|
||||
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
||||
return ParseBool(c.getdata(key))
|
||||
}
|
||||
|
||||
// DefaultBool returns the boolean value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||
v, err := c.Bool(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns the integer value for a given key.
|
||||
func (c *IniConfigContainer) Int(key string) (int, error) {
|
||||
return strconv.Atoi(c.getdata(key))
|
||||
}
|
||||
|
||||
// DefaultInt returns the integer value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||
v, err := c.Int(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value for a given key.
|
||||
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
||||
return strconv.ParseInt(c.getdata(key), 10, 64)
|
||||
}
|
||||
|
||||
// DefaultInt64 returns the int64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||
v, err := c.Int64(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float returns the float value for a given key.
|
||||
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
||||
return strconv.ParseFloat(c.getdata(key), 64)
|
||||
}
|
||||
|
||||
// DefaultFloat returns the float64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||
v, err := c.Float(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns the string value for a given key.
|
||||
func (c *IniConfigContainer) String(key string) string {
|
||||
return c.getdata(key)
|
||||
}
|
||||
|
||||
// DefaultString returns the string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultString(key string, defaultval string) string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Strings returns the []string value for a given key.
|
||||
// Return nil if config value does not exist or is empty.
|
||||
func (c *IniConfigContainer) Strings(key string) []string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(v, ";")
|
||||
}
|
||||
|
||||
// DefaultStrings returns the []string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *IniConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||
v := c.Strings(key)
|
||||
if v == nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSection returns map for the given section
|
||||
func (c *IniConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||
if v, ok := c.data[section]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("not exist section")
|
||||
}
|
||||
|
||||
// SaveConfigFile save the config into file.
|
||||
//
|
||||
// BUG(env): The environment variable config item will be saved with real value in SaveConfigFile Funcation.
|
||||
func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
|
||||
// Write configuration file by filename.
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Get section or key comments. Fixed #1607
|
||||
getCommentStr := func(section, key string) string {
|
||||
comment, ok := "", false
|
||||
if len(key) == 0 {
|
||||
comment, ok = c.sectionComment[section]
|
||||
} else {
|
||||
comment, ok = c.keyComment[section+"."+key]
|
||||
}
|
||||
|
||||
if ok {
|
||||
// Empty comment
|
||||
if len(comment) == 0 || len(strings.TrimSpace(comment)) == 0 {
|
||||
return string(bNumComment)
|
||||
}
|
||||
prefix := string(bNumComment)
|
||||
// Add the line head character "#"
|
||||
return prefix + strings.Replace(comment, lineBreak, lineBreak+prefix, -1)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
// Save default section at first place
|
||||
if dt, ok := c.data[defaultSection]; ok {
|
||||
for key, val := range dt {
|
||||
if key != " " {
|
||||
// Write key comments.
|
||||
if v := getCommentStr(defaultSection, key); len(v) > 0 {
|
||||
if _, err = buf.WriteString(v + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Write key and value.
|
||||
if _, err = buf.WriteString(key + string(bEqual) + val + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put a line between sections.
|
||||
if _, err = buf.WriteString(lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Save named sections
|
||||
for section, dt := range c.data {
|
||||
if section != defaultSection {
|
||||
// Write section comments.
|
||||
if v := getCommentStr(section, ""); len(v) > 0 {
|
||||
if _, err = buf.WriteString(v + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Write section name.
|
||||
if _, err = buf.WriteString(string(sectionStart) + section + string(sectionEnd) + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, val := range dt {
|
||||
if key != " " {
|
||||
// Write key comments.
|
||||
if v := getCommentStr(section, key); len(v) > 0 {
|
||||
if _, err = buf.WriteString(v + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Write key and value.
|
||||
if _, err = buf.WriteString(key + string(bEqual) + val + lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put a line between sections.
|
||||
if _, err = buf.WriteString(lineBreak); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = buf.WriteTo(f); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set writes a new value for key.
|
||||
// if write to one section, the key need be "section::key".
|
||||
// if the section is not existed, it panics.
|
||||
func (c *IniConfigContainer) Set(key, value string) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
if len(key) == 0 {
|
||||
return errors.New("key is empty")
|
||||
}
|
||||
|
||||
var (
|
||||
section, k string
|
||||
sectionKey = strings.Split(key, "::")
|
||||
)
|
||||
|
||||
if len(sectionKey) >= 2 {
|
||||
section = sectionKey[0]
|
||||
k = sectionKey[1]
|
||||
} else {
|
||||
section = defaultSection
|
||||
k = sectionKey[0]
|
||||
}
|
||||
|
||||
if _, ok := c.data[section]; !ok {
|
||||
c.data[section] = make(map[string]string)
|
||||
}
|
||||
c.data[section][k] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// DIY returns the raw value by a given key.
|
||||
func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||
if v, ok := c.data[strings.ToLower(key)]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return v, errors.New("key not find")
|
||||
}
|
||||
|
||||
// section.key or key
|
||||
func (c *IniConfigContainer) getdata(key string) string {
|
||||
if len(key) == 0 {
|
||||
return ""
|
||||
}
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
var (
|
||||
section, k string
|
||||
sectionKey = strings.Split(strings.ToLower(key), "::")
|
||||
)
|
||||
if len(sectionKey) >= 2 {
|
||||
section = sectionKey[0]
|
||||
k = sectionKey[1]
|
||||
} else {
|
||||
section = defaultSection
|
||||
k = sectionKey[0]
|
||||
}
|
||||
if v, ok := c.data[section]; ok {
|
||||
if vv, ok := v[k]; ok {
|
||||
return vv
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("ini", &IniConfig{})
|
||||
}
|
||||
190
vendor/github.com/fatedier/beego/config/ini_test.go
generated
vendored
Normal file
190
vendor/github.com/fatedier/beego/config/ini_test.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIni(t *testing.T) {
|
||||
|
||||
var (
|
||||
inicontext = `
|
||||
;comment one
|
||||
#comment two
|
||||
appname = beeapi
|
||||
httpport = 8080
|
||||
mysqlport = 3600
|
||||
PI = 3.1415976
|
||||
runmode = "dev"
|
||||
autorender = false
|
||||
copyrequestbody = true
|
||||
session= on
|
||||
cookieon= off
|
||||
newreg = OFF
|
||||
needlogin = ON
|
||||
enableSession = Y
|
||||
enableCookie = N
|
||||
flag = 1
|
||||
path1 = ${GOPATH}
|
||||
path2 = ${GOPATH||/home/go}
|
||||
[demo]
|
||||
key1="asta"
|
||||
key2 = "xie"
|
||||
CaseInsensitive = true
|
||||
peers = one;two;three
|
||||
password = ${GOPATH}
|
||||
`
|
||||
|
||||
keyValue = map[string]interface{}{
|
||||
"appname": "beeapi",
|
||||
"httpport": 8080,
|
||||
"mysqlport": int64(3600),
|
||||
"pi": 3.1415976,
|
||||
"runmode": "dev",
|
||||
"autorender": false,
|
||||
"copyrequestbody": true,
|
||||
"session": true,
|
||||
"cookieon": false,
|
||||
"newreg": false,
|
||||
"needlogin": true,
|
||||
"enableSession": true,
|
||||
"enableCookie": false,
|
||||
"flag": true,
|
||||
"path1": os.Getenv("GOPATH"),
|
||||
"path2": os.Getenv("GOPATH"),
|
||||
"demo::key1": "asta",
|
||||
"demo::key2": "xie",
|
||||
"demo::CaseInsensitive": true,
|
||||
"demo::peers": []string{"one", "two", "three"},
|
||||
"demo::password": os.Getenv("GOPATH"),
|
||||
"null": "",
|
||||
"demo2::key1": "",
|
||||
"error": "",
|
||||
"emptystrings": []string{},
|
||||
}
|
||||
)
|
||||
|
||||
f, err := os.Create("testini.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(inicontext)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
defer os.Remove("testini.conf")
|
||||
iniconf, err := NewConfig("ini", "testini.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for k, v := range keyValue {
|
||||
var err error
|
||||
var value interface{}
|
||||
switch v.(type) {
|
||||
case int:
|
||||
value, err = iniconf.Int(k)
|
||||
case int64:
|
||||
value, err = iniconf.Int64(k)
|
||||
case float64:
|
||||
value, err = iniconf.Float(k)
|
||||
case bool:
|
||||
value, err = iniconf.Bool(k)
|
||||
case []string:
|
||||
value = iniconf.Strings(k)
|
||||
case string:
|
||||
value = iniconf.String(k)
|
||||
default:
|
||||
value, err = iniconf.DIY(k)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("get key %q value fail,err %s", k, err)
|
||||
} else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
|
||||
t.Fatalf("get key %q value, want %v got %v .", k, v, value)
|
||||
}
|
||||
|
||||
}
|
||||
if err = iniconf.Set("name", "astaxie"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if iniconf.String("name") != "astaxie" {
|
||||
t.Fatal("get name error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIniSave(t *testing.T) {
|
||||
|
||||
const (
|
||||
inicontext = `
|
||||
app = app
|
||||
;comment one
|
||||
#comment two
|
||||
# comment three
|
||||
appname = beeapi
|
||||
httpport = 8080
|
||||
# DB Info
|
||||
# enable db
|
||||
[dbinfo]
|
||||
# db type name
|
||||
# suport mysql,sqlserver
|
||||
name = mysql
|
||||
`
|
||||
|
||||
saveResult = `
|
||||
app=app
|
||||
#comment one
|
||||
#comment two
|
||||
# comment three
|
||||
appname=beeapi
|
||||
httpport=8080
|
||||
|
||||
# DB Info
|
||||
# enable db
|
||||
[dbinfo]
|
||||
# db type name
|
||||
# suport mysql,sqlserver
|
||||
name=mysql
|
||||
`
|
||||
)
|
||||
cfg, err := NewConfigData("ini", []byte(inicontext))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
name := "newIniConfig.ini"
|
||||
if err := cfg.SaveConfigFile(name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(name)
|
||||
|
||||
if data, err := ioutil.ReadFile(name); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
cfgData := string(data)
|
||||
datas := strings.Split(saveResult, "\n")
|
||||
for _, line := range datas {
|
||||
if strings.Contains(cfgData, line+"\n") == false {
|
||||
t.Fatalf("different after save ini config file. need contains %q", line)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
266
vendor/github.com/fatedier/beego/config/json.go
generated
vendored
Normal file
266
vendor/github.com/fatedier/beego/config/json.go
generated
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// JSONConfig is a json config parser and implements Config interface.
|
||||
type JSONConfig struct {
|
||||
}
|
||||
|
||||
// Parse returns a ConfigContainer with parsed json config map.
|
||||
func (js *JSONConfig) Parse(filename string) (Configer, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return js.ParseData(content)
|
||||
}
|
||||
|
||||
// ParseData returns a ConfigContainer with json string
|
||||
func (js *JSONConfig) ParseData(data []byte) (Configer, error) {
|
||||
x := &JSONConfigContainer{
|
||||
data: make(map[string]interface{}),
|
||||
}
|
||||
err := json.Unmarshal(data, &x.data)
|
||||
if err != nil {
|
||||
var wrappingArray []interface{}
|
||||
err2 := json.Unmarshal(data, &wrappingArray)
|
||||
if err2 != nil {
|
||||
return nil, err
|
||||
}
|
||||
x.data["rootArray"] = wrappingArray
|
||||
}
|
||||
|
||||
x.data = ExpandValueEnvForMap(x.data)
|
||||
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// JSONConfigContainer A Config represents the json configuration.
|
||||
// Only when get value, support key as section:name type.
|
||||
type JSONConfigContainer struct {
|
||||
data map[string]interface{}
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// Bool returns the boolean value for a given key.
|
||||
func (c *JSONConfigContainer) Bool(key string) (bool, error) {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
return ParseBool(val)
|
||||
}
|
||||
return false, fmt.Errorf("not exist key: %q", key)
|
||||
}
|
||||
|
||||
// DefaultBool return the bool value if has no error
|
||||
// otherwise return the defaultval
|
||||
func (c *JSONConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||
if v, err := c.Bool(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// Int returns the integer value for a given key.
|
||||
func (c *JSONConfigContainer) Int(key string) (int, error) {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
if v, ok := val.(float64); ok {
|
||||
return int(v), nil
|
||||
}
|
||||
return 0, errors.New("not int value")
|
||||
}
|
||||
return 0, errors.New("not exist key:" + key)
|
||||
}
|
||||
|
||||
// DefaultInt returns the integer value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *JSONConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||
if v, err := c.Int(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value for a given key.
|
||||
func (c *JSONConfigContainer) Int64(key string) (int64, error) {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
if v, ok := val.(float64); ok {
|
||||
return int64(v), nil
|
||||
}
|
||||
return 0, errors.New("not int64 value")
|
||||
}
|
||||
return 0, errors.New("not exist key:" + key)
|
||||
}
|
||||
|
||||
// DefaultInt64 returns the int64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *JSONConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||
if v, err := c.Int64(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// Float returns the float value for a given key.
|
||||
func (c *JSONConfigContainer) Float(key string) (float64, error) {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
if v, ok := val.(float64); ok {
|
||||
return v, nil
|
||||
}
|
||||
return 0.0, errors.New("not float64 value")
|
||||
}
|
||||
return 0.0, errors.New("not exist key:" + key)
|
||||
}
|
||||
|
||||
// DefaultFloat returns the float64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *JSONConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||
if v, err := c.Float(key); err == nil {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// String returns the string value for a given key.
|
||||
func (c *JSONConfigContainer) String(key string) string {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
if v, ok := val.(string); ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DefaultString returns the string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *JSONConfigContainer) DefaultString(key string, defaultval string) string {
|
||||
// TODO FIXME should not use "" to replace non existence
|
||||
if v := c.String(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// Strings returns the []string value for a given key.
|
||||
func (c *JSONConfigContainer) Strings(key string) []string {
|
||||
stringVal := c.String(key)
|
||||
if stringVal == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(c.String(key), ";")
|
||||
}
|
||||
|
||||
// DefaultStrings returns the []string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *JSONConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||
if v := c.Strings(key); v != nil {
|
||||
return v
|
||||
}
|
||||
return defaultval
|
||||
}
|
||||
|
||||
// GetSection returns map for the given section
|
||||
func (c *JSONConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||
if v, ok := c.data[section]; ok {
|
||||
return v.(map[string]string), nil
|
||||
}
|
||||
return nil, errors.New("nonexist section " + section)
|
||||
}
|
||||
|
||||
// SaveConfigFile save the config into file
|
||||
func (c *JSONConfigContainer) SaveConfigFile(filename string) (err error) {
|
||||
// Write configuration file by filename.
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
b, err := json.MarshalIndent(c.data, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set writes a new value for key.
|
||||
func (c *JSONConfigContainer) Set(key, val string) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// DIY returns the raw value by a given key.
|
||||
func (c *JSONConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||
val := c.getData(key)
|
||||
if val != nil {
|
||||
return val, nil
|
||||
}
|
||||
return nil, errors.New("not exist key")
|
||||
}
|
||||
|
||||
// section.key or key
|
||||
func (c *JSONConfigContainer) getData(key string) interface{} {
|
||||
if len(key) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
|
||||
sectionKeys := strings.Split(key, "::")
|
||||
if len(sectionKeys) >= 2 {
|
||||
curValue, ok := c.data[sectionKeys[0]]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
for _, key := range sectionKeys[1:] {
|
||||
if v, ok := curValue.(map[string]interface{}); ok {
|
||||
if curValue, ok = v[key]; !ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return curValue
|
||||
}
|
||||
if v, ok := c.data[key]; ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register("json", &JSONConfig{})
|
||||
}
|
||||
222
vendor/github.com/fatedier/beego/config/json_test.go
generated
vendored
Normal file
222
vendor/github.com/fatedier/beego/config/json_test.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJsonStartsWithArray(t *testing.T) {
|
||||
|
||||
const jsoncontextwitharray = `[
|
||||
{
|
||||
"url": "user",
|
||||
"serviceAPI": "http://www.test.com/user"
|
||||
},
|
||||
{
|
||||
"url": "employee",
|
||||
"serviceAPI": "http://www.test.com/employee"
|
||||
}
|
||||
]`
|
||||
f, err := os.Create("testjsonWithArray.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(jsoncontextwitharray)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
defer os.Remove("testjsonWithArray.conf")
|
||||
jsonconf, err := NewConfig("json", "testjsonWithArray.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rootArray, err := jsonconf.DIY("rootArray")
|
||||
if err != nil {
|
||||
t.Error("array does not exist as element")
|
||||
}
|
||||
rootArrayCasted := rootArray.([]interface{})
|
||||
if rootArrayCasted == nil {
|
||||
t.Error("array from root is nil")
|
||||
} else {
|
||||
elem := rootArrayCasted[0].(map[string]interface{})
|
||||
if elem["url"] != "user" || elem["serviceAPI"] != "http://www.test.com/user" {
|
||||
t.Error("array[0] values are not valid")
|
||||
}
|
||||
|
||||
elem2 := rootArrayCasted[1].(map[string]interface{})
|
||||
if elem2["url"] != "employee" || elem2["serviceAPI"] != "http://www.test.com/employee" {
|
||||
t.Error("array[1] values are not valid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJson(t *testing.T) {
|
||||
|
||||
var (
|
||||
jsoncontext = `{
|
||||
"appname": "beeapi",
|
||||
"testnames": "foo;bar",
|
||||
"httpport": 8080,
|
||||
"mysqlport": 3600,
|
||||
"PI": 3.1415976,
|
||||
"runmode": "dev",
|
||||
"autorender": false,
|
||||
"copyrequestbody": true,
|
||||
"session": "on",
|
||||
"cookieon": "off",
|
||||
"newreg": "OFF",
|
||||
"needlogin": "ON",
|
||||
"enableSession": "Y",
|
||||
"enableCookie": "N",
|
||||
"flag": 1,
|
||||
"path1": "${GOPATH}",
|
||||
"path2": "${GOPATH||/home/go}",
|
||||
"database": {
|
||||
"host": "host",
|
||||
"port": "port",
|
||||
"database": "database",
|
||||
"username": "username",
|
||||
"password": "${GOPATH}",
|
||||
"conns":{
|
||||
"maxconnection":12,
|
||||
"autoconnect":true,
|
||||
"connectioninfo":"info",
|
||||
"root": "${GOPATH}"
|
||||
}
|
||||
}
|
||||
}`
|
||||
keyValue = map[string]interface{}{
|
||||
"appname": "beeapi",
|
||||
"testnames": []string{"foo", "bar"},
|
||||
"httpport": 8080,
|
||||
"mysqlport": int64(3600),
|
||||
"PI": 3.1415976,
|
||||
"runmode": "dev",
|
||||
"autorender": false,
|
||||
"copyrequestbody": true,
|
||||
"session": true,
|
||||
"cookieon": false,
|
||||
"newreg": false,
|
||||
"needlogin": true,
|
||||
"enableSession": true,
|
||||
"enableCookie": false,
|
||||
"flag": true,
|
||||
"path1": os.Getenv("GOPATH"),
|
||||
"path2": os.Getenv("GOPATH"),
|
||||
"database::host": "host",
|
||||
"database::port": "port",
|
||||
"database::database": "database",
|
||||
"database::password": os.Getenv("GOPATH"),
|
||||
"database::conns::maxconnection": 12,
|
||||
"database::conns::autoconnect": true,
|
||||
"database::conns::connectioninfo": "info",
|
||||
"database::conns::root": os.Getenv("GOPATH"),
|
||||
"unknown": "",
|
||||
}
|
||||
)
|
||||
|
||||
f, err := os.Create("testjson.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(jsoncontext)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
defer os.Remove("testjson.conf")
|
||||
jsonconf, err := NewConfig("json", "testjson.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for k, v := range keyValue {
|
||||
var err error
|
||||
var value interface{}
|
||||
switch v.(type) {
|
||||
case int:
|
||||
value, err = jsonconf.Int(k)
|
||||
case int64:
|
||||
value, err = jsonconf.Int64(k)
|
||||
case float64:
|
||||
value, err = jsonconf.Float(k)
|
||||
case bool:
|
||||
value, err = jsonconf.Bool(k)
|
||||
case []string:
|
||||
value = jsonconf.Strings(k)
|
||||
case string:
|
||||
value = jsonconf.String(k)
|
||||
default:
|
||||
value, err = jsonconf.DIY(k)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("get key %q value fatal,%v err %s", k, v, err)
|
||||
} else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
|
||||
t.Fatalf("get key %q value, want %v got %v .", k, v, value)
|
||||
}
|
||||
|
||||
}
|
||||
if err = jsonconf.Set("name", "astaxie"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if jsonconf.String("name") != "astaxie" {
|
||||
t.Fatal("get name error")
|
||||
}
|
||||
|
||||
if db, err := jsonconf.DIY("database"); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if m, ok := db.(map[string]interface{}); !ok {
|
||||
t.Log(db)
|
||||
t.Fatal("db not map[string]interface{}")
|
||||
} else {
|
||||
if m["host"].(string) != "host" {
|
||||
t.Fatal("get host err")
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := jsonconf.Int("unknown"); err == nil {
|
||||
t.Error("unknown keys should return an error when expecting an Int")
|
||||
}
|
||||
|
||||
if _, err := jsonconf.Int64("unknown"); err == nil {
|
||||
t.Error("unknown keys should return an error when expecting an Int64")
|
||||
}
|
||||
|
||||
if _, err := jsonconf.Float("unknown"); err == nil {
|
||||
t.Error("unknown keys should return an error when expecting a Float")
|
||||
}
|
||||
|
||||
if _, err := jsonconf.DIY("unknown"); err == nil {
|
||||
t.Error("unknown keys should return an error when expecting an interface{}")
|
||||
}
|
||||
|
||||
if val := jsonconf.String("unknown"); val != "" {
|
||||
t.Error("unknown keys should return an empty string when expecting a String")
|
||||
}
|
||||
|
||||
if _, err := jsonconf.Bool("unknown"); err == nil {
|
||||
t.Error("unknown keys should return an error when expecting a Bool")
|
||||
}
|
||||
|
||||
if !jsonconf.DefaultBool("unknow", true) {
|
||||
t.Error("unknown keys with default value wrong")
|
||||
}
|
||||
}
|
||||
228
vendor/github.com/fatedier/beego/config/xml/xml.go
generated
vendored
Normal file
228
vendor/github.com/fatedier/beego/config/xml/xml.go
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package xml for config provider.
|
||||
//
|
||||
// depend on github.com/beego/x2j.
|
||||
//
|
||||
// go install github.com/beego/x2j.
|
||||
//
|
||||
// Usage:
|
||||
// import(
|
||||
// _ "github.com/astaxie/beego/config/xml"
|
||||
// "github.com/astaxie/beego/config"
|
||||
// )
|
||||
//
|
||||
// cnf, err := config.NewConfig("xml", "config.xml")
|
||||
//
|
||||
//More docs http://beego.me/docs/module/config.md
|
||||
package xml
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
"github.com/beego/x2j"
|
||||
)
|
||||
|
||||
// Config is a xml config parser and implements Config interface.
|
||||
// xml configurations should be included in <config></config> tag.
|
||||
// only support key/value pair as <key>value</key> as each item.
|
||||
type Config struct{}
|
||||
|
||||
// Parse returns a ConfigContainer with parsed xml config map.
|
||||
func (xc *Config) Parse(filename string) (config.Configer, error) {
|
||||
context, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return xc.ParseData(context)
|
||||
}
|
||||
|
||||
// ParseData xml data
|
||||
func (xc *Config) ParseData(data []byte) (config.Configer, error) {
|
||||
x := &ConfigContainer{data: make(map[string]interface{})}
|
||||
|
||||
d, err := x2j.DocToMap(string(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x.data = config.ExpandValueEnvForMap(d["config"].(map[string]interface{}))
|
||||
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// ConfigContainer A Config represents the xml configuration.
|
||||
type ConfigContainer struct {
|
||||
data map[string]interface{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Bool returns the boolean value for a given key.
|
||||
func (c *ConfigContainer) Bool(key string) (bool, error) {
|
||||
if v := c.data[key]; v != nil {
|
||||
return config.ParseBool(v)
|
||||
}
|
||||
return false, fmt.Errorf("not exist key: %q", key)
|
||||
}
|
||||
|
||||
// DefaultBool return the bool value if has no error
|
||||
// otherwise return the defaultval
|
||||
func (c *ConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||
v, err := c.Bool(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns the integer value for a given key.
|
||||
func (c *ConfigContainer) Int(key string) (int, error) {
|
||||
return strconv.Atoi(c.data[key].(string))
|
||||
}
|
||||
|
||||
// DefaultInt returns the integer value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||
v, err := c.Int(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value for a given key.
|
||||
func (c *ConfigContainer) Int64(key string) (int64, error) {
|
||||
return strconv.ParseInt(c.data[key].(string), 10, 64)
|
||||
}
|
||||
|
||||
// DefaultInt64 returns the int64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||
v, err := c.Int64(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
|
||||
}
|
||||
|
||||
// Float returns the float value for a given key.
|
||||
func (c *ConfigContainer) Float(key string) (float64, error) {
|
||||
return strconv.ParseFloat(c.data[key].(string), 64)
|
||||
}
|
||||
|
||||
// DefaultFloat returns the float64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||
v, err := c.Float(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns the string value for a given key.
|
||||
func (c *ConfigContainer) String(key string) string {
|
||||
if v, ok := c.data[key].(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DefaultString returns the string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultString(key string, defaultval string) string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Strings returns the []string value for a given key.
|
||||
func (c *ConfigContainer) Strings(key string) []string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(v, ";")
|
||||
}
|
||||
|
||||
// DefaultStrings returns the []string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||
v := c.Strings(key)
|
||||
if v == nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSection returns map for the given section
|
||||
func (c *ConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||
if v, ok := c.data[section].(map[string]interface{}); ok {
|
||||
mapstr := make(map[string]string)
|
||||
for k, val := range v {
|
||||
mapstr[k] = config.ToString(val)
|
||||
}
|
||||
return mapstr, nil
|
||||
}
|
||||
return nil, fmt.Errorf("section '%s' not found", section)
|
||||
}
|
||||
|
||||
// SaveConfigFile save the config into file
|
||||
func (c *ConfigContainer) SaveConfigFile(filename string) (err error) {
|
||||
// Write configuration file by filename.
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
b, err := xml.MarshalIndent(c.data, " ", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set writes a new value for key.
|
||||
func (c *ConfigContainer) Set(key, val string) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// DIY returns the raw value by a given key.
|
||||
func (c *ConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||
if v, ok := c.data[key]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("not exist key")
|
||||
}
|
||||
|
||||
func init() {
|
||||
config.Register("xml", &Config{})
|
||||
}
|
||||
125
vendor/github.com/fatedier/beego/config/xml/xml_test.go
generated
vendored
Normal file
125
vendor/github.com/fatedier/beego/config/xml/xml_test.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package xml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
)
|
||||
|
||||
func TestXML(t *testing.T) {
|
||||
|
||||
var (
|
||||
//xml parse should incluce in <config></config> tags
|
||||
xmlcontext = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config>
|
||||
<appname>beeapi</appname>
|
||||
<httpport>8080</httpport>
|
||||
<mysqlport>3600</mysqlport>
|
||||
<PI>3.1415976</PI>
|
||||
<runmode>dev</runmode>
|
||||
<autorender>false</autorender>
|
||||
<copyrequestbody>true</copyrequestbody>
|
||||
<path1>${GOPATH}</path1>
|
||||
<path2>${GOPATH||/home/go}</path2>
|
||||
<mysection>
|
||||
<id>1</id>
|
||||
<name>MySection</name>
|
||||
</mysection>
|
||||
</config>
|
||||
`
|
||||
keyValue = map[string]interface{}{
|
||||
"appname": "beeapi",
|
||||
"httpport": 8080,
|
||||
"mysqlport": int64(3600),
|
||||
"PI": 3.1415976,
|
||||
"runmode": "dev",
|
||||
"autorender": false,
|
||||
"copyrequestbody": true,
|
||||
"path1": os.Getenv("GOPATH"),
|
||||
"path2": os.Getenv("GOPATH"),
|
||||
"error": "",
|
||||
"emptystrings": []string{},
|
||||
}
|
||||
)
|
||||
|
||||
f, err := os.Create("testxml.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(xmlcontext)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
defer os.Remove("testxml.conf")
|
||||
|
||||
xmlconf, err := config.NewConfig("xml", "testxml.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var xmlsection map[string]string
|
||||
xmlsection, err = xmlconf.GetSection("mysection")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(xmlsection) == 0 {
|
||||
t.Error("section should not be empty")
|
||||
}
|
||||
|
||||
for k, v := range keyValue {
|
||||
|
||||
var (
|
||||
value interface{}
|
||||
err error
|
||||
)
|
||||
|
||||
switch v.(type) {
|
||||
case int:
|
||||
value, err = xmlconf.Int(k)
|
||||
case int64:
|
||||
value, err = xmlconf.Int64(k)
|
||||
case float64:
|
||||
value, err = xmlconf.Float(k)
|
||||
case bool:
|
||||
value, err = xmlconf.Bool(k)
|
||||
case []string:
|
||||
value = xmlconf.Strings(k)
|
||||
case string:
|
||||
value = xmlconf.String(k)
|
||||
default:
|
||||
value, err = xmlconf.DIY(k)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("get key %q value fatal,%v err %s", k, v, err)
|
||||
} else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
|
||||
t.Errorf("get key %q value, want %v got %v .", k, v, value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err = xmlconf.Set("name", "astaxie"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if xmlconf.String("name") != "astaxie" {
|
||||
t.Fatal("get name error")
|
||||
}
|
||||
}
|
||||
297
vendor/github.com/fatedier/beego/config/yaml/yaml.go
generated
vendored
Normal file
297
vendor/github.com/fatedier/beego/config/yaml/yaml.go
generated
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package yaml for config provider
|
||||
//
|
||||
// depend on github.com/beego/goyaml2
|
||||
//
|
||||
// go install github.com/beego/goyaml2
|
||||
//
|
||||
// Usage:
|
||||
// import(
|
||||
// _ "github.com/astaxie/beego/config/yaml"
|
||||
// "github.com/astaxie/beego/config"
|
||||
// )
|
||||
//
|
||||
// cnf, err := config.NewConfig("yaml", "config.yaml")
|
||||
//
|
||||
//More docs http://beego.me/docs/module/config.md
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
"github.com/beego/goyaml2"
|
||||
)
|
||||
|
||||
// Config is a yaml config parser and implements Config interface.
|
||||
type Config struct{}
|
||||
|
||||
// Parse returns a ConfigContainer with parsed yaml config map.
|
||||
func (yaml *Config) Parse(filename string) (y config.Configer, err error) {
|
||||
cnf, err := ReadYmlReader(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
y = &ConfigContainer{
|
||||
data: cnf,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ParseData parse yaml data
|
||||
func (yaml *Config) ParseData(data []byte) (config.Configer, error) {
|
||||
cnf, err := parseYML(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ConfigContainer{
|
||||
data: cnf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ReadYmlReader Read yaml file to map.
|
||||
// if json like, use json package, unless goyaml2 package.
|
||||
func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
|
||||
buf, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return parseYML(buf)
|
||||
}
|
||||
|
||||
// parseYML parse yaml formatted []byte to map.
|
||||
func parseYML(buf []byte) (cnf map[string]interface{}, err error) {
|
||||
if len(buf) < 3 {
|
||||
return
|
||||
}
|
||||
|
||||
if string(buf[0:1]) == "{" {
|
||||
log.Println("Look like a Json, try json umarshal")
|
||||
err = json.Unmarshal(buf, &cnf)
|
||||
if err == nil {
|
||||
log.Println("It is Json Map")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
data, err := goyaml2.Read(bytes.NewBuffer(buf))
|
||||
if err != nil {
|
||||
log.Println("Goyaml2 ERR>", string(buf), err)
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf))
|
||||
return
|
||||
}
|
||||
cnf, ok := data.(map[string]interface{})
|
||||
if !ok {
|
||||
log.Println("Not a Map? >> ", string(buf), data)
|
||||
cnf = nil
|
||||
}
|
||||
cnf = config.ExpandValueEnvForMap(cnf)
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigContainer A Config represents the yaml configuration.
|
||||
type ConfigContainer struct {
|
||||
data map[string]interface{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Bool returns the boolean value for a given key.
|
||||
func (c *ConfigContainer) Bool(key string) (bool, error) {
|
||||
v, err := c.getData(key)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return config.ParseBool(v)
|
||||
}
|
||||
|
||||
// DefaultBool return the bool value if has no error
|
||||
// otherwise return the defaultval
|
||||
func (c *ConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||
v, err := c.Bool(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int returns the integer value for a given key.
|
||||
func (c *ConfigContainer) Int(key string) (int, error) {
|
||||
if v, err := c.getData(key); err != nil {
|
||||
return 0, err
|
||||
} else if vv, ok := v.(int); ok {
|
||||
return vv, nil
|
||||
} else if vv, ok := v.(int64); ok {
|
||||
return int(vv), nil
|
||||
}
|
||||
return 0, errors.New("not int value")
|
||||
}
|
||||
|
||||
// DefaultInt returns the integer value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||
v, err := c.Int(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value for a given key.
|
||||
func (c *ConfigContainer) Int64(key string) (int64, error) {
|
||||
if v, err := c.getData(key); err != nil {
|
||||
return 0, err
|
||||
} else if vv, ok := v.(int64); ok {
|
||||
return vv, nil
|
||||
}
|
||||
return 0, errors.New("not bool value")
|
||||
}
|
||||
|
||||
// DefaultInt64 returns the int64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||
v, err := c.Int64(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Float returns the float value for a given key.
|
||||
func (c *ConfigContainer) Float(key string) (float64, error) {
|
||||
if v, err := c.getData(key); err != nil {
|
||||
return 0.0, err
|
||||
} else if vv, ok := v.(float64); ok {
|
||||
return vv, nil
|
||||
} else if vv, ok := v.(int); ok {
|
||||
return float64(vv), nil
|
||||
} else if vv, ok := v.(int64); ok {
|
||||
return float64(vv), nil
|
||||
}
|
||||
return 0.0, errors.New("not float64 value")
|
||||
}
|
||||
|
||||
// DefaultFloat returns the float64 value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||
v, err := c.Float(key)
|
||||
if err != nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// String returns the string value for a given key.
|
||||
func (c *ConfigContainer) String(key string) string {
|
||||
if v, err := c.getData(key); err == nil {
|
||||
if vv, ok := v.(string); ok {
|
||||
return vv
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// DefaultString returns the string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultString(key string, defaultval string) string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Strings returns the []string value for a given key.
|
||||
func (c *ConfigContainer) Strings(key string) []string {
|
||||
v := c.String(key)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(v, ";")
|
||||
}
|
||||
|
||||
// DefaultStrings returns the []string value for a given key.
|
||||
// if err != nil return defaltval
|
||||
func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||
v := c.Strings(key)
|
||||
if v == nil {
|
||||
return defaultval
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSection returns map for the given section
|
||||
func (c *ConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||
|
||||
if v, ok := c.data[section]; ok {
|
||||
return v.(map[string]string), nil
|
||||
}
|
||||
return nil, errors.New("not exist section")
|
||||
}
|
||||
|
||||
// SaveConfigFile save the config into file
|
||||
func (c *ConfigContainer) SaveConfigFile(filename string) (err error) {
|
||||
// Write configuration file by filename.
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
err = goyaml2.Write(f, c.data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set writes a new value for key.
|
||||
func (c *ConfigContainer) Set(key, val string) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.data[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
// DIY returns the raw value by a given key.
|
||||
func (c *ConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||
return c.getData(key)
|
||||
}
|
||||
|
||||
func (c *ConfigContainer) getData(key string) (interface{}, error) {
|
||||
|
||||
if len(key) == 0 {
|
||||
return nil, errors.New("key is empty")
|
||||
}
|
||||
|
||||
if v, ok := c.data[key]; ok {
|
||||
return v, nil
|
||||
}
|
||||
return nil, fmt.Errorf("not exist key %q", key)
|
||||
}
|
||||
|
||||
func init() {
|
||||
config.Register("yaml", &Config{})
|
||||
}
|
||||
115
vendor/github.com/fatedier/beego/config/yaml/yaml_test.go
generated
vendored
Normal file
115
vendor/github.com/fatedier/beego/config/yaml/yaml_test.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
)
|
||||
|
||||
func TestYaml(t *testing.T) {
|
||||
|
||||
var (
|
||||
yamlcontext = `
|
||||
"appname": beeapi
|
||||
"httpport": 8080
|
||||
"mysqlport": 3600
|
||||
"PI": 3.1415976
|
||||
"runmode": dev
|
||||
"autorender": false
|
||||
"copyrequestbody": true
|
||||
"PATH": GOPATH
|
||||
"path1": ${GOPATH}
|
||||
"path2": ${GOPATH||/home/go}
|
||||
"empty": ""
|
||||
`
|
||||
|
||||
keyValue = map[string]interface{}{
|
||||
"appname": "beeapi",
|
||||
"httpport": 8080,
|
||||
"mysqlport": int64(3600),
|
||||
"PI": 3.1415976,
|
||||
"runmode": "dev",
|
||||
"autorender": false,
|
||||
"copyrequestbody": true,
|
||||
"PATH": "GOPATH",
|
||||
"path1": os.Getenv("GOPATH"),
|
||||
"path2": os.Getenv("GOPATH"),
|
||||
"error": "",
|
||||
"emptystrings": []string{},
|
||||
}
|
||||
)
|
||||
f, err := os.Create("testyaml.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(yamlcontext)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
defer os.Remove("testyaml.conf")
|
||||
yamlconf, err := config.NewConfig("yaml", "testyaml.conf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if yamlconf.String("appname") != "beeapi" {
|
||||
t.Fatal("appname not equal to beeapi")
|
||||
}
|
||||
|
||||
for k, v := range keyValue {
|
||||
|
||||
var (
|
||||
value interface{}
|
||||
err error
|
||||
)
|
||||
|
||||
switch v.(type) {
|
||||
case int:
|
||||
value, err = yamlconf.Int(k)
|
||||
case int64:
|
||||
value, err = yamlconf.Int64(k)
|
||||
case float64:
|
||||
value, err = yamlconf.Float(k)
|
||||
case bool:
|
||||
value, err = yamlconf.Bool(k)
|
||||
case []string:
|
||||
value = yamlconf.Strings(k)
|
||||
case string:
|
||||
value = yamlconf.String(k)
|
||||
default:
|
||||
value, err = yamlconf.DIY(k)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("get key %q value fatal,%v err %s", k, v, err)
|
||||
} else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) {
|
||||
t.Errorf("get key %q value, want %v got %v .", k, v, value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err = yamlconf.Set("name", "astaxie"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if yamlconf.String("name") != "astaxie" {
|
||||
t.Fatal("get name error")
|
||||
}
|
||||
|
||||
}
|
||||
138
vendor/github.com/fatedier/beego/config_test.go
generated
vendored
Normal file
138
vendor/github.com/fatedier/beego/config_test.go
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/config"
|
||||
)
|
||||
|
||||
func TestDefaults(t *testing.T) {
|
||||
if BConfig.WebConfig.FlashName != "BEEGO_FLASH" {
|
||||
t.Errorf("FlashName was not set to default.")
|
||||
}
|
||||
|
||||
if BConfig.WebConfig.FlashSeparator != "BEEGOFLASH" {
|
||||
t.Errorf("FlashName was not set to default.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssignConfig_01(t *testing.T) {
|
||||
_BConfig := &Config{}
|
||||
_BConfig.AppName = "beego_test"
|
||||
jcf := &config.JSONConfig{}
|
||||
ac, _ := jcf.ParseData([]byte(`{"AppName":"beego_json"}`))
|
||||
assignSingleConfig(_BConfig, ac)
|
||||
if _BConfig.AppName != "beego_json" {
|
||||
t.Log(_BConfig)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssignConfig_02(t *testing.T) {
|
||||
_BConfig := &Config{}
|
||||
bs, _ := json.Marshal(newBConfig())
|
||||
|
||||
jsonMap := map[string]interface{}{}
|
||||
json.Unmarshal(bs, &jsonMap)
|
||||
|
||||
configMap := map[string]interface{}{}
|
||||
for k, v := range jsonMap {
|
||||
if reflect.TypeOf(v).Kind() == reflect.Map {
|
||||
for k1, v1 := range v.(map[string]interface{}) {
|
||||
if reflect.TypeOf(v1).Kind() == reflect.Map {
|
||||
for k2, v2 := range v1.(map[string]interface{}) {
|
||||
configMap[k2] = v2
|
||||
}
|
||||
} else {
|
||||
configMap[k1] = v1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
configMap[k] = v
|
||||
}
|
||||
}
|
||||
configMap["MaxMemory"] = 1024
|
||||
configMap["Graceful"] = true
|
||||
configMap["XSRFExpire"] = 32
|
||||
configMap["SessionProviderConfig"] = "file"
|
||||
configMap["FileLineNum"] = true
|
||||
|
||||
jcf := &config.JSONConfig{}
|
||||
bs, _ = json.Marshal(configMap)
|
||||
ac, _ := jcf.ParseData([]byte(bs))
|
||||
|
||||
for _, i := range []interface{}{_BConfig, &_BConfig.Listen, &_BConfig.WebConfig, &_BConfig.Log, &_BConfig.WebConfig.Session} {
|
||||
assignSingleConfig(i, ac)
|
||||
}
|
||||
|
||||
if _BConfig.MaxMemory != 1024 {
|
||||
t.Log(_BConfig.MaxMemory)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !_BConfig.Listen.Graceful {
|
||||
t.Log(_BConfig.Listen.Graceful)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if _BConfig.WebConfig.XSRFExpire != 32 {
|
||||
t.Log(_BConfig.WebConfig.XSRFExpire)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if _BConfig.WebConfig.Session.SessionProviderConfig != "file" {
|
||||
t.Log(_BConfig.WebConfig.Session.SessionProviderConfig)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !_BConfig.Log.FileLineNum {
|
||||
t.Log(_BConfig.Log.FileLineNum)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAssignConfig_03(t *testing.T) {
|
||||
jcf := &config.JSONConfig{}
|
||||
ac, _ := jcf.ParseData([]byte(`{"AppName":"beego"}`))
|
||||
ac.Set("AppName", "test_app")
|
||||
ac.Set("RunMode", "online")
|
||||
ac.Set("StaticDir", "download:down download2:down2")
|
||||
ac.Set("StaticExtensionsToGzip", ".css,.js,.html,.jpg,.png")
|
||||
assignConfig(ac)
|
||||
|
||||
t.Logf("%#v", BConfig)
|
||||
|
||||
if BConfig.AppName != "test_app" {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if BConfig.RunMode != "online" {
|
||||
t.FailNow()
|
||||
}
|
||||
if BConfig.WebConfig.StaticDir["/download"] != "down" {
|
||||
t.FailNow()
|
||||
}
|
||||
if BConfig.WebConfig.StaticDir["/download2"] != "down2" {
|
||||
t.FailNow()
|
||||
}
|
||||
if len(BConfig.WebConfig.StaticExtensionsToGzip) != 5 {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
231
vendor/github.com/fatedier/beego/context/acceptencoder.go
generated
vendored
Normal file
231
vendor/github.com/fatedier/beego/context/acceptencoder.go
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright 2015 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
//Default size==20B same as nginx
|
||||
defaultGzipMinLength = 20
|
||||
//Content will only be compressed if content length is either unknown or greater than gzipMinLength.
|
||||
gzipMinLength = defaultGzipMinLength
|
||||
//The compression level used for deflate compression. (0-9).
|
||||
gzipCompressLevel int
|
||||
//List of HTTP methods to compress. If not set, only GET requests are compressed.
|
||||
includedMethods map[string]bool
|
||||
getMethodOnly bool
|
||||
)
|
||||
|
||||
func InitGzip(minLength, compressLevel int, methods []string) {
|
||||
if minLength >= 0 {
|
||||
gzipMinLength = minLength
|
||||
}
|
||||
gzipCompressLevel = compressLevel
|
||||
if gzipCompressLevel < flate.NoCompression || gzipCompressLevel > flate.BestCompression {
|
||||
gzipCompressLevel = flate.BestSpeed
|
||||
}
|
||||
getMethodOnly = (len(methods) == 0) || (len(methods) == 1 && strings.ToUpper(methods[0]) == "GET")
|
||||
includedMethods = make(map[string]bool, len(methods))
|
||||
for _, v := range methods {
|
||||
includedMethods[strings.ToUpper(v)] = true
|
||||
}
|
||||
}
|
||||
|
||||
type resetWriter interface {
|
||||
io.Writer
|
||||
Reset(w io.Writer)
|
||||
}
|
||||
|
||||
type nopResetWriter struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (n nopResetWriter) Reset(w io.Writer) {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
type acceptEncoder struct {
|
||||
name string
|
||||
levelEncode func(int) resetWriter
|
||||
customCompressLevelPool *sync.Pool
|
||||
bestCompressionPool *sync.Pool
|
||||
}
|
||||
|
||||
func (ac acceptEncoder) encode(wr io.Writer, level int) resetWriter {
|
||||
if ac.customCompressLevelPool == nil || ac.bestCompressionPool == nil {
|
||||
return nopResetWriter{wr}
|
||||
}
|
||||
var rwr resetWriter
|
||||
switch level {
|
||||
case flate.BestSpeed:
|
||||
rwr = ac.customCompressLevelPool.Get().(resetWriter)
|
||||
case flate.BestCompression:
|
||||
rwr = ac.bestCompressionPool.Get().(resetWriter)
|
||||
default:
|
||||
rwr = ac.levelEncode(level)
|
||||
}
|
||||
rwr.Reset(wr)
|
||||
return rwr
|
||||
}
|
||||
|
||||
func (ac acceptEncoder) put(wr resetWriter, level int) {
|
||||
if ac.customCompressLevelPool == nil || ac.bestCompressionPool == nil {
|
||||
return
|
||||
}
|
||||
wr.Reset(nil)
|
||||
|
||||
//notice
|
||||
//compressionLevel==BestCompression DOES NOT MATTER
|
||||
//sync.Pool will not memory leak
|
||||
|
||||
switch level {
|
||||
case gzipCompressLevel:
|
||||
ac.customCompressLevelPool.Put(wr)
|
||||
case flate.BestCompression:
|
||||
ac.bestCompressionPool.Put(wr)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
noneCompressEncoder = acceptEncoder{"", nil, nil, nil}
|
||||
gzipCompressEncoder = acceptEncoder{
|
||||
name: "gzip",
|
||||
levelEncode: func(level int) resetWriter { wr, _ := gzip.NewWriterLevel(nil, level); return wr },
|
||||
customCompressLevelPool: &sync.Pool{New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, gzipCompressLevel); return wr }},
|
||||
bestCompressionPool: &sync.Pool{New: func() interface{} { wr, _ := gzip.NewWriterLevel(nil, flate.BestCompression); return wr }},
|
||||
}
|
||||
|
||||
//according to the sec :http://tools.ietf.org/html/rfc2616#section-3.5 ,the deflate compress in http is zlib indeed
|
||||
//deflate
|
||||
//The "zlib" format defined in RFC 1950 [31] in combination with
|
||||
//the "deflate" compression mechanism described in RFC 1951 [29].
|
||||
deflateCompressEncoder = acceptEncoder{
|
||||
name: "deflate",
|
||||
levelEncode: func(level int) resetWriter { wr, _ := zlib.NewWriterLevel(nil, level); return wr },
|
||||
customCompressLevelPool: &sync.Pool{New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, gzipCompressLevel); return wr }},
|
||||
bestCompressionPool: &sync.Pool{New: func() interface{} { wr, _ := zlib.NewWriterLevel(nil, flate.BestCompression); return wr }},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
encoderMap = map[string]acceptEncoder{ // all the other compress methods will ignore
|
||||
"gzip": gzipCompressEncoder,
|
||||
"deflate": deflateCompressEncoder,
|
||||
"*": gzipCompressEncoder, // * means any compress will accept,we prefer gzip
|
||||
"identity": noneCompressEncoder, // identity means none-compress
|
||||
}
|
||||
)
|
||||
|
||||
// WriteFile reads from file and writes to writer by the specific encoding(gzip/deflate)
|
||||
func WriteFile(encoding string, writer io.Writer, file *os.File) (bool, string, error) {
|
||||
return writeLevel(encoding, writer, file, flate.BestCompression)
|
||||
}
|
||||
|
||||
// WriteBody reads writes content to writer by the specific encoding(gzip/deflate)
|
||||
func WriteBody(encoding string, writer io.Writer, content []byte) (bool, string, error) {
|
||||
if encoding == "" || len(content) < gzipMinLength {
|
||||
_, err := writer.Write(content)
|
||||
return false, "", err
|
||||
}
|
||||
return writeLevel(encoding, writer, bytes.NewReader(content), gzipCompressLevel)
|
||||
}
|
||||
|
||||
// writeLevel reads from reader,writes to writer by specific encoding and compress level
|
||||
// the compress level is defined by deflate package
|
||||
func writeLevel(encoding string, writer io.Writer, reader io.Reader, level int) (bool, string, error) {
|
||||
var outputWriter resetWriter
|
||||
var err error
|
||||
var ce = noneCompressEncoder
|
||||
|
||||
if cf, ok := encoderMap[encoding]; ok {
|
||||
ce = cf
|
||||
}
|
||||
encoding = ce.name
|
||||
outputWriter = ce.encode(writer, level)
|
||||
defer ce.put(outputWriter, level)
|
||||
|
||||
_, err = io.Copy(outputWriter, reader)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
|
||||
switch outputWriter.(type) {
|
||||
case io.WriteCloser:
|
||||
outputWriter.(io.WriteCloser).Close()
|
||||
}
|
||||
return encoding != "", encoding, nil
|
||||
}
|
||||
|
||||
// ParseEncoding will extract the right encoding for response
|
||||
// the Accept-Encoding's sec is here:
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
|
||||
func ParseEncoding(r *http.Request) string {
|
||||
if r == nil {
|
||||
return ""
|
||||
}
|
||||
if (getMethodOnly && r.Method == "GET") || includedMethods[r.Method] {
|
||||
return parseEncoding(r)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type q struct {
|
||||
name string
|
||||
value float64
|
||||
}
|
||||
|
||||
func parseEncoding(r *http.Request) string {
|
||||
acceptEncoding := r.Header.Get("Accept-Encoding")
|
||||
if acceptEncoding == "" {
|
||||
return ""
|
||||
}
|
||||
var lastQ q
|
||||
for _, v := range strings.Split(acceptEncoding, ",") {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
vs := strings.Split(v, ";")
|
||||
var cf acceptEncoder
|
||||
var ok bool
|
||||
if cf, ok = encoderMap[vs[0]]; !ok {
|
||||
continue
|
||||
}
|
||||
if len(vs) == 1 {
|
||||
return cf.name
|
||||
}
|
||||
if len(vs) == 2 {
|
||||
f, _ := strconv.ParseFloat(strings.Replace(vs[1], "q=", "", -1), 64)
|
||||
if f == 0 {
|
||||
continue
|
||||
}
|
||||
if f > lastQ.value {
|
||||
lastQ = q{cf.name, f}
|
||||
}
|
||||
}
|
||||
}
|
||||
return lastQ.name
|
||||
}
|
||||
59
vendor/github.com/fatedier/beego/context/acceptencoder_test.go
generated
vendored
Normal file
59
vendor/github.com/fatedier/beego/context/acceptencoder_test.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2015 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_ExtractEncoding(t *testing.T) {
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip,deflate"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"deflate,gzip"}}}) != "deflate" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip;q=.5,deflate"}}}) != "deflate" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip;q=.5,deflate;q=0.3"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip;q=0,deflate"}}}) != "deflate" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"deflate;q=0.5,gzip;q=0.5,identity"}}}) != "" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"*"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"x,gzip,deflate"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip,x,deflate"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip;q=0.5,x,deflate"}}}) != "deflate" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"x"}}}) != "" {
|
||||
t.Fail()
|
||||
}
|
||||
if parseEncoding(&http.Request{Header: map[string][]string{"Accept-Encoding": {"gzip;q=0.5,x;q=0.8"}}}) != "gzip" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
230
vendor/github.com/fatedier/beego/context/context.go
generated
vendored
Normal file
230
vendor/github.com/fatedier/beego/context/context.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package context provide the context utils
|
||||
// Usage:
|
||||
//
|
||||
// import "github.com/astaxie/beego/context"
|
||||
//
|
||||
// ctx := context.Context{Request:req,ResponseWriter:rw}
|
||||
//
|
||||
// more docs http://beego.me/docs/module/context.md
|
||||
package context
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
// NewContext return the Context with Input and Output
|
||||
func NewContext() *Context {
|
||||
return &Context{
|
||||
Input: NewInput(),
|
||||
Output: NewOutput(),
|
||||
}
|
||||
}
|
||||
|
||||
// Context Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter.
|
||||
// BeegoInput and BeegoOutput provides some api to operate request and response more easily.
|
||||
type Context struct {
|
||||
Input *BeegoInput
|
||||
Output *BeegoOutput
|
||||
Request *http.Request
|
||||
ResponseWriter *Response
|
||||
_xsrfToken string
|
||||
}
|
||||
|
||||
// Reset init Context, BeegoInput and BeegoOutput
|
||||
func (ctx *Context) Reset(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx.Request = r
|
||||
if ctx.ResponseWriter == nil {
|
||||
ctx.ResponseWriter = &Response{}
|
||||
}
|
||||
ctx.ResponseWriter.reset(rw)
|
||||
ctx.Input.Reset(ctx)
|
||||
ctx.Output.Reset(ctx)
|
||||
ctx._xsrfToken = ""
|
||||
}
|
||||
|
||||
// Redirect does redirection to localurl with http header status code.
|
||||
func (ctx *Context) Redirect(status int, localurl string) {
|
||||
http.Redirect(ctx.ResponseWriter, ctx.Request, localurl, status)
|
||||
}
|
||||
|
||||
// Abort stops this request.
|
||||
// if beego.ErrorMaps exists, panic body.
|
||||
func (ctx *Context) Abort(status int, body string) {
|
||||
ctx.Output.SetStatus(status)
|
||||
panic(body)
|
||||
}
|
||||
|
||||
// WriteString Write string to response body.
|
||||
// it sends response body.
|
||||
func (ctx *Context) WriteString(content string) {
|
||||
ctx.ResponseWriter.Write([]byte(content))
|
||||
}
|
||||
|
||||
// GetCookie Get cookie from request by a given key.
|
||||
// It's alias of BeegoInput.Cookie.
|
||||
func (ctx *Context) GetCookie(key string) string {
|
||||
return ctx.Input.Cookie(key)
|
||||
}
|
||||
|
||||
// SetCookie Set cookie for response.
|
||||
// It's alias of BeegoOutput.Cookie.
|
||||
func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
|
||||
ctx.Output.Cookie(name, value, others...)
|
||||
}
|
||||
|
||||
// GetSecureCookie Get secure cookie from request by a given key.
|
||||
func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) {
|
||||
val := ctx.Input.Cookie(key)
|
||||
if val == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
parts := strings.SplitN(val, "|", 3)
|
||||
|
||||
if len(parts) != 3 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
vs := parts[0]
|
||||
timestamp := parts[1]
|
||||
sig := parts[2]
|
||||
|
||||
h := hmac.New(sha1.New, []byte(Secret))
|
||||
fmt.Fprintf(h, "%s%s", vs, timestamp)
|
||||
|
||||
if fmt.Sprintf("%02x", h.Sum(nil)) != sig {
|
||||
return "", false
|
||||
}
|
||||
res, _ := base64.URLEncoding.DecodeString(vs)
|
||||
return string(res), true
|
||||
}
|
||||
|
||||
// SetSecureCookie Set Secure cookie for response.
|
||||
func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) {
|
||||
vs := base64.URLEncoding.EncodeToString([]byte(value))
|
||||
timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
h := hmac.New(sha1.New, []byte(Secret))
|
||||
fmt.Fprintf(h, "%s%s", vs, timestamp)
|
||||
sig := fmt.Sprintf("%02x", h.Sum(nil))
|
||||
cookie := strings.Join([]string{vs, timestamp, sig}, "|")
|
||||
ctx.Output.Cookie(name, cookie, others...)
|
||||
}
|
||||
|
||||
// XSRFToken creates a xsrf token string and returns.
|
||||
func (ctx *Context) XSRFToken(key string, expire int64) string {
|
||||
if ctx._xsrfToken == "" {
|
||||
token, ok := ctx.GetSecureCookie(key, "_xsrf")
|
||||
if !ok {
|
||||
token = string(utils.RandomCreateBytes(32))
|
||||
ctx.SetSecureCookie(key, "_xsrf", token, expire)
|
||||
}
|
||||
ctx._xsrfToken = token
|
||||
}
|
||||
return ctx._xsrfToken
|
||||
}
|
||||
|
||||
// CheckXSRFCookie checks xsrf token in this request is valid or not.
|
||||
// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
|
||||
// or in form field value named as "_xsrf".
|
||||
func (ctx *Context) CheckXSRFCookie() bool {
|
||||
token := ctx.Input.Query("_xsrf")
|
||||
if token == "" {
|
||||
token = ctx.Request.Header.Get("X-Xsrftoken")
|
||||
}
|
||||
if token == "" {
|
||||
token = ctx.Request.Header.Get("X-Csrftoken")
|
||||
}
|
||||
if token == "" {
|
||||
ctx.Abort(403, "'_xsrf' argument missing from POST")
|
||||
return false
|
||||
}
|
||||
if ctx._xsrfToken != token {
|
||||
ctx.Abort(403, "XSRF cookie does not match POST argument")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//Response is a wrapper for the http.ResponseWriter
|
||||
//started set to true if response was written to then don't execute other handler
|
||||
type Response struct {
|
||||
http.ResponseWriter
|
||||
Started bool
|
||||
Status int
|
||||
}
|
||||
|
||||
func (r *Response) reset(rw http.ResponseWriter) {
|
||||
r.ResponseWriter = rw
|
||||
r.Status = 0
|
||||
r.Started = false
|
||||
}
|
||||
|
||||
// Write writes the data to the connection as part of an HTTP reply,
|
||||
// and sets `started` to true.
|
||||
// started means the response has sent out.
|
||||
func (r *Response) Write(p []byte) (int, error) {
|
||||
r.Started = true
|
||||
return r.ResponseWriter.Write(p)
|
||||
}
|
||||
|
||||
// WriteHeader sends an HTTP response header with status code,
|
||||
// and sets `started` to true.
|
||||
func (r *Response) WriteHeader(code int) {
|
||||
if r.Status > 0 {
|
||||
//prevent multiple response.WriteHeader calls
|
||||
return
|
||||
}
|
||||
r.Status = code
|
||||
r.Started = true
|
||||
r.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
// Hijack hijacker for http
|
||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
hj, ok := r.ResponseWriter.(http.Hijacker)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("webserver doesn't support hijacking")
|
||||
}
|
||||
return hj.Hijack()
|
||||
}
|
||||
|
||||
// Flush http.Flusher
|
||||
func (r *Response) Flush() {
|
||||
if f, ok := r.ResponseWriter.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// CloseNotify http.CloseNotifier
|
||||
func (r *Response) CloseNotify() <-chan bool {
|
||||
if cn, ok := r.ResponseWriter.(http.CloseNotifier); ok {
|
||||
return cn.CloseNotify()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
47
vendor/github.com/fatedier/beego/context/context_test.go
generated
vendored
Normal file
47
vendor/github.com/fatedier/beego/context/context_test.go
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2016 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestXsrfReset_01(t *testing.T) {
|
||||
r := &http.Request{}
|
||||
c := NewContext()
|
||||
c.Request = r
|
||||
c.ResponseWriter = &Response{}
|
||||
c.ResponseWriter.reset(httptest.NewRecorder())
|
||||
c.Output.Reset(c)
|
||||
c.Input.Reset(c)
|
||||
c.XSRFToken("key", 16)
|
||||
if c._xsrfToken == "" {
|
||||
t.FailNow()
|
||||
}
|
||||
token := c._xsrfToken
|
||||
c.Reset(&Response{ResponseWriter: httptest.NewRecorder()}, r)
|
||||
if c._xsrfToken != "" {
|
||||
t.FailNow()
|
||||
}
|
||||
c.XSRFToken("key", 16)
|
||||
if c._xsrfToken == "" {
|
||||
t.FailNow()
|
||||
}
|
||||
if token == c._xsrfToken {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
650
vendor/github.com/fatedier/beego/context/input.go
generated
vendored
Normal file
650
vendor/github.com/fatedier/beego/context/input.go
generated
vendored
Normal file
@@ -0,0 +1,650 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/session"
|
||||
)
|
||||
|
||||
// Regexes for checking the accept headers
|
||||
// TODO make sure these are correct
|
||||
var (
|
||||
acceptsHTMLRegex = regexp.MustCompile(`(text/html|application/xhtml\+xml)(?:,|$)`)
|
||||
acceptsXMLRegex = regexp.MustCompile(`(application/xml|text/xml)(?:,|$)`)
|
||||
acceptsJSONRegex = regexp.MustCompile(`(application/json)(?:,|$)`)
|
||||
maxParam = 50
|
||||
)
|
||||
|
||||
// BeegoInput operates the http request header, data, cookie and body.
|
||||
// it also contains router params and current session.
|
||||
type BeegoInput struct {
|
||||
Context *Context
|
||||
CruSession session.Store
|
||||
pnames []string
|
||||
pvalues []string
|
||||
data map[interface{}]interface{} // store some values in this context when calling context in filter or controller.
|
||||
RequestBody []byte
|
||||
RunMethod string
|
||||
RunController reflect.Type
|
||||
}
|
||||
|
||||
// NewInput return BeegoInput generated by Context.
|
||||
func NewInput() *BeegoInput {
|
||||
return &BeegoInput{
|
||||
pnames: make([]string, 0, maxParam),
|
||||
pvalues: make([]string, 0, maxParam),
|
||||
data: make(map[interface{}]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Reset init the BeegoInput
|
||||
func (input *BeegoInput) Reset(ctx *Context) {
|
||||
input.Context = ctx
|
||||
input.CruSession = nil
|
||||
input.pnames = input.pnames[:0]
|
||||
input.pvalues = input.pvalues[:0]
|
||||
input.data = nil
|
||||
input.RequestBody = []byte{}
|
||||
}
|
||||
|
||||
// Protocol returns request protocol name, such as HTTP/1.1 .
|
||||
func (input *BeegoInput) Protocol() string {
|
||||
return input.Context.Request.Proto
|
||||
}
|
||||
|
||||
// URI returns full request url with query string, fragment.
|
||||
func (input *BeegoInput) URI() string {
|
||||
return input.Context.Request.RequestURI
|
||||
}
|
||||
|
||||
// URL returns request url path (without query string, fragment).
|
||||
func (input *BeegoInput) URL() string {
|
||||
return input.Context.Request.URL.Path
|
||||
}
|
||||
|
||||
// Site returns base site url as scheme://domain type.
|
||||
func (input *BeegoInput) Site() string {
|
||||
return input.Scheme() + "://" + input.Domain()
|
||||
}
|
||||
|
||||
// Scheme returns request scheme as "http" or "https".
|
||||
func (input *BeegoInput) Scheme() string {
|
||||
if scheme := input.Header("X-Forwarded-Proto"); scheme != "" {
|
||||
return scheme
|
||||
}
|
||||
if input.Context.Request.URL.Scheme != "" {
|
||||
return input.Context.Request.URL.Scheme
|
||||
}
|
||||
if input.Context.Request.TLS == nil {
|
||||
return "http"
|
||||
}
|
||||
return "https"
|
||||
}
|
||||
|
||||
// Domain returns host name.
|
||||
// Alias of Host method.
|
||||
func (input *BeegoInput) Domain() string {
|
||||
return input.Host()
|
||||
}
|
||||
|
||||
// Host returns host name.
|
||||
// if no host info in request, return localhost.
|
||||
func (input *BeegoInput) Host() string {
|
||||
if input.Context.Request.Host != "" {
|
||||
hostParts := strings.Split(input.Context.Request.Host, ":")
|
||||
if len(hostParts) > 0 {
|
||||
return hostParts[0]
|
||||
}
|
||||
return input.Context.Request.Host
|
||||
}
|
||||
return "localhost"
|
||||
}
|
||||
|
||||
// Method returns http request method.
|
||||
func (input *BeegoInput) Method() string {
|
||||
return input.Context.Request.Method
|
||||
}
|
||||
|
||||
// Is returns boolean of this request is on given method, such as Is("POST").
|
||||
func (input *BeegoInput) Is(method string) bool {
|
||||
return input.Method() == method
|
||||
}
|
||||
|
||||
// IsGet Is this a GET method request?
|
||||
func (input *BeegoInput) IsGet() bool {
|
||||
return input.Is("GET")
|
||||
}
|
||||
|
||||
// IsPost Is this a POST method request?
|
||||
func (input *BeegoInput) IsPost() bool {
|
||||
return input.Is("POST")
|
||||
}
|
||||
|
||||
// IsHead Is this a Head method request?
|
||||
func (input *BeegoInput) IsHead() bool {
|
||||
return input.Is("HEAD")
|
||||
}
|
||||
|
||||
// IsOptions Is this a OPTIONS method request?
|
||||
func (input *BeegoInput) IsOptions() bool {
|
||||
return input.Is("OPTIONS")
|
||||
}
|
||||
|
||||
// IsPut Is this a PUT method request?
|
||||
func (input *BeegoInput) IsPut() bool {
|
||||
return input.Is("PUT")
|
||||
}
|
||||
|
||||
// IsDelete Is this a DELETE method request?
|
||||
func (input *BeegoInput) IsDelete() bool {
|
||||
return input.Is("DELETE")
|
||||
}
|
||||
|
||||
// IsPatch Is this a PATCH method request?
|
||||
func (input *BeegoInput) IsPatch() bool {
|
||||
return input.Is("PATCH")
|
||||
}
|
||||
|
||||
// IsAjax returns boolean of this request is generated by ajax.
|
||||
func (input *BeegoInput) IsAjax() bool {
|
||||
return input.Header("X-Requested-With") == "XMLHttpRequest"
|
||||
}
|
||||
|
||||
// IsSecure returns boolean of this request is in https.
|
||||
func (input *BeegoInput) IsSecure() bool {
|
||||
return input.Scheme() == "https"
|
||||
}
|
||||
|
||||
// IsWebsocket returns boolean of this request is in webSocket.
|
||||
func (input *BeegoInput) IsWebsocket() bool {
|
||||
return input.Header("Upgrade") == "websocket"
|
||||
}
|
||||
|
||||
// IsUpload returns boolean of whether file uploads in this request or not..
|
||||
func (input *BeegoInput) IsUpload() bool {
|
||||
return strings.Contains(input.Header("Content-Type"), "multipart/form-data")
|
||||
}
|
||||
|
||||
// AcceptsHTML Checks if request accepts html response
|
||||
func (input *BeegoInput) AcceptsHTML() bool {
|
||||
return acceptsHTMLRegex.MatchString(input.Header("Accept"))
|
||||
}
|
||||
|
||||
// AcceptsXML Checks if request accepts xml response
|
||||
func (input *BeegoInput) AcceptsXML() bool {
|
||||
return acceptsXMLRegex.MatchString(input.Header("Accept"))
|
||||
}
|
||||
|
||||
// AcceptsJSON Checks if request accepts json response
|
||||
func (input *BeegoInput) AcceptsJSON() bool {
|
||||
return acceptsJSONRegex.MatchString(input.Header("Accept"))
|
||||
}
|
||||
|
||||
// IP returns request client ip.
|
||||
// if in proxy, return first proxy id.
|
||||
// if error, return 127.0.0.1.
|
||||
func (input *BeegoInput) IP() string {
|
||||
ips := input.Proxy()
|
||||
if len(ips) > 0 && ips[0] != "" {
|
||||
rip := strings.Split(ips[0], ":")
|
||||
return rip[0]
|
||||
}
|
||||
ip := strings.Split(input.Context.Request.RemoteAddr, ":")
|
||||
if len(ip) > 0 {
|
||||
if ip[0] != "[" {
|
||||
return ip[0]
|
||||
}
|
||||
}
|
||||
return "127.0.0.1"
|
||||
}
|
||||
|
||||
// Proxy returns proxy client ips slice.
|
||||
func (input *BeegoInput) Proxy() []string {
|
||||
if ips := input.Header("X-Forwarded-For"); ips != "" {
|
||||
return strings.Split(ips, ",")
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Referer returns http referer header.
|
||||
func (input *BeegoInput) Referer() string {
|
||||
return input.Header("Referer")
|
||||
}
|
||||
|
||||
// Refer returns http referer header.
|
||||
func (input *BeegoInput) Refer() string {
|
||||
return input.Referer()
|
||||
}
|
||||
|
||||
// SubDomains returns sub domain string.
|
||||
// if aa.bb.domain.com, returns aa.bb .
|
||||
func (input *BeegoInput) SubDomains() string {
|
||||
parts := strings.Split(input.Host(), ".")
|
||||
if len(parts) >= 3 {
|
||||
return strings.Join(parts[:len(parts)-2], ".")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Port returns request client port.
|
||||
// when error or empty, return 80.
|
||||
func (input *BeegoInput) Port() int {
|
||||
parts := strings.Split(input.Context.Request.Host, ":")
|
||||
if len(parts) == 2 {
|
||||
port, _ := strconv.Atoi(parts[1])
|
||||
return port
|
||||
}
|
||||
return 80
|
||||
}
|
||||
|
||||
// UserAgent returns request client user agent string.
|
||||
func (input *BeegoInput) UserAgent() string {
|
||||
return input.Header("User-Agent")
|
||||
}
|
||||
|
||||
// ParamsLen return the length of the params
|
||||
func (input *BeegoInput) ParamsLen() int {
|
||||
return len(input.pnames)
|
||||
}
|
||||
|
||||
// Param returns router param by a given key.
|
||||
func (input *BeegoInput) Param(key string) string {
|
||||
for i, v := range input.pnames {
|
||||
if v == key && i <= len(input.pvalues) {
|
||||
return input.pvalues[i]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Params returns the map[key]value.
|
||||
func (input *BeegoInput) Params() map[string]string {
|
||||
m := make(map[string]string)
|
||||
for i, v := range input.pnames {
|
||||
if i <= len(input.pvalues) {
|
||||
m[v] = input.pvalues[i]
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// SetParam will set the param with key and value
|
||||
func (input *BeegoInput) SetParam(key, val string) {
|
||||
// check if already exists
|
||||
for i, v := range input.pnames {
|
||||
if v == key && i <= len(input.pvalues) {
|
||||
input.pvalues[i] = val
|
||||
return
|
||||
}
|
||||
}
|
||||
input.pvalues = append(input.pvalues, val)
|
||||
input.pnames = append(input.pnames, key)
|
||||
}
|
||||
|
||||
// ResetParams clears any of the input's Params
|
||||
// This function is used to clear parameters so they may be reset between filter
|
||||
// passes.
|
||||
func (input *BeegoInput) ResetParams() {
|
||||
input.pnames = input.pnames[:0]
|
||||
input.pvalues = input.pvalues[:0]
|
||||
}
|
||||
|
||||
// Query returns input data item string by a given string.
|
||||
func (input *BeegoInput) Query(key string) string {
|
||||
if val := input.Param(key); val != "" {
|
||||
return val
|
||||
}
|
||||
if input.Context.Request.Form == nil {
|
||||
input.Context.Request.ParseForm()
|
||||
}
|
||||
return input.Context.Request.Form.Get(key)
|
||||
}
|
||||
|
||||
// Header returns request header item string by a given string.
|
||||
// if non-existed, return empty string.
|
||||
func (input *BeegoInput) Header(key string) string {
|
||||
return input.Context.Request.Header.Get(key)
|
||||
}
|
||||
|
||||
// Cookie returns request cookie item string by a given key.
|
||||
// if non-existed, return empty string.
|
||||
func (input *BeegoInput) Cookie(key string) string {
|
||||
ck, err := input.Context.Request.Cookie(key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return ck.Value
|
||||
}
|
||||
|
||||
// Session returns current session item value by a given key.
|
||||
// if non-existed, return nil.
|
||||
func (input *BeegoInput) Session(key interface{}) interface{} {
|
||||
return input.CruSession.Get(key)
|
||||
}
|
||||
|
||||
// CopyBody returns the raw request body data as bytes.
|
||||
func (input *BeegoInput) CopyBody(MaxMemory int64) []byte {
|
||||
if input.Context.Request.Body == nil {
|
||||
return []byte{}
|
||||
}
|
||||
safe := &io.LimitedReader{R: input.Context.Request.Body, N: MaxMemory}
|
||||
requestbody, _ := ioutil.ReadAll(safe)
|
||||
input.Context.Request.Body.Close()
|
||||
bf := bytes.NewBuffer(requestbody)
|
||||
input.Context.Request.Body = ioutil.NopCloser(bf)
|
||||
input.RequestBody = requestbody
|
||||
return requestbody
|
||||
}
|
||||
|
||||
// Data return the implicit data in the input
|
||||
func (input *BeegoInput) Data() map[interface{}]interface{} {
|
||||
if input.data == nil {
|
||||
input.data = make(map[interface{}]interface{})
|
||||
}
|
||||
return input.data
|
||||
}
|
||||
|
||||
// GetData returns the stored data in this context.
|
||||
func (input *BeegoInput) GetData(key interface{}) interface{} {
|
||||
if v, ok := input.data[key]; ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetData stores data with given key in this context.
|
||||
// This data are only available in this context.
|
||||
func (input *BeegoInput) SetData(key, val interface{}) {
|
||||
if input.data == nil {
|
||||
input.data = make(map[interface{}]interface{})
|
||||
}
|
||||
input.data[key] = val
|
||||
}
|
||||
|
||||
// ParseFormOrMulitForm parseForm or parseMultiForm based on Content-type
|
||||
func (input *BeegoInput) ParseFormOrMulitForm(maxMemory int64) error {
|
||||
// Parse the body depending on the content type.
|
||||
if strings.Contains(input.Header("Content-Type"), "multipart/form-data") {
|
||||
if err := input.Context.Request.ParseMultipartForm(maxMemory); err != nil {
|
||||
return errors.New("Error parsing request body:" + err.Error())
|
||||
}
|
||||
} else if err := input.Context.Request.ParseForm(); err != nil {
|
||||
return errors.New("Error parsing request body:" + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bind data from request.Form[key] to dest
|
||||
// like /?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie
|
||||
// var id int beegoInput.Bind(&id, "id") id ==123
|
||||
// var isok bool beegoInput.Bind(&isok, "isok") isok ==true
|
||||
// var ft float64 beegoInput.Bind(&ft, "ft") ft ==1.2
|
||||
// ol := make([]int, 0, 2) beegoInput.Bind(&ol, "ol") ol ==[1 2]
|
||||
// ul := make([]string, 0, 2) beegoInput.Bind(&ul, "ul") ul ==[str array]
|
||||
// user struct{Name} beegoInput.Bind(&user, "user") user == {Name:"astaxie"}
|
||||
func (input *BeegoInput) Bind(dest interface{}, key string) error {
|
||||
value := reflect.ValueOf(dest)
|
||||
if value.Kind() != reflect.Ptr {
|
||||
return errors.New("beego: non-pointer passed to Bind: " + key)
|
||||
}
|
||||
value = value.Elem()
|
||||
if !value.CanSet() {
|
||||
return errors.New("beego: non-settable variable passed to Bind: " + key)
|
||||
}
|
||||
typ := value.Type()
|
||||
// Get real type if dest define with interface{}.
|
||||
// e.g var dest interface{} dest=1.0
|
||||
if value.Kind() == reflect.Interface {
|
||||
typ = value.Elem().Type()
|
||||
}
|
||||
rv := input.bind(key, typ)
|
||||
if !rv.IsValid() {
|
||||
return errors.New("beego: reflect value is empty")
|
||||
}
|
||||
value.Set(rv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bind(key string, typ reflect.Type) reflect.Value {
|
||||
if input.Context.Request.Form == nil {
|
||||
input.Context.Request.ParseForm()
|
||||
}
|
||||
rv := reflect.Zero(typ)
|
||||
switch typ.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val := input.Query(key)
|
||||
if len(val) == 0 {
|
||||
return rv
|
||||
}
|
||||
rv = input.bindInt(val, typ)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
val := input.Query(key)
|
||||
if len(val) == 0 {
|
||||
return rv
|
||||
}
|
||||
rv = input.bindUint(val, typ)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
val := input.Query(key)
|
||||
if len(val) == 0 {
|
||||
return rv
|
||||
}
|
||||
rv = input.bindFloat(val, typ)
|
||||
case reflect.String:
|
||||
val := input.Query(key)
|
||||
if len(val) == 0 {
|
||||
return rv
|
||||
}
|
||||
rv = input.bindString(val, typ)
|
||||
case reflect.Bool:
|
||||
val := input.Query(key)
|
||||
if len(val) == 0 {
|
||||
return rv
|
||||
}
|
||||
rv = input.bindBool(val, typ)
|
||||
case reflect.Slice:
|
||||
rv = input.bindSlice(&input.Context.Request.Form, key, typ)
|
||||
case reflect.Struct:
|
||||
rv = input.bindStruct(&input.Context.Request.Form, key, typ)
|
||||
case reflect.Ptr:
|
||||
rv = input.bindPoint(key, typ)
|
||||
case reflect.Map:
|
||||
rv = input.bindMap(&input.Context.Request.Form, key, typ)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindValue(val string, typ reflect.Type) reflect.Value {
|
||||
rv := reflect.Zero(typ)
|
||||
switch typ.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
rv = input.bindInt(val, typ)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
rv = input.bindUint(val, typ)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
rv = input.bindFloat(val, typ)
|
||||
case reflect.String:
|
||||
rv = input.bindString(val, typ)
|
||||
case reflect.Bool:
|
||||
rv = input.bindBool(val, typ)
|
||||
case reflect.Slice:
|
||||
rv = input.bindSlice(&url.Values{"": {val}}, "", typ)
|
||||
case reflect.Struct:
|
||||
rv = input.bindStruct(&url.Values{"": {val}}, "", typ)
|
||||
case reflect.Ptr:
|
||||
rv = input.bindPoint(val, typ)
|
||||
case reflect.Map:
|
||||
rv = input.bindMap(&url.Values{"": {val}}, "", typ)
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindInt(val string, typ reflect.Type) reflect.Value {
|
||||
intValue, err := strconv.ParseInt(val, 10, 64)
|
||||
if err != nil {
|
||||
return reflect.Zero(typ)
|
||||
}
|
||||
pValue := reflect.New(typ)
|
||||
pValue.Elem().SetInt(intValue)
|
||||
return pValue.Elem()
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindUint(val string, typ reflect.Type) reflect.Value {
|
||||
uintValue, err := strconv.ParseUint(val, 10, 64)
|
||||
if err != nil {
|
||||
return reflect.Zero(typ)
|
||||
}
|
||||
pValue := reflect.New(typ)
|
||||
pValue.Elem().SetUint(uintValue)
|
||||
return pValue.Elem()
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindFloat(val string, typ reflect.Type) reflect.Value {
|
||||
floatValue, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
return reflect.Zero(typ)
|
||||
}
|
||||
pValue := reflect.New(typ)
|
||||
pValue.Elem().SetFloat(floatValue)
|
||||
return pValue.Elem()
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindString(val string, typ reflect.Type) reflect.Value {
|
||||
return reflect.ValueOf(val)
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindBool(val string, typ reflect.Type) reflect.Value {
|
||||
val = strings.TrimSpace(strings.ToLower(val))
|
||||
switch val {
|
||||
case "true", "on", "1":
|
||||
return reflect.ValueOf(true)
|
||||
}
|
||||
return reflect.ValueOf(false)
|
||||
}
|
||||
|
||||
type sliceValue struct {
|
||||
index int // Index extracted from brackets. If -1, no index was provided.
|
||||
value reflect.Value // the bound value for this slice element.
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindSlice(params *url.Values, key string, typ reflect.Type) reflect.Value {
|
||||
maxIndex := -1
|
||||
numNoIndex := 0
|
||||
sliceValues := []sliceValue{}
|
||||
for reqKey, vals := range *params {
|
||||
if !strings.HasPrefix(reqKey, key+"[") {
|
||||
continue
|
||||
}
|
||||
// Extract the index, and the index where a sub-key starts. (e.g. field[0].subkey)
|
||||
index := -1
|
||||
leftBracket, rightBracket := len(key), strings.Index(reqKey[len(key):], "]")+len(key)
|
||||
if rightBracket > leftBracket+1 {
|
||||
index, _ = strconv.Atoi(reqKey[leftBracket+1 : rightBracket])
|
||||
}
|
||||
subKeyIndex := rightBracket + 1
|
||||
|
||||
// Handle the indexed case.
|
||||
if index > -1 {
|
||||
if index > maxIndex {
|
||||
maxIndex = index
|
||||
}
|
||||
sliceValues = append(sliceValues, sliceValue{
|
||||
index: index,
|
||||
value: input.bind(reqKey[:subKeyIndex], typ.Elem()),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// It's an un-indexed element. (e.g. element[])
|
||||
numNoIndex += len(vals)
|
||||
for _, val := range vals {
|
||||
// Unindexed values can only be direct-bound.
|
||||
sliceValues = append(sliceValues, sliceValue{
|
||||
index: -1,
|
||||
value: input.bindValue(val, typ.Elem()),
|
||||
})
|
||||
}
|
||||
}
|
||||
resultArray := reflect.MakeSlice(typ, maxIndex+1, maxIndex+1+numNoIndex)
|
||||
for _, sv := range sliceValues {
|
||||
if sv.index != -1 {
|
||||
resultArray.Index(sv.index).Set(sv.value)
|
||||
} else {
|
||||
resultArray = reflect.Append(resultArray, sv.value)
|
||||
}
|
||||
}
|
||||
return resultArray
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindStruct(params *url.Values, key string, typ reflect.Type) reflect.Value {
|
||||
result := reflect.New(typ).Elem()
|
||||
fieldValues := make(map[string]reflect.Value)
|
||||
for reqKey, val := range *params {
|
||||
var fieldName string
|
||||
if strings.HasPrefix(reqKey, key+".") {
|
||||
fieldName = reqKey[len(key)+1:]
|
||||
} else if strings.HasPrefix(reqKey, key+"[") && reqKey[len(reqKey)-1] == ']' {
|
||||
fieldName = reqKey[len(key)+1 : len(reqKey)-1]
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := fieldValues[fieldName]; !ok {
|
||||
// Time to bind this field. Get it and make sure we can set it.
|
||||
fieldValue := result.FieldByName(fieldName)
|
||||
if !fieldValue.IsValid() {
|
||||
continue
|
||||
}
|
||||
if !fieldValue.CanSet() {
|
||||
continue
|
||||
}
|
||||
boundVal := input.bindValue(val[0], fieldValue.Type())
|
||||
fieldValue.Set(boundVal)
|
||||
fieldValues[fieldName] = boundVal
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindPoint(key string, typ reflect.Type) reflect.Value {
|
||||
return input.bind(key, typ.Elem()).Addr()
|
||||
}
|
||||
|
||||
func (input *BeegoInput) bindMap(params *url.Values, key string, typ reflect.Type) reflect.Value {
|
||||
var (
|
||||
result = reflect.MakeMap(typ)
|
||||
keyType = typ.Key()
|
||||
valueType = typ.Elem()
|
||||
)
|
||||
for paramName, values := range *params {
|
||||
if !strings.HasPrefix(paramName, key+"[") || paramName[len(paramName)-1] != ']' {
|
||||
continue
|
||||
}
|
||||
|
||||
key := paramName[len(key)+1 : len(paramName)-1]
|
||||
result.SetMapIndex(input.bindValue(key, keyType), input.bindValue(values[0], valueType))
|
||||
}
|
||||
return result
|
||||
}
|
||||
207
vendor/github.com/fatedier/beego/context/input_test.go
generated
vendored
Normal file
207
vendor/github.com/fatedier/beego/context/input_test.go
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBind(t *testing.T) {
|
||||
type testItem struct {
|
||||
field string
|
||||
empty interface{}
|
||||
want interface{}
|
||||
}
|
||||
type Human struct {
|
||||
ID int
|
||||
Nick string
|
||||
Pwd string
|
||||
Ms bool
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
request string
|
||||
valueGp []testItem
|
||||
}{
|
||||
{"/?p=str", []testItem{{"p", interface{}(""), interface{}("str")}}},
|
||||
|
||||
{"/?p=", []testItem{{"p", "", ""}}},
|
||||
{"/?p=str", []testItem{{"p", "", "str"}}},
|
||||
|
||||
{"/?p=123", []testItem{{"p", 0, 123}}},
|
||||
{"/?p=123", []testItem{{"p", uint(0), uint(123)}}},
|
||||
|
||||
{"/?p=1.0", []testItem{{"p", 0.0, 1.0}}},
|
||||
{"/?p=1", []testItem{{"p", false, true}}},
|
||||
|
||||
{"/?p=true", []testItem{{"p", false, true}}},
|
||||
{"/?p=ON", []testItem{{"p", false, true}}},
|
||||
{"/?p=on", []testItem{{"p", false, true}}},
|
||||
{"/?p=1", []testItem{{"p", false, true}}},
|
||||
{"/?p=2", []testItem{{"p", false, false}}},
|
||||
{"/?p=false", []testItem{{"p", false, false}}},
|
||||
|
||||
{"/?p[a]=1&p[b]=2&p[c]=3", []testItem{{"p", map[string]int{}, map[string]int{"a": 1, "b": 2, "c": 3}}}},
|
||||
{"/?p[a]=v1&p[b]=v2&p[c]=v3", []testItem{{"p", map[string]string{}, map[string]string{"a": "v1", "b": "v2", "c": "v3"}}}},
|
||||
|
||||
{"/?p[]=8&p[]=9&p[]=10", []testItem{{"p", []int{}, []int{8, 9, 10}}}},
|
||||
{"/?p[0]=8&p[1]=9&p[2]=10", []testItem{{"p", []int{}, []int{8, 9, 10}}}},
|
||||
{"/?p[0]=8&p[1]=9&p[2]=10&p[5]=14", []testItem{{"p", []int{}, []int{8, 9, 10, 0, 0, 14}}}},
|
||||
{"/?p[0]=8.0&p[1]=9.0&p[2]=10.0", []testItem{{"p", []float64{}, []float64{8.0, 9.0, 10.0}}}},
|
||||
|
||||
{"/?p[]=10&p[]=9&p[]=8", []testItem{{"p", []string{}, []string{"10", "9", "8"}}}},
|
||||
{"/?p[0]=8&p[1]=9&p[2]=10", []testItem{{"p", []string{}, []string{"8", "9", "10"}}}},
|
||||
|
||||
{"/?p[0]=true&p[1]=false&p[2]=true&p[5]=1&p[6]=ON&p[7]=other", []testItem{{"p", []bool{}, []bool{true, false, true, false, false, true, true, false}}}},
|
||||
|
||||
{"/?human.Nick=astaxie", []testItem{{"human", Human{}, Human{Nick: "astaxie"}}}},
|
||||
{"/?human.ID=888&human.Nick=astaxie&human.Ms=true&human[Pwd]=pass", []testItem{{"human", Human{}, Human{ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass"}}}},
|
||||
{"/?human[0].ID=888&human[0].Nick=astaxie&human[0].Ms=true&human[0][Pwd]=pass01&human[1].ID=999&human[1].Nick=ysqi&human[1].Ms=On&human[1].Pwd=pass02",
|
||||
[]testItem{{"human", []Human{}, []Human{
|
||||
Human{ID: 888, Nick: "astaxie", Ms: true, Pwd: "pass01"},
|
||||
Human{ID: 999, Nick: "ysqi", Ms: true, Pwd: "pass02"},
|
||||
}}}},
|
||||
|
||||
{
|
||||
"/?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&human.Nick=astaxie",
|
||||
[]testItem{
|
||||
{"id", 0, 123},
|
||||
{"isok", false, true},
|
||||
{"ft", 0.0, 1.2},
|
||||
{"ol", []int{}, []int{1, 2}},
|
||||
{"ul", []string{}, []string{"str", "array"}},
|
||||
{"human", Human{}, Human{Nick: "astaxie"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
r, _ := http.NewRequest("GET", c.request, nil)
|
||||
beegoInput := NewInput()
|
||||
beegoInput.Context = NewContext()
|
||||
beegoInput.Context.Reset(httptest.NewRecorder(), r)
|
||||
|
||||
for _, item := range c.valueGp {
|
||||
got := item.empty
|
||||
err := beegoInput.Bind(&got, item.field)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, item.want) {
|
||||
t.Fatalf("Bind %q error,should be:\n%#v \ngot:\n%#v", item.field, item.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubDomain(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "http://www.example.com/?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie", nil)
|
||||
beegoInput := NewInput()
|
||||
beegoInput.Context = NewContext()
|
||||
beegoInput.Context.Reset(httptest.NewRecorder(), r)
|
||||
|
||||
subdomain := beegoInput.SubDomains()
|
||||
if subdomain != "www" {
|
||||
t.Fatal("Subdomain parse error, got" + subdomain)
|
||||
}
|
||||
|
||||
r, _ = http.NewRequest("GET", "http://localhost/", nil)
|
||||
beegoInput.Context.Request = r
|
||||
if beegoInput.SubDomains() != "" {
|
||||
t.Fatal("Subdomain parse error, should be empty, got " + beegoInput.SubDomains())
|
||||
}
|
||||
|
||||
r, _ = http.NewRequest("GET", "http://aa.bb.example.com/", nil)
|
||||
beegoInput.Context.Request = r
|
||||
if beegoInput.SubDomains() != "aa.bb" {
|
||||
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||
}
|
||||
|
||||
/* TODO Fix this
|
||||
r, _ = http.NewRequest("GET", "http://127.0.0.1/", nil)
|
||||
beegoInput.Context.Request = r
|
||||
if beegoInput.SubDomains() != "" {
|
||||
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||
}
|
||||
*/
|
||||
|
||||
r, _ = http.NewRequest("GET", "http://example.com/", nil)
|
||||
beegoInput.Context.Request = r
|
||||
if beegoInput.SubDomains() != "" {
|
||||
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||
}
|
||||
|
||||
r, _ = http.NewRequest("GET", "http://aa.bb.cc.dd.example.com/", nil)
|
||||
beegoInput.Context.Request = r
|
||||
if beegoInput.SubDomains() != "aa.bb.cc.dd" {
|
||||
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||
}
|
||||
}
|
||||
|
||||
func TestParams(t *testing.T) {
|
||||
inp := NewInput()
|
||||
|
||||
inp.SetParam("p1", "val1_ver1")
|
||||
inp.SetParam("p2", "val2_ver1")
|
||||
inp.SetParam("p3", "val3_ver1")
|
||||
if l := inp.ParamsLen(); l != 3 {
|
||||
t.Fatalf("Input.ParamsLen wrong value: %d, expected %d", l, 3)
|
||||
}
|
||||
|
||||
if val := inp.Param("p1"); val != "val1_ver1" {
|
||||
t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver1")
|
||||
}
|
||||
if val := inp.Param("p3"); val != "val3_ver1" {
|
||||
t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val3_ver1")
|
||||
}
|
||||
vals := inp.Params()
|
||||
expected := map[string]string{
|
||||
"p1": "val1_ver1",
|
||||
"p2": "val2_ver1",
|
||||
"p3": "val3_ver1",
|
||||
}
|
||||
if !reflect.DeepEqual(vals, expected) {
|
||||
t.Fatalf("Input.Params wrong value: %s, expected %s", vals, expected)
|
||||
}
|
||||
|
||||
// overwriting existing params
|
||||
inp.SetParam("p1", "val1_ver2")
|
||||
inp.SetParam("p2", "val2_ver2")
|
||||
expected = map[string]string{
|
||||
"p1": "val1_ver2",
|
||||
"p2": "val2_ver2",
|
||||
"p3": "val3_ver1",
|
||||
}
|
||||
vals = inp.Params()
|
||||
if !reflect.DeepEqual(vals, expected) {
|
||||
t.Fatalf("Input.Params wrong value: %s, expected %s", vals, expected)
|
||||
}
|
||||
|
||||
if l := inp.ParamsLen(); l != 3 {
|
||||
t.Fatalf("Input.ParamsLen wrong value: %d, expected %d", l, 3)
|
||||
}
|
||||
|
||||
if val := inp.Param("p1"); val != "val1_ver2" {
|
||||
t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver2")
|
||||
}
|
||||
|
||||
if val := inp.Param("p2"); val != "val2_ver2" {
|
||||
t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver2")
|
||||
}
|
||||
|
||||
}
|
||||
350
vendor/github.com/fatedier/beego/context/output.go
generated
vendored
Normal file
350
vendor/github.com/fatedier/beego/context/output.go
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BeegoOutput does work for sending response header.
|
||||
type BeegoOutput struct {
|
||||
Context *Context
|
||||
Status int
|
||||
EnableGzip bool
|
||||
}
|
||||
|
||||
// NewOutput returns new BeegoOutput.
|
||||
// it contains nothing now.
|
||||
func NewOutput() *BeegoOutput {
|
||||
return &BeegoOutput{}
|
||||
}
|
||||
|
||||
// Reset init BeegoOutput
|
||||
func (output *BeegoOutput) Reset(ctx *Context) {
|
||||
output.Context = ctx
|
||||
output.Status = 0
|
||||
}
|
||||
|
||||
// Header sets response header item string via given key.
|
||||
func (output *BeegoOutput) Header(key, val string) {
|
||||
output.Context.ResponseWriter.Header().Set(key, val)
|
||||
}
|
||||
|
||||
// Body sets response body content.
|
||||
// if EnableGzip, compress content string.
|
||||
// it sends out response body directly.
|
||||
func (output *BeegoOutput) Body(content []byte) error {
|
||||
var encoding string
|
||||
var buf = &bytes.Buffer{}
|
||||
if output.EnableGzip {
|
||||
encoding = ParseEncoding(output.Context.Request)
|
||||
}
|
||||
if b, n, _ := WriteBody(encoding, buf, content); b {
|
||||
output.Header("Content-Encoding", n)
|
||||
output.Header("Content-Length", strconv.Itoa(buf.Len()))
|
||||
} else {
|
||||
output.Header("Content-Length", strconv.Itoa(len(content)))
|
||||
}
|
||||
// Write status code if it has been set manually
|
||||
// Set it to 0 afterwards to prevent "multiple response.WriteHeader calls"
|
||||
if output.Status != 0 {
|
||||
output.Context.ResponseWriter.WriteHeader(output.Status)
|
||||
output.Status = 0
|
||||
} else {
|
||||
output.Context.ResponseWriter.Started = true
|
||||
}
|
||||
io.Copy(output.Context.ResponseWriter, buf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cookie sets cookie value via given key.
|
||||
// others are ordered as cookie's max age time, path,domain, secure and httponly.
|
||||
func (output *BeegoOutput) Cookie(name string, value string, others ...interface{}) {
|
||||
var b bytes.Buffer
|
||||
fmt.Fprintf(&b, "%s=%s", sanitizeName(name), sanitizeValue(value))
|
||||
|
||||
//fix cookie not work in IE
|
||||
if len(others) > 0 {
|
||||
var maxAge int64
|
||||
|
||||
switch v := others[0].(type) {
|
||||
case int:
|
||||
maxAge = int64(v)
|
||||
case int32:
|
||||
maxAge = int64(v)
|
||||
case int64:
|
||||
maxAge = v
|
||||
}
|
||||
|
||||
switch {
|
||||
case maxAge > 0:
|
||||
fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(maxAge)*time.Second).UTC().Format(time.RFC1123), maxAge)
|
||||
case maxAge < 0:
|
||||
fmt.Fprintf(&b, "; Max-Age=0")
|
||||
}
|
||||
}
|
||||
|
||||
// the settings below
|
||||
// Path, Domain, Secure, HttpOnly
|
||||
// can use nil skip set
|
||||
|
||||
// default "/"
|
||||
if len(others) > 1 {
|
||||
if v, ok := others[1].(string); ok && len(v) > 0 {
|
||||
fmt.Fprintf(&b, "; Path=%s", sanitizeValue(v))
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(&b, "; Path=%s", "/")
|
||||
}
|
||||
|
||||
// default empty
|
||||
if len(others) > 2 {
|
||||
if v, ok := others[2].(string); ok && len(v) > 0 {
|
||||
fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(v))
|
||||
}
|
||||
}
|
||||
|
||||
// default empty
|
||||
if len(others) > 3 {
|
||||
var secure bool
|
||||
switch v := others[3].(type) {
|
||||
case bool:
|
||||
secure = v
|
||||
default:
|
||||
if others[3] != nil {
|
||||
secure = true
|
||||
}
|
||||
}
|
||||
if secure {
|
||||
fmt.Fprintf(&b, "; Secure")
|
||||
}
|
||||
}
|
||||
|
||||
// default false. for session cookie default true
|
||||
if len(others) > 4 {
|
||||
if v, ok := others[4].(bool); ok && v {
|
||||
fmt.Fprintf(&b, "; HttpOnly")
|
||||
}
|
||||
}
|
||||
|
||||
output.Context.ResponseWriter.Header().Add("Set-Cookie", b.String())
|
||||
}
|
||||
|
||||
var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
|
||||
|
||||
func sanitizeName(n string) string {
|
||||
return cookieNameSanitizer.Replace(n)
|
||||
}
|
||||
|
||||
var cookieValueSanitizer = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")
|
||||
|
||||
func sanitizeValue(v string) string {
|
||||
return cookieValueSanitizer.Replace(v)
|
||||
}
|
||||
|
||||
// JSON writes json to response body.
|
||||
// if coding is true, it converts utf-8 to \u0000 type.
|
||||
func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, coding bool) error {
|
||||
output.Header("Content-Type", "application/json; charset=utf-8")
|
||||
var content []byte
|
||||
var err error
|
||||
if hasIndent {
|
||||
content, err = json.MarshalIndent(data, "", " ")
|
||||
} else {
|
||||
content, err = json.Marshal(data)
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
if coding {
|
||||
content = []byte(stringsToJSON(string(content)))
|
||||
}
|
||||
return output.Body(content)
|
||||
}
|
||||
|
||||
// JSONP writes jsonp to response body.
|
||||
func (output *BeegoOutput) JSONP(data interface{}, hasIndent bool) error {
|
||||
output.Header("Content-Type", "application/javascript; charset=utf-8")
|
||||
var content []byte
|
||||
var err error
|
||||
if hasIndent {
|
||||
content, err = json.MarshalIndent(data, "", " ")
|
||||
} else {
|
||||
content, err = json.Marshal(data)
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
callback := output.Context.Input.Query("callback")
|
||||
if callback == "" {
|
||||
return errors.New(`"callback" parameter required`)
|
||||
}
|
||||
callback = template.JSEscapeString(callback)
|
||||
callbackContent := bytes.NewBufferString(" if(window." + callback + ")" + callback)
|
||||
callbackContent.WriteString("(")
|
||||
callbackContent.Write(content)
|
||||
callbackContent.WriteString(");\r\n")
|
||||
return output.Body(callbackContent.Bytes())
|
||||
}
|
||||
|
||||
// XML writes xml string to response body.
|
||||
func (output *BeegoOutput) XML(data interface{}, hasIndent bool) error {
|
||||
output.Header("Content-Type", "application/xml; charset=utf-8")
|
||||
var content []byte
|
||||
var err error
|
||||
if hasIndent {
|
||||
content, err = xml.MarshalIndent(data, "", " ")
|
||||
} else {
|
||||
content, err = xml.Marshal(data)
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
|
||||
return err
|
||||
}
|
||||
return output.Body(content)
|
||||
}
|
||||
|
||||
// Download forces response for download file.
|
||||
// it prepares the download response header automatically.
|
||||
func (output *BeegoOutput) Download(file string, filename ...string) {
|
||||
// check get file error, file not found or other error.
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
http.ServeFile(output.Context.ResponseWriter, output.Context.Request, file)
|
||||
return
|
||||
}
|
||||
|
||||
var fName string
|
||||
if len(filename) > 0 && filename[0] != "" {
|
||||
fName = filename[0]
|
||||
} else {
|
||||
fName = filepath.Base(file)
|
||||
}
|
||||
output.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(fName))
|
||||
output.Header("Content-Description", "File Transfer")
|
||||
output.Header("Content-Type", "application/octet-stream")
|
||||
output.Header("Content-Transfer-Encoding", "binary")
|
||||
output.Header("Expires", "0")
|
||||
output.Header("Cache-Control", "must-revalidate")
|
||||
output.Header("Pragma", "public")
|
||||
http.ServeFile(output.Context.ResponseWriter, output.Context.Request, file)
|
||||
}
|
||||
|
||||
// ContentType sets the content type from ext string.
|
||||
// MIME type is given in mime package.
|
||||
func (output *BeegoOutput) ContentType(ext string) {
|
||||
if !strings.HasPrefix(ext, ".") {
|
||||
ext = "." + ext
|
||||
}
|
||||
ctype := mime.TypeByExtension(ext)
|
||||
if ctype != "" {
|
||||
output.Header("Content-Type", ctype)
|
||||
}
|
||||
}
|
||||
|
||||
// SetStatus sets response status code.
|
||||
// It writes response header directly.
|
||||
func (output *BeegoOutput) SetStatus(status int) {
|
||||
output.Status = status
|
||||
}
|
||||
|
||||
// IsCachable returns boolean of this request is cached.
|
||||
// HTTP 304 means cached.
|
||||
func (output *BeegoOutput) IsCachable() bool {
|
||||
return output.Status >= 200 && output.Status < 300 || output.Status == 304
|
||||
}
|
||||
|
||||
// IsEmpty returns boolean of this request is empty.
|
||||
// HTTP 201,204 and 304 means empty.
|
||||
func (output *BeegoOutput) IsEmpty() bool {
|
||||
return output.Status == 201 || output.Status == 204 || output.Status == 304
|
||||
}
|
||||
|
||||
// IsOk returns boolean of this request runs well.
|
||||
// HTTP 200 means ok.
|
||||
func (output *BeegoOutput) IsOk() bool {
|
||||
return output.Status == 200
|
||||
}
|
||||
|
||||
// IsSuccessful returns boolean of this request runs successfully.
|
||||
// HTTP 2xx means ok.
|
||||
func (output *BeegoOutput) IsSuccessful() bool {
|
||||
return output.Status >= 200 && output.Status < 300
|
||||
}
|
||||
|
||||
// IsRedirect returns boolean of this request is redirection header.
|
||||
// HTTP 301,302,307 means redirection.
|
||||
func (output *BeegoOutput) IsRedirect() bool {
|
||||
return output.Status == 301 || output.Status == 302 || output.Status == 303 || output.Status == 307
|
||||
}
|
||||
|
||||
// IsForbidden returns boolean of this request is forbidden.
|
||||
// HTTP 403 means forbidden.
|
||||
func (output *BeegoOutput) IsForbidden() bool {
|
||||
return output.Status == 403
|
||||
}
|
||||
|
||||
// IsNotFound returns boolean of this request is not found.
|
||||
// HTTP 404 means forbidden.
|
||||
func (output *BeegoOutput) IsNotFound() bool {
|
||||
return output.Status == 404
|
||||
}
|
||||
|
||||
// IsClientError returns boolean of this request client sends error data.
|
||||
// HTTP 4xx means forbidden.
|
||||
func (output *BeegoOutput) IsClientError() bool {
|
||||
return output.Status >= 400 && output.Status < 500
|
||||
}
|
||||
|
||||
// IsServerError returns boolean of this server handler errors.
|
||||
// HTTP 5xx means server internal error.
|
||||
func (output *BeegoOutput) IsServerError() bool {
|
||||
return output.Status >= 500 && output.Status < 600
|
||||
}
|
||||
|
||||
func stringsToJSON(str string) string {
|
||||
rs := []rune(str)
|
||||
var jsons bytes.Buffer
|
||||
for _, r := range rs {
|
||||
rint := int(r)
|
||||
if rint < 128 {
|
||||
jsons.WriteRune(r)
|
||||
} else {
|
||||
jsons.WriteString("\\u")
|
||||
jsons.WriteString(strconv.FormatInt(int64(rint), 16))
|
||||
}
|
||||
}
|
||||
return jsons.String()
|
||||
}
|
||||
|
||||
// Session sets session item value with given key.
|
||||
func (output *BeegoOutput) Session(name interface{}, value interface{}) {
|
||||
output.Context.Input.CruSession.Set(name, value)
|
||||
}
|
||||
652
vendor/github.com/fatedier/beego/controller.go
generated
vendored
Normal file
652
vendor/github.com/fatedier/beego/controller.go
generated
vendored
Normal file
@@ -0,0 +1,652 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"html/template"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/astaxie/beego/session"
|
||||
)
|
||||
|
||||
//commonly used mime-types
|
||||
const (
|
||||
applicationJSON = "application/json"
|
||||
applicationXML = "application/xml"
|
||||
textXML = "text/xml"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAbort custom error when user stop request handler manually.
|
||||
ErrAbort = errors.New("User stop run")
|
||||
// GlobalControllerRouter store comments with controller. pkgpath+controller:comments
|
||||
GlobalControllerRouter = make(map[string][]ControllerComments)
|
||||
)
|
||||
|
||||
// ControllerComments store the comment for the controller method
|
||||
type ControllerComments struct {
|
||||
Method string
|
||||
Router string
|
||||
AllowHTTPMethods []string
|
||||
Params []map[string]string
|
||||
}
|
||||
|
||||
// Controller defines some basic http request handler operations, such as
|
||||
// http context, template and view, session and xsrf.
|
||||
type Controller struct {
|
||||
// context data
|
||||
Ctx *context.Context
|
||||
Data map[interface{}]interface{}
|
||||
|
||||
// route controller info
|
||||
controllerName string
|
||||
actionName string
|
||||
methodMapping map[string]func() //method:routertree
|
||||
gotofunc string
|
||||
AppController interface{}
|
||||
|
||||
// template data
|
||||
TplName string
|
||||
ViewPath string
|
||||
Layout string
|
||||
LayoutSections map[string]string // the key is the section name and the value is the template name
|
||||
TplPrefix string
|
||||
TplExt string
|
||||
EnableRender bool
|
||||
|
||||
// xsrf data
|
||||
_xsrfToken string
|
||||
XSRFExpire int
|
||||
EnableXSRF bool
|
||||
|
||||
// session
|
||||
CruSession session.Store
|
||||
}
|
||||
|
||||
// ControllerInterface is an interface to uniform all controller handler.
|
||||
type ControllerInterface interface {
|
||||
Init(ct *context.Context, controllerName, actionName string, app interface{})
|
||||
Prepare()
|
||||
Get()
|
||||
Post()
|
||||
Delete()
|
||||
Put()
|
||||
Head()
|
||||
Patch()
|
||||
Options()
|
||||
Finish()
|
||||
Render() error
|
||||
XSRFToken() string
|
||||
CheckXSRFCookie() bool
|
||||
HandlerFunc(fn string) bool
|
||||
URLMapping()
|
||||
}
|
||||
|
||||
// Init generates default values of controller operations.
|
||||
func (c *Controller) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
|
||||
c.Layout = ""
|
||||
c.TplName = ""
|
||||
c.controllerName = controllerName
|
||||
c.actionName = actionName
|
||||
c.Ctx = ctx
|
||||
c.TplExt = "tpl"
|
||||
c.AppController = app
|
||||
c.EnableRender = true
|
||||
c.EnableXSRF = true
|
||||
c.Data = ctx.Input.Data()
|
||||
c.methodMapping = make(map[string]func())
|
||||
}
|
||||
|
||||
// Prepare runs after Init before request function execution.
|
||||
func (c *Controller) Prepare() {}
|
||||
|
||||
// Finish runs after request function execution.
|
||||
func (c *Controller) Finish() {}
|
||||
|
||||
// Get adds a request function to handle GET request.
|
||||
func (c *Controller) Get() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Post adds a request function to handle POST request.
|
||||
func (c *Controller) Post() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Delete adds a request function to handle DELETE request.
|
||||
func (c *Controller) Delete() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Put adds a request function to handle PUT request.
|
||||
func (c *Controller) Put() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Head adds a request function to handle HEAD request.
|
||||
func (c *Controller) Head() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Patch adds a request function to handle PATCH request.
|
||||
func (c *Controller) Patch() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// Options adds a request function to handle OPTIONS request.
|
||||
func (c *Controller) Options() {
|
||||
http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", 405)
|
||||
}
|
||||
|
||||
// HandlerFunc call function with the name
|
||||
func (c *Controller) HandlerFunc(fnname string) bool {
|
||||
if v, ok := c.methodMapping[fnname]; ok {
|
||||
v()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// URLMapping register the internal Controller router.
|
||||
func (c *Controller) URLMapping() {}
|
||||
|
||||
// Mapping the method to function
|
||||
func (c *Controller) Mapping(method string, fn func()) {
|
||||
c.methodMapping[method] = fn
|
||||
}
|
||||
|
||||
// Render sends the response with rendered template bytes as text/html type.
|
||||
func (c *Controller) Render() error {
|
||||
if !c.EnableRender {
|
||||
return nil
|
||||
}
|
||||
rb, err := c.RenderBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Ctx.ResponseWriter.Header().Get("Content-Type") == "" {
|
||||
c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8")
|
||||
}
|
||||
|
||||
return c.Ctx.Output.Body(rb)
|
||||
}
|
||||
|
||||
// RenderString returns the rendered template string. Do not send out response.
|
||||
func (c *Controller) RenderString() (string, error) {
|
||||
b, e := c.RenderBytes()
|
||||
return string(b), e
|
||||
}
|
||||
|
||||
// RenderBytes returns the bytes of rendered template string. Do not send out response.
|
||||
func (c *Controller) RenderBytes() ([]byte, error) {
|
||||
buf, err := c.renderTemplate()
|
||||
//if the controller has set layout, then first get the tplName's content set the content to the layout
|
||||
if err == nil && c.Layout != "" {
|
||||
c.Data["LayoutContent"] = template.HTML(buf.String())
|
||||
|
||||
if c.LayoutSections != nil {
|
||||
for sectionName, sectionTpl := range c.LayoutSections {
|
||||
if sectionTpl == "" {
|
||||
c.Data[sectionName] = ""
|
||||
continue
|
||||
}
|
||||
buf.Reset()
|
||||
err = ExecuteViewPathTemplate(&buf, sectionTpl, c.viewPath(), c.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Data[sectionName] = template.HTML(buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath() ,c.Data)
|
||||
}
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func (c *Controller) renderTemplate() (bytes.Buffer, error) {
|
||||
var buf bytes.Buffer
|
||||
if c.TplName == "" {
|
||||
c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt
|
||||
}
|
||||
if c.TplPrefix != "" {
|
||||
c.TplName = c.TplPrefix + c.TplName
|
||||
}
|
||||
if BConfig.RunMode == DEV {
|
||||
buildFiles := []string{c.TplName}
|
||||
if c.Layout != "" {
|
||||
buildFiles = append(buildFiles, c.Layout)
|
||||
if c.LayoutSections != nil {
|
||||
for _, sectionTpl := range c.LayoutSections {
|
||||
if sectionTpl == "" {
|
||||
continue
|
||||
}
|
||||
buildFiles = append(buildFiles, sectionTpl)
|
||||
}
|
||||
}
|
||||
}
|
||||
BuildTemplate(c.viewPath() , buildFiles...)
|
||||
}
|
||||
return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data)
|
||||
}
|
||||
|
||||
func (c *Controller) viewPath() string {
|
||||
if c.ViewPath == "" {
|
||||
return BConfig.WebConfig.ViewsPath
|
||||
}
|
||||
return c.ViewPath
|
||||
}
|
||||
|
||||
// Redirect sends the redirection response to url with status code.
|
||||
func (c *Controller) Redirect(url string, code int) {
|
||||
c.Ctx.Redirect(code, url)
|
||||
}
|
||||
|
||||
// Abort stops controller handler and show the error data if code is defined in ErrorMap or code string.
|
||||
func (c *Controller) Abort(code string) {
|
||||
status, err := strconv.Atoi(code)
|
||||
if err != nil {
|
||||
status = 200
|
||||
}
|
||||
c.CustomAbort(status, code)
|
||||
}
|
||||
|
||||
// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
|
||||
func (c *Controller) CustomAbort(status int, body string) {
|
||||
// first panic from ErrorMaps, it is user defined error functions.
|
||||
if _, ok := ErrorMaps[body]; ok {
|
||||
c.Ctx.Output.Status = status
|
||||
panic(body)
|
||||
}
|
||||
// last panic user string
|
||||
c.Ctx.ResponseWriter.WriteHeader(status)
|
||||
c.Ctx.ResponseWriter.Write([]byte(body))
|
||||
panic(ErrAbort)
|
||||
}
|
||||
|
||||
// StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
|
||||
func (c *Controller) StopRun() {
|
||||
panic(ErrAbort)
|
||||
}
|
||||
|
||||
// URLFor does another controller handler in this request function.
|
||||
// it goes to this controller method if endpoint is not clear.
|
||||
func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
|
||||
if len(endpoint) == 0 {
|
||||
return ""
|
||||
}
|
||||
if endpoint[0] == '.' {
|
||||
return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...)
|
||||
}
|
||||
return URLFor(endpoint, values...)
|
||||
}
|
||||
|
||||
// ServeJSON sends a json response with encoding charset.
|
||||
func (c *Controller) ServeJSON(encoding ...bool) {
|
||||
var (
|
||||
hasIndent = true
|
||||
hasEncoding = false
|
||||
)
|
||||
if BConfig.RunMode == PROD {
|
||||
hasIndent = false
|
||||
}
|
||||
if len(encoding) > 0 && encoding[0] == true {
|
||||
hasEncoding = true
|
||||
}
|
||||
c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
|
||||
}
|
||||
|
||||
// ServeJSONP sends a jsonp response.
|
||||
func (c *Controller) ServeJSONP() {
|
||||
hasIndent := true
|
||||
if BConfig.RunMode == PROD {
|
||||
hasIndent = false
|
||||
}
|
||||
c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
|
||||
}
|
||||
|
||||
// ServeXML sends xml response.
|
||||
func (c *Controller) ServeXML() {
|
||||
hasIndent := true
|
||||
if BConfig.RunMode == PROD {
|
||||
hasIndent = false
|
||||
}
|
||||
c.Ctx.Output.XML(c.Data["xml"], hasIndent)
|
||||
}
|
||||
|
||||
// ServeFormatted serve Xml OR Json, depending on the value of the Accept header
|
||||
func (c *Controller) ServeFormatted() {
|
||||
accept := c.Ctx.Input.Header("Accept")
|
||||
switch accept {
|
||||
case applicationJSON:
|
||||
c.ServeJSON()
|
||||
case applicationXML, textXML:
|
||||
c.ServeXML()
|
||||
default:
|
||||
c.ServeJSON()
|
||||
}
|
||||
}
|
||||
|
||||
// Input returns the input data map from POST or PUT request body and query string.
|
||||
func (c *Controller) Input() url.Values {
|
||||
if c.Ctx.Request.Form == nil {
|
||||
c.Ctx.Request.ParseForm()
|
||||
}
|
||||
return c.Ctx.Request.Form
|
||||
}
|
||||
|
||||
// ParseForm maps input data map to obj struct.
|
||||
func (c *Controller) ParseForm(obj interface{}) error {
|
||||
return ParseForm(c.Input(), obj)
|
||||
}
|
||||
|
||||
// GetString returns the input value by key string or the default value while it's present and input is blank
|
||||
func (c *Controller) GetString(key string, def ...string) string {
|
||||
if v := c.Ctx.Input.Query(key); v != "" {
|
||||
return v
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetStrings returns the input string slice by key string or the default value while it's present and input is blank
|
||||
// it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection.
|
||||
func (c *Controller) GetStrings(key string, def ...[]string) []string {
|
||||
var defv []string
|
||||
if len(def) > 0 {
|
||||
defv = def[0]
|
||||
}
|
||||
|
||||
if f := c.Input(); f == nil {
|
||||
return defv
|
||||
} else if vs := f[key]; len(vs) > 0 {
|
||||
return vs
|
||||
}
|
||||
|
||||
return defv
|
||||
}
|
||||
|
||||
// GetInt returns input as an int or the default value while it's present and input is blank
|
||||
func (c *Controller) GetInt(key string, def ...int) (int, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
return strconv.Atoi(strv)
|
||||
}
|
||||
|
||||
// GetInt8 return input as an int8 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetInt8(key string, def ...int8) (int8, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
i64, err := strconv.ParseInt(strv, 10, 8)
|
||||
return int8(i64), err
|
||||
}
|
||||
|
||||
// GetUint8 return input as an uint8 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetUint8(key string, def ...uint8) (uint8, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
u64, err := strconv.ParseUint(strv, 10, 8)
|
||||
return uint8(u64), err
|
||||
}
|
||||
|
||||
// GetInt16 returns input as an int16 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetInt16(key string, def ...int16) (int16, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
i64, err := strconv.ParseInt(strv, 10, 16)
|
||||
return int16(i64), err
|
||||
}
|
||||
|
||||
// GetUint16 returns input as an uint16 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetUint16(key string, def ...uint16) (uint16, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
u64, err := strconv.ParseUint(strv, 10, 16)
|
||||
return uint16(u64), err
|
||||
}
|
||||
|
||||
// GetInt32 returns input as an int32 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetInt32(key string, def ...int32) (int32, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
i64, err := strconv.ParseInt(strv, 10, 32)
|
||||
return int32(i64), err
|
||||
}
|
||||
|
||||
// GetUint32 returns input as an uint32 or the default value while it's present and input is blank
|
||||
func (c *Controller) GetUint32(key string, def ...uint32) (uint32, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
u64, err := strconv.ParseUint(strv, 10, 32)
|
||||
return uint32(u64), err
|
||||
}
|
||||
|
||||
// GetInt64 returns input value as int64 or the default value while it's present and input is blank.
|
||||
func (c *Controller) GetInt64(key string, def ...int64) (int64, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
return strconv.ParseInt(strv, 10, 64)
|
||||
}
|
||||
|
||||
// GetUint64 returns input value as uint64 or the default value while it's present and input is blank.
|
||||
func (c *Controller) GetUint64(key string, def ...uint64) (uint64, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
return strconv.ParseUint(strv, 10, 64)
|
||||
}
|
||||
|
||||
// GetBool returns input value as bool or the default value while it's present and input is blank.
|
||||
func (c *Controller) GetBool(key string, def ...bool) (bool, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
return strconv.ParseBool(strv)
|
||||
}
|
||||
|
||||
// GetFloat returns input value as float64 or the default value while it's present and input is blank.
|
||||
func (c *Controller) GetFloat(key string, def ...float64) (float64, error) {
|
||||
strv := c.Ctx.Input.Query(key)
|
||||
if len(strv) == 0 && len(def) > 0 {
|
||||
return def[0], nil
|
||||
}
|
||||
return strconv.ParseFloat(strv, 64)
|
||||
}
|
||||
|
||||
// GetFile returns the file data in file upload field named as key.
|
||||
// it returns the first one of multi-uploaded files.
|
||||
func (c *Controller) GetFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
||||
return c.Ctx.Request.FormFile(key)
|
||||
}
|
||||
|
||||
// GetFiles return multi-upload files
|
||||
// files, err:=c.GetFiles("myfiles")
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusNoContent)
|
||||
// return
|
||||
// }
|
||||
// for i, _ := range files {
|
||||
// //for each fileheader, get a handle to the actual file
|
||||
// file, err := files[i].Open()
|
||||
// defer file.Close()
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// //create destination file making sure the path is writeable.
|
||||
// dst, err := os.Create("upload/" + files[i].Filename)
|
||||
// defer dst.Close()
|
||||
// if err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// //copy the uploaded file to the destination file
|
||||
// if _, err := io.Copy(dst, file); err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
func (c *Controller) GetFiles(key string) ([]*multipart.FileHeader, error) {
|
||||
if files, ok := c.Ctx.Request.MultipartForm.File[key]; ok {
|
||||
return files, nil
|
||||
}
|
||||
return nil, http.ErrMissingFile
|
||||
}
|
||||
|
||||
// SaveToFile saves uploaded file to new path.
|
||||
// it only operates the first one of mutil-upload form file field.
|
||||
func (c *Controller) SaveToFile(fromfile, tofile string) error {
|
||||
file, _, err := c.Ctx.Request.FormFile(fromfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
io.Copy(f, file)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartSession starts session and load old session data info this controller.
|
||||
func (c *Controller) StartSession() session.Store {
|
||||
if c.CruSession == nil {
|
||||
c.CruSession = c.Ctx.Input.CruSession
|
||||
}
|
||||
return c.CruSession
|
||||
}
|
||||
|
||||
// SetSession puts value into session.
|
||||
func (c *Controller) SetSession(name interface{}, value interface{}) {
|
||||
if c.CruSession == nil {
|
||||
c.StartSession()
|
||||
}
|
||||
c.CruSession.Set(name, value)
|
||||
}
|
||||
|
||||
// GetSession gets value from session.
|
||||
func (c *Controller) GetSession(name interface{}) interface{} {
|
||||
if c.CruSession == nil {
|
||||
c.StartSession()
|
||||
}
|
||||
return c.CruSession.Get(name)
|
||||
}
|
||||
|
||||
// DelSession removes value from session.
|
||||
func (c *Controller) DelSession(name interface{}) {
|
||||
if c.CruSession == nil {
|
||||
c.StartSession()
|
||||
}
|
||||
c.CruSession.Delete(name)
|
||||
}
|
||||
|
||||
// SessionRegenerateID regenerates session id for this session.
|
||||
// the session data have no changes.
|
||||
func (c *Controller) SessionRegenerateID() {
|
||||
if c.CruSession != nil {
|
||||
c.CruSession.SessionRelease(c.Ctx.ResponseWriter)
|
||||
}
|
||||
c.CruSession = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||
c.Ctx.Input.CruSession = c.CruSession
|
||||
}
|
||||
|
||||
// DestroySession cleans session data and session cookie.
|
||||
func (c *Controller) DestroySession() {
|
||||
c.Ctx.Input.CruSession.Flush()
|
||||
c.Ctx.Input.CruSession = nil
|
||||
GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||
}
|
||||
|
||||
// IsAjax returns this request is ajax or not.
|
||||
func (c *Controller) IsAjax() bool {
|
||||
return c.Ctx.Input.IsAjax()
|
||||
}
|
||||
|
||||
// GetSecureCookie returns decoded cookie value from encoded browser cookie values.
|
||||
func (c *Controller) GetSecureCookie(Secret, key string) (string, bool) {
|
||||
return c.Ctx.GetSecureCookie(Secret, key)
|
||||
}
|
||||
|
||||
// SetSecureCookie puts value into cookie after encoded the value.
|
||||
func (c *Controller) SetSecureCookie(Secret, name, value string, others ...interface{}) {
|
||||
c.Ctx.SetSecureCookie(Secret, name, value, others...)
|
||||
}
|
||||
|
||||
// XSRFToken creates a CSRF token string and returns.
|
||||
func (c *Controller) XSRFToken() string {
|
||||
if c._xsrfToken == "" {
|
||||
expire := int64(BConfig.WebConfig.XSRFExpire)
|
||||
if c.XSRFExpire > 0 {
|
||||
expire = int64(c.XSRFExpire)
|
||||
}
|
||||
c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKey, expire)
|
||||
}
|
||||
return c._xsrfToken
|
||||
}
|
||||
|
||||
// CheckXSRFCookie checks xsrf token in this request is valid or not.
|
||||
// the token can provided in request header "X-Xsrftoken" and "X-CsrfToken"
|
||||
// or in form field value named as "_xsrf".
|
||||
func (c *Controller) CheckXSRFCookie() bool {
|
||||
if !c.EnableXSRF {
|
||||
return true
|
||||
}
|
||||
return c.Ctx.CheckXSRFCookie()
|
||||
}
|
||||
|
||||
// XSRFFormHTML writes an input field contains xsrf token value.
|
||||
func (c *Controller) XSRFFormHTML() string {
|
||||
return `<input type="hidden" name="_xsrf" value="` +
|
||||
c.XSRFToken() + `" />`
|
||||
}
|
||||
|
||||
// GetControllerAndAction gets the executing controller name and action name.
|
||||
func (c *Controller) GetControllerAndAction() (string, string) {
|
||||
return c.controllerName, c.actionName
|
||||
}
|
||||
181
vendor/github.com/fatedier/beego/controller_test.go
generated
vendored
Normal file
181
vendor/github.com/fatedier/beego/controller_test.go
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func TestGetInt(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", "40")
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetInt("age")
|
||||
if val != 40 {
|
||||
t.Errorf("TestGetInt expect 40,get %T,%v", val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInt8(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", "40")
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetInt8("age")
|
||||
if val != 40 {
|
||||
t.Errorf("TestGetInt8 expect 40,get %T,%v", val, val)
|
||||
}
|
||||
//Output: int8
|
||||
}
|
||||
|
||||
func TestGetInt16(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", "40")
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetInt16("age")
|
||||
if val != 40 {
|
||||
t.Errorf("TestGetInt16 expect 40,get %T,%v", val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInt32(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", "40")
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetInt32("age")
|
||||
if val != 40 {
|
||||
t.Errorf("TestGetInt32 expect 40,get %T,%v", val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInt64(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", "40")
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetInt64("age")
|
||||
if val != 40 {
|
||||
t.Errorf("TestGeetInt64 expect 40,get %T,%v", val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUint8(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", strconv.FormatUint(math.MaxUint8, 10))
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetUint8("age")
|
||||
if val != math.MaxUint8 {
|
||||
t.Errorf("TestGetUint8 expect %v,get %T,%v", math.MaxUint8, val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUint16(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", strconv.FormatUint(math.MaxUint16, 10))
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetUint16("age")
|
||||
if val != math.MaxUint16 {
|
||||
t.Errorf("TestGetUint16 expect %v,get %T,%v", math.MaxUint16, val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUint32(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", strconv.FormatUint(math.MaxUint32, 10))
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetUint32("age")
|
||||
if val != math.MaxUint32 {
|
||||
t.Errorf("TestGetUint32 expect %v,get %T,%v", math.MaxUint32, val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUint64(t *testing.T) {
|
||||
i := context.NewInput()
|
||||
i.SetParam("age", strconv.FormatUint(math.MaxUint64, 10))
|
||||
ctx := &context.Context{Input: i}
|
||||
ctrlr := Controller{Ctx: ctx}
|
||||
val, _ := ctrlr.GetUint64("age")
|
||||
if val != math.MaxUint64 {
|
||||
t.Errorf("TestGetUint64 expect %v,get %T,%v", uint64(math.MaxUint64), val, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdditionalViewPaths(t *testing.T) {
|
||||
dir1 := "_beeTmp"
|
||||
dir2 := "_beeTmp2"
|
||||
defer os.RemoveAll(dir1)
|
||||
defer os.RemoveAll(dir2)
|
||||
|
||||
dir1file := "file1.tpl"
|
||||
dir2file := "file2.tpl"
|
||||
|
||||
genFile := func(dir string, name string, content string) {
|
||||
os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0777)
|
||||
if f, err := os.Create(filepath.Join(dir, name)); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
defer f.Close()
|
||||
f.WriteString(content)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
}
|
||||
genFile(dir1, dir1file, `<div>{{.Content}}</div>`)
|
||||
genFile(dir2, dir2file, `<html>{{.Content}}</html>`)
|
||||
|
||||
AddViewPath(dir1)
|
||||
AddViewPath(dir2)
|
||||
|
||||
ctrl := Controller{
|
||||
TplName: "file1.tpl",
|
||||
ViewPath: dir1,
|
||||
}
|
||||
ctrl.Data = map[interface{}]interface{}{
|
||||
"Content": "value2",
|
||||
}
|
||||
if result, err := ctrl.RenderString(); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
if result != "<div>value2</div>" {
|
||||
t.Fatalf("TestAdditionalViewPaths expect %s got %s", "<div>value2</div>", result)
|
||||
}
|
||||
}
|
||||
|
||||
func() {
|
||||
ctrl.TplName = "file2.tpl"
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Fatal("TestAdditionalViewPaths expected error")
|
||||
}
|
||||
}()
|
||||
ctrl.RenderString();
|
||||
}()
|
||||
|
||||
ctrl.TplName = "file2.tpl"
|
||||
ctrl.ViewPath = dir2
|
||||
ctrl.RenderString();
|
||||
}
|
||||
17
vendor/github.com/fatedier/beego/doc.go
generated
vendored
Normal file
17
vendor/github.com/fatedier/beego/doc.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Package beego provide a MVC framework
|
||||
beego: an open-source, high-performance, modular, full-stack web framework
|
||||
|
||||
It is used for rapid development of RESTful APIs, web apps and backend services in Go.
|
||||
beego is inspired by Tornado, Sinatra and Flask with the added benefit of some Go-specific features such as interfaces and struct embedding.
|
||||
|
||||
package main
|
||||
import "github.com/astaxie/beego"
|
||||
|
||||
func main() {
|
||||
beego.Run()
|
||||
}
|
||||
|
||||
more information: http://beego.me
|
||||
*/
|
||||
package beego
|
||||
452
vendor/github.com/fatedier/beego/error.go
generated
vendored
Normal file
452
vendor/github.com/fatedier/beego/error.go
generated
vendored
Normal file
@@ -0,0 +1,452 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
errorTypeHandler = iota
|
||||
errorTypeController
|
||||
)
|
||||
|
||||
var tpl = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>beego application error</title>
|
||||
<style>
|
||||
html, body, body * {padding: 0; margin: 0;}
|
||||
#header {background:#ffd; border-bottom:solid 2px #A31515; padding: 20px 10px;}
|
||||
#header h2{ }
|
||||
#footer {border-top:solid 1px #aaa; padding: 5px 10px; font-size: 12px; color:green;}
|
||||
#content {padding: 5px;}
|
||||
#content .stack b{ font-size: 13px; color: red;}
|
||||
#content .stack pre{padding-left: 10px;}
|
||||
table {}
|
||||
td.t {text-align: right; padding-right: 5px; color: #888;}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<h2>{{.AppError}}</h2>
|
||||
</div>
|
||||
<div id="content">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="t">Request Method: </td><td>{{.RequestMethod}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="t">Request URL: </td><td>{{.RequestURL}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="t">RemoteAddr: </td><td>{{.RemoteAddr }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="stack">
|
||||
<b>Stack</b>
|
||||
<pre>{{.Stack}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<p>beego {{ .BeegoVersion }} (beego framework)</p>
|
||||
<p>golang version: {{.GoVersion}}</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// render default application error page with error and stack string.
|
||||
func showErr(err interface{}, ctx *context.Context, stack string) {
|
||||
t, _ := template.New("beegoerrortemp").Parse(tpl)
|
||||
data := map[string]string{
|
||||
"AppError": fmt.Sprintf("%s:%v", BConfig.AppName, err),
|
||||
"RequestMethod": ctx.Input.Method(),
|
||||
"RequestURL": ctx.Input.URI(),
|
||||
"RemoteAddr": ctx.Input.IP(),
|
||||
"Stack": stack,
|
||||
"BeegoVersion": VERSION,
|
||||
"GoVersion": runtime.Version(),
|
||||
}
|
||||
if ctx.Output.Status != 0 {
|
||||
ctx.ResponseWriter.WriteHeader(ctx.Output.Status)
|
||||
} else {
|
||||
ctx.ResponseWriter.WriteHeader(500)
|
||||
}
|
||||
t.Execute(ctx.ResponseWriter, data)
|
||||
}
|
||||
|
||||
var errtpl = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>{{.Title}}</title>
|
||||
<style type="text/css">
|
||||
* {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color:#EFEFEF;
|
||||
font: .9em "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||
}
|
||||
|
||||
#wrapper{
|
||||
width:600px;
|
||||
margin:40px auto 0;
|
||||
text-align:center;
|
||||
-moz-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||
-webkit-box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||
box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#wrapper h1{
|
||||
color:#FFF;
|
||||
text-align:center;
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
#wrapper a{
|
||||
display:block;
|
||||
font-size:.9em;
|
||||
padding-top:20px;
|
||||
color:#FFF;
|
||||
text-decoration:none;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#container {
|
||||
width:600px;
|
||||
padding-bottom:15px;
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
|
||||
.navtop{
|
||||
height:40px;
|
||||
background-color:#24B2EB;
|
||||
padding:13px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding:10px 10px 25px;
|
||||
background: #FFFFFF;
|
||||
margin:;
|
||||
color:#333;
|
||||
}
|
||||
|
||||
a.button{
|
||||
color:white;
|
||||
padding:15px 20px;
|
||||
text-shadow:1px 1px 0 #00A5FF;
|
||||
font-weight:bold;
|
||||
text-align:center;
|
||||
border:1px solid #24B2EB;
|
||||
margin:0px 200px;
|
||||
clear:both;
|
||||
background-color: #24B2EB;
|
||||
border-radius:100px;
|
||||
-moz-border-radius:100px;
|
||||
-webkit-border-radius:100px;
|
||||
}
|
||||
|
||||
a.button:hover{
|
||||
text-decoration:none;
|
||||
background-color: #24B2EB;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="container">
|
||||
<div class="navtop">
|
||||
<h1>{{.Title}}</h1>
|
||||
</div>
|
||||
<div id="content">
|
||||
{{.Content}}
|
||||
<a href="/" title="Home" class="button">Go Home</a><br />
|
||||
|
||||
<br>Powered by beego {{.BeegoVersion}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
type errorInfo struct {
|
||||
controllerType reflect.Type
|
||||
handler http.HandlerFunc
|
||||
method string
|
||||
errorType int
|
||||
}
|
||||
|
||||
// ErrorMaps holds map of http handlers for each error string.
|
||||
// there is 10 kinds default error(40x and 50x)
|
||||
var ErrorMaps = make(map[string]*errorInfo, 10)
|
||||
|
||||
// show 401 unauthorized error.
|
||||
func unauthorized(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
401,
|
||||
"<br>The page you have requested can't be authorized."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br>The credentials you supplied are incorrect"+
|
||||
"<br>There are errors in the website address"+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 402 Payment Required
|
||||
func paymentRequired(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
402,
|
||||
"<br>The page you have requested Payment Required."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br>The credentials you supplied are incorrect"+
|
||||
"<br>There are errors in the website address"+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 403 forbidden error.
|
||||
func forbidden(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
403,
|
||||
"<br>The page you have requested is forbidden."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br>Your address may be blocked"+
|
||||
"<br>The site may be disabled"+
|
||||
"<br>You need to log in"+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 404 not found error.
|
||||
func notFound(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
404,
|
||||
"<br>The page you have requested has flown the coop."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br>The page has moved"+
|
||||
"<br>The page no longer exists"+
|
||||
"<br>You were looking for your puppy and got lost"+
|
||||
"<br>You like 404 pages"+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 405 Method Not Allowed
|
||||
func methodNotAllowed(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
405,
|
||||
"<br>The method you have requested Not Allowed."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br>The method specified in the Request-Line is not allowed for the resource identified by the Request-URI"+
|
||||
"<br>The response MUST include an Allow header containing a list of valid methods for the requested resource."+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 500 internal server error.
|
||||
func internalServerError(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
500,
|
||||
"<br>The page you have requested is down right now."+
|
||||
"<br><br><ul>"+
|
||||
"<br>Please try again later and report the error to the website administrator"+
|
||||
"<br></ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 501 Not Implemented.
|
||||
func notImplemented(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
501,
|
||||
"<br>The page you have requested is Not Implemented."+
|
||||
"<br><br><ul>"+
|
||||
"<br>Please try again later and report the error to the website administrator"+
|
||||
"<br></ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 502 Bad Gateway.
|
||||
func badGateway(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
502,
|
||||
"<br>The page you have requested is down right now."+
|
||||
"<br><br><ul>"+
|
||||
"<br>The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request."+
|
||||
"<br>Please try again later and report the error to the website administrator"+
|
||||
"<br></ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 503 service unavailable error.
|
||||
func serviceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
503,
|
||||
"<br>The page you have requested is unavailable."+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br><br>The page is overloaded"+
|
||||
"<br>Please try again later."+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
// show 504 Gateway Timeout.
|
||||
func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
||||
responseError(rw, r,
|
||||
504,
|
||||
"<br>The page you have requested is unavailable"+
|
||||
"<br>Perhaps you are here because:"+
|
||||
"<br><br><ul>"+
|
||||
"<br><br>The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI."+
|
||||
"<br>Please try again later."+
|
||||
"</ul>",
|
||||
)
|
||||
}
|
||||
|
||||
func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
|
||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||
data := map[string]interface{}{
|
||||
"Title": http.StatusText(errCode),
|
||||
"BeegoVersion": VERSION,
|
||||
"Content": template.HTML(errContent),
|
||||
}
|
||||
t.Execute(rw, data)
|
||||
}
|
||||
|
||||
// ErrorHandler registers http.HandlerFunc to each http err code string.
|
||||
// usage:
|
||||
// beego.ErrorHandler("404",NotFound)
|
||||
// beego.ErrorHandler("500",InternalServerError)
|
||||
func ErrorHandler(code string, h http.HandlerFunc) *App {
|
||||
ErrorMaps[code] = &errorInfo{
|
||||
errorType: errorTypeHandler,
|
||||
handler: h,
|
||||
method: code,
|
||||
}
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// ErrorController registers ControllerInterface to each http err code string.
|
||||
// usage:
|
||||
// beego.ErrorController(&controllers.ErrorController{})
|
||||
func ErrorController(c ControllerInterface) *App {
|
||||
reflectVal := reflect.ValueOf(c)
|
||||
rt := reflectVal.Type()
|
||||
ct := reflect.Indirect(reflectVal).Type()
|
||||
for i := 0; i < rt.NumMethod(); i++ {
|
||||
methodName := rt.Method(i).Name
|
||||
if !utils.InSlice(methodName, exceptMethod) && strings.HasPrefix(methodName, "Error") {
|
||||
errName := strings.TrimPrefix(methodName, "Error")
|
||||
ErrorMaps[errName] = &errorInfo{
|
||||
errorType: errorTypeController,
|
||||
controllerType: ct,
|
||||
method: methodName,
|
||||
}
|
||||
}
|
||||
}
|
||||
return BeeApp
|
||||
}
|
||||
|
||||
// Exception Write HttpStatus with errCode and Exec error handler if exist.
|
||||
func Exception(errCode uint64, ctx *context.Context) {
|
||||
exception(strconv.FormatUint(errCode, 10), ctx)
|
||||
}
|
||||
|
||||
// show error string as simple text message.
|
||||
// if error string is empty, show 503 or 500 error as default.
|
||||
func exception(errCode string, ctx *context.Context) {
|
||||
atoi := func(code string) int {
|
||||
v, err := strconv.Atoi(code)
|
||||
if err == nil {
|
||||
return v
|
||||
}
|
||||
if ctx.Output.Status == 0 {
|
||||
return 503
|
||||
}
|
||||
return ctx.Output.Status
|
||||
}
|
||||
|
||||
for _, ec := range []string{errCode, "503", "500"} {
|
||||
if h, ok := ErrorMaps[ec]; ok {
|
||||
executeError(h, ctx, atoi(ec))
|
||||
return
|
||||
}
|
||||
}
|
||||
//if 50x error has been removed from errorMap
|
||||
ctx.ResponseWriter.WriteHeader(atoi(errCode))
|
||||
ctx.WriteString(errCode)
|
||||
}
|
||||
|
||||
func executeError(err *errorInfo, ctx *context.Context, code int) {
|
||||
if err.errorType == errorTypeHandler {
|
||||
ctx.ResponseWriter.WriteHeader(code)
|
||||
err.handler(ctx.ResponseWriter, ctx.Request)
|
||||
return
|
||||
}
|
||||
if err.errorType == errorTypeController {
|
||||
ctx.Output.SetStatus(code)
|
||||
//Invoke the request handler
|
||||
vc := reflect.New(err.controllerType)
|
||||
execController, ok := vc.Interface().(ControllerInterface)
|
||||
if !ok {
|
||||
panic("controller is not ControllerInterface")
|
||||
}
|
||||
//call the controller init function
|
||||
execController.Init(ctx, err.controllerType.Name(), err.method, vc.Interface())
|
||||
|
||||
//call prepare function
|
||||
execController.Prepare()
|
||||
|
||||
execController.URLMapping()
|
||||
|
||||
method := vc.MethodByName(err.method)
|
||||
method.Call([]reflect.Value{})
|
||||
|
||||
//render template
|
||||
if BConfig.WebConfig.AutoRender {
|
||||
if err := execController.Render(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// finish all runrouter. release resource
|
||||
execController.Finish()
|
||||
}
|
||||
}
|
||||
88
vendor/github.com/fatedier/beego/error_test.go
generated
vendored
Normal file
88
vendor/github.com/fatedier/beego/error_test.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2016 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type errorTestController struct {
|
||||
Controller
|
||||
}
|
||||
|
||||
const parseCodeError = "parse code error"
|
||||
|
||||
func (ec *errorTestController) Get() {
|
||||
errorCode, err := ec.GetInt("code")
|
||||
if err != nil {
|
||||
ec.Abort(parseCodeError)
|
||||
}
|
||||
if errorCode != 0 {
|
||||
ec.CustomAbort(errorCode, ec.GetString("code"))
|
||||
}
|
||||
ec.Abort("404")
|
||||
}
|
||||
|
||||
func TestErrorCode_01(t *testing.T) {
|
||||
registerDefaultErrorHandler()
|
||||
for k := range ErrorMaps {
|
||||
r, _ := http.NewRequest("GET", "/error?code="+k, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
handler := NewControllerRegister()
|
||||
handler.Add("/error", &errorTestController{})
|
||||
handler.ServeHTTP(w, r)
|
||||
code, _ := strconv.Atoi(k)
|
||||
if w.Code != code {
|
||||
t.Fail()
|
||||
}
|
||||
if !strings.Contains(string(w.Body.Bytes()), http.StatusText(code)) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorCode_02(t *testing.T) {
|
||||
registerDefaultErrorHandler()
|
||||
r, _ := http.NewRequest("GET", "/error?code=0", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
handler := NewControllerRegister()
|
||||
handler.Add("/error", &errorTestController{})
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Code != 404 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorCode_03(t *testing.T) {
|
||||
registerDefaultErrorHandler()
|
||||
r, _ := http.NewRequest("GET", "/error?code=panic", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
handler := NewControllerRegister()
|
||||
handler.Add("/error", &errorTestController{})
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Code != 200 {
|
||||
t.Fail()
|
||||
}
|
||||
if string(w.Body.Bytes()) != parseCodeError {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/fatedier/beego/filter.go
generated
vendored
Normal file
44
vendor/github.com/fatedier/beego/filter.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import "github.com/astaxie/beego/context"
|
||||
|
||||
// FilterFunc defines a filter function which is invoked before the controller handler is executed.
|
||||
type FilterFunc func(*context.Context)
|
||||
|
||||
// FilterRouter defines a filter operation which is invoked before the controller handler is executed.
|
||||
// It can match the URL against a pattern, and execute a filter function
|
||||
// when a request with a matching URL arrives.
|
||||
type FilterRouter struct {
|
||||
filterFunc FilterFunc
|
||||
tree *Tree
|
||||
pattern string
|
||||
returnOnOutput bool
|
||||
resetParams bool
|
||||
}
|
||||
|
||||
// ValidRouter checks if the current request is matched by this filter.
|
||||
// If the request is matched, the values of the URL parameters defined
|
||||
// by the filter pattern are also returned.
|
||||
func (f *FilterRouter) ValidRouter(url string, ctx *context.Context) bool {
|
||||
isOk := f.tree.Match(url, ctx)
|
||||
if isOk != nil {
|
||||
if b, ok := isOk.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
68
vendor/github.com/fatedier/beego/filter_test.go
generated
vendored
Normal file
68
vendor/github.com/fatedier/beego/filter_test.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
)
|
||||
|
||||
var FilterUser = func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte("i am " + ctx.Input.Param(":last") + ctx.Input.Param(":first")))
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/person/asta/Xie", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler := NewControllerRegister()
|
||||
handler.InsertFilter("/person/:last/:first", BeforeRouter, FilterUser)
|
||||
handler.Add("/person/:last/:first", &TestController{})
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Body.String() != "i am astaXie" {
|
||||
t.Errorf("user define func can't run")
|
||||
}
|
||||
}
|
||||
|
||||
var FilterAdminUser = func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte("i am admin"))
|
||||
}
|
||||
|
||||
// Filter pattern /admin/:all
|
||||
// all url like /admin/ /admin/xie will all get filter
|
||||
|
||||
func TestPatternTwo(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/admin/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler := NewControllerRegister()
|
||||
handler.InsertFilter("/admin/?:all", BeforeRouter, FilterAdminUser)
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Body.String() != "i am admin" {
|
||||
t.Errorf("filter /admin/ can't run")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatternThree(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/admin/astaxie", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler := NewControllerRegister()
|
||||
handler.InsertFilter("/admin/:all", BeforeRouter, FilterAdminUser)
|
||||
handler.ServeHTTP(w, r)
|
||||
if w.Body.String() != "i am admin" {
|
||||
t.Errorf("filter /admin/astaxie can't run")
|
||||
}
|
||||
}
|
||||
110
vendor/github.com/fatedier/beego/flash.go
generated
vendored
Normal file
110
vendor/github.com/fatedier/beego/flash.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FlashData is a tools to maintain data when using across request.
|
||||
type FlashData struct {
|
||||
Data map[string]string
|
||||
}
|
||||
|
||||
// NewFlash return a new empty FlashData struct.
|
||||
func NewFlash() *FlashData {
|
||||
return &FlashData{
|
||||
Data: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// Set message to flash
|
||||
func (fd *FlashData) Set(key string, msg string, args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
fd.Data[key] = msg
|
||||
} else {
|
||||
fd.Data[key] = fmt.Sprintf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Success writes success message to flash.
|
||||
func (fd *FlashData) Success(msg string, args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
fd.Data["success"] = msg
|
||||
} else {
|
||||
fd.Data["success"] = fmt.Sprintf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Notice writes notice message to flash.
|
||||
func (fd *FlashData) Notice(msg string, args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
fd.Data["notice"] = msg
|
||||
} else {
|
||||
fd.Data["notice"] = fmt.Sprintf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warning writes warning message to flash.
|
||||
func (fd *FlashData) Warning(msg string, args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
fd.Data["warning"] = msg
|
||||
} else {
|
||||
fd.Data["warning"] = fmt.Sprintf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error writes error message to flash.
|
||||
func (fd *FlashData) Error(msg string, args ...interface{}) {
|
||||
if len(args) == 0 {
|
||||
fd.Data["error"] = msg
|
||||
} else {
|
||||
fd.Data["error"] = fmt.Sprintf(msg, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Store does the saving operation of flash data.
|
||||
// the data are encoded and saved in cookie.
|
||||
func (fd *FlashData) Store(c *Controller) {
|
||||
c.Data["flash"] = fd.Data
|
||||
var flashValue string
|
||||
for key, value := range fd.Data {
|
||||
flashValue += "\x00" + key + "\x23" + BConfig.WebConfig.FlashSeparator + "\x23" + value + "\x00"
|
||||
}
|
||||
c.Ctx.SetCookie(BConfig.WebConfig.FlashName, url.QueryEscape(flashValue), 0, "/")
|
||||
}
|
||||
|
||||
// ReadFromRequest parsed flash data from encoded values in cookie.
|
||||
func ReadFromRequest(c *Controller) *FlashData {
|
||||
flash := NewFlash()
|
||||
if cookie, err := c.Ctx.Request.Cookie(BConfig.WebConfig.FlashName); err == nil {
|
||||
v, _ := url.QueryUnescape(cookie.Value)
|
||||
vals := strings.Split(v, "\x00")
|
||||
for _, v := range vals {
|
||||
if len(v) > 0 {
|
||||
kv := strings.Split(v, "\x23"+BConfig.WebConfig.FlashSeparator+"\x23")
|
||||
if len(kv) == 2 {
|
||||
flash.Data[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
//read one time then delete it
|
||||
c.Ctx.SetCookie(BConfig.WebConfig.FlashName, "", -1, "/")
|
||||
}
|
||||
c.Data["flash"] = flash.Data
|
||||
return flash
|
||||
}
|
||||
54
vendor/github.com/fatedier/beego/flash_test.go
generated
vendored
Normal file
54
vendor/github.com/fatedier/beego/flash_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestFlashController struct {
|
||||
Controller
|
||||
}
|
||||
|
||||
func (t *TestFlashController) TestWriteFlash() {
|
||||
flash := NewFlash()
|
||||
flash.Notice("TestFlashString")
|
||||
flash.Store(&t.Controller)
|
||||
// we choose to serve json because we don't want to load a template html file
|
||||
t.ServeJSON(true)
|
||||
}
|
||||
|
||||
func TestFlashHeader(t *testing.T) {
|
||||
// create fake GET request
|
||||
r, _ := http.NewRequest("GET", "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
// setup the handler
|
||||
handler := NewControllerRegister()
|
||||
handler.Add("/", &TestFlashController{}, "get:TestWriteFlash")
|
||||
handler.ServeHTTP(w, r)
|
||||
|
||||
// get the Set-Cookie value
|
||||
sc := w.Header().Get("Set-Cookie")
|
||||
// match for the expected header
|
||||
res := strings.Contains(sc, "BEEGO_FLASH=%00notice%23BEEGOFLASH%23TestFlashString%00")
|
||||
// validate the assertion
|
||||
if res != true {
|
||||
t.Errorf("TestFlashHeader() unable to validate flash message")
|
||||
}
|
||||
}
|
||||
28
vendor/github.com/fatedier/beego/grace/conn.go
generated
vendored
Normal file
28
vendor/github.com/fatedier/beego/grace/conn.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package grace
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
type graceConn struct {
|
||||
net.Conn
|
||||
server *Server
|
||||
}
|
||||
|
||||
func (c graceConn) Close() (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
switch x := r.(type) {
|
||||
case string:
|
||||
err = errors.New(x)
|
||||
case error:
|
||||
err = x
|
||||
default:
|
||||
err = errors.New("Unknown panic")
|
||||
}
|
||||
}
|
||||
}()
|
||||
c.server.wg.Done()
|
||||
return c.Conn.Close()
|
||||
}
|
||||
166
vendor/github.com/fatedier/beego/grace/grace.go
generated
vendored
Normal file
166
vendor/github.com/fatedier/beego/grace/grace.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package grace use to hot reload
|
||||
// Description: http://grisha.org/blog/2014/06/03/graceful-restart-in-golang/
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// import(
|
||||
// "log"
|
||||
// "net/http"
|
||||
// "os"
|
||||
//
|
||||
// "github.com/astaxie/beego/grace"
|
||||
// )
|
||||
//
|
||||
// func handler(w http.ResponseWriter, r *http.Request) {
|
||||
// w.Write([]byte("WORLD!"))
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// mux := http.NewServeMux()
|
||||
// mux.HandleFunc("/hello", handler)
|
||||
//
|
||||
// err := grace.ListenAndServe("localhost:8080", mux)
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// }
|
||||
// log.Println("Server on 8080 stopped")
|
||||
// os.Exit(0)
|
||||
// }
|
||||
package grace
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// PreSignal is the position to add filter before signal
|
||||
PreSignal = iota
|
||||
// PostSignal is the position to add filter after signal
|
||||
PostSignal
|
||||
// StateInit represent the application inited
|
||||
StateInit
|
||||
// StateRunning represent the application is running
|
||||
StateRunning
|
||||
// StateShuttingDown represent the application is shutting down
|
||||
StateShuttingDown
|
||||
// StateTerminate represent the application is killed
|
||||
StateTerminate
|
||||
)
|
||||
|
||||
var (
|
||||
regLock *sync.Mutex
|
||||
runningServers map[string]*Server
|
||||
runningServersOrder []string
|
||||
socketPtrOffsetMap map[string]uint
|
||||
runningServersForked bool
|
||||
|
||||
// DefaultReadTimeOut is the HTTP read timeout
|
||||
DefaultReadTimeOut time.Duration
|
||||
// DefaultWriteTimeOut is the HTTP Write timeout
|
||||
DefaultWriteTimeOut time.Duration
|
||||
// DefaultMaxHeaderBytes is the Max HTTP Herder size, default is 0, no limit
|
||||
DefaultMaxHeaderBytes int
|
||||
// DefaultTimeout is the shutdown server's timeout. default is 60s
|
||||
DefaultTimeout = 60 * time.Second
|
||||
|
||||
isChild bool
|
||||
socketOrder string
|
||||
|
||||
hookableSignals []os.Signal
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&isChild, "graceful", false, "listen on open fd (after forking)")
|
||||
flag.StringVar(&socketOrder, "socketorder", "", "previous initialization order - used when more than one listener was started")
|
||||
|
||||
regLock = &sync.Mutex{}
|
||||
runningServers = make(map[string]*Server)
|
||||
runningServersOrder = []string{}
|
||||
socketPtrOffsetMap = make(map[string]uint)
|
||||
|
||||
hookableSignals = []os.Signal{
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
}
|
||||
}
|
||||
|
||||
// NewServer returns a new graceServer.
|
||||
func NewServer(addr string, handler http.Handler) (srv *Server) {
|
||||
regLock.Lock()
|
||||
defer regLock.Unlock()
|
||||
|
||||
if !flag.Parsed() {
|
||||
flag.Parse()
|
||||
}
|
||||
if len(socketOrder) > 0 {
|
||||
for i, addr := range strings.Split(socketOrder, ",") {
|
||||
socketPtrOffsetMap[addr] = uint(i)
|
||||
}
|
||||
} else {
|
||||
socketPtrOffsetMap[addr] = uint(len(runningServersOrder))
|
||||
}
|
||||
|
||||
srv = &Server{
|
||||
wg: sync.WaitGroup{},
|
||||
sigChan: make(chan os.Signal),
|
||||
isChild: isChild,
|
||||
SignalHooks: map[int]map[os.Signal][]func(){
|
||||
PreSignal: {
|
||||
syscall.SIGHUP: {},
|
||||
syscall.SIGINT: {},
|
||||
syscall.SIGTERM: {},
|
||||
},
|
||||
PostSignal: {
|
||||
syscall.SIGHUP: {},
|
||||
syscall.SIGINT: {},
|
||||
syscall.SIGTERM: {},
|
||||
},
|
||||
},
|
||||
state: StateInit,
|
||||
Network: "tcp",
|
||||
}
|
||||
srv.Server = &http.Server{}
|
||||
srv.Server.Addr = addr
|
||||
srv.Server.ReadTimeout = DefaultReadTimeOut
|
||||
srv.Server.WriteTimeout = DefaultWriteTimeOut
|
||||
srv.Server.MaxHeaderBytes = DefaultMaxHeaderBytes
|
||||
srv.Server.Handler = handler
|
||||
|
||||
runningServersOrder = append(runningServersOrder, addr)
|
||||
runningServers[addr] = srv
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListenAndServe refer http.ListenAndServe
|
||||
func ListenAndServe(addr string, handler http.Handler) error {
|
||||
server := NewServer(addr, handler)
|
||||
return server.ListenAndServe()
|
||||
}
|
||||
|
||||
// ListenAndServeTLS refer http.ListenAndServeTLS
|
||||
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error {
|
||||
server := NewServer(addr, handler)
|
||||
return server.ListenAndServeTLS(certFile, keyFile)
|
||||
}
|
||||
62
vendor/github.com/fatedier/beego/grace/listener.go
generated
vendored
Normal file
62
vendor/github.com/fatedier/beego/grace/listener.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package grace
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type graceListener struct {
|
||||
net.Listener
|
||||
stop chan error
|
||||
stopped bool
|
||||
server *Server
|
||||
}
|
||||
|
||||
func newGraceListener(l net.Listener, srv *Server) (el *graceListener) {
|
||||
el = &graceListener{
|
||||
Listener: l,
|
||||
stop: make(chan error),
|
||||
server: srv,
|
||||
}
|
||||
go func() {
|
||||
_ = <-el.stop
|
||||
el.stopped = true
|
||||
el.stop <- el.Listener.Close()
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func (gl *graceListener) Accept() (c net.Conn, err error) {
|
||||
tc, err := gl.Listener.(*net.TCPListener).AcceptTCP()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
||||
|
||||
c = graceConn{
|
||||
Conn: tc,
|
||||
server: gl.server,
|
||||
}
|
||||
|
||||
gl.server.wg.Add(1)
|
||||
return
|
||||
}
|
||||
|
||||
func (gl *graceListener) Close() error {
|
||||
if gl.stopped {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
gl.stop <- nil
|
||||
return <-gl.stop
|
||||
}
|
||||
|
||||
func (gl *graceListener) File() *os.File {
|
||||
// returns a dup(2) - FD_CLOEXEC flag *not* set
|
||||
tl := gl.Listener.(*net.TCPListener)
|
||||
fl, _ := tl.File()
|
||||
return fl
|
||||
}
|
||||
306
vendor/github.com/fatedier/beego/grace/server.go
generated
vendored
Normal file
306
vendor/github.com/fatedier/beego/grace/server.go
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
package grace
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Server embedded http.Server
|
||||
type Server struct {
|
||||
*http.Server
|
||||
GraceListener net.Listener
|
||||
SignalHooks map[int]map[os.Signal][]func()
|
||||
tlsInnerListener *graceListener
|
||||
wg sync.WaitGroup
|
||||
sigChan chan os.Signal
|
||||
isChild bool
|
||||
state uint8
|
||||
Network string
|
||||
}
|
||||
|
||||
// Serve accepts incoming connections on the Listener l,
|
||||
// creating a new service goroutine for each.
|
||||
// The service goroutines read requests and then call srv.Handler to reply to them.
|
||||
func (srv *Server) Serve() (err error) {
|
||||
srv.state = StateRunning
|
||||
err = srv.Server.Serve(srv.GraceListener)
|
||||
log.Println(syscall.Getpid(), "Waiting for connections to finish...")
|
||||
srv.wg.Wait()
|
||||
srv.state = StateTerminate
|
||||
return
|
||||
}
|
||||
|
||||
// ListenAndServe listens on the TCP network address srv.Addr and then calls Serve
|
||||
// to handle requests on incoming connections. If srv.Addr is blank, ":http" is
|
||||
// used.
|
||||
func (srv *Server) ListenAndServe() (err error) {
|
||||
addr := srv.Addr
|
||||
if addr == "" {
|
||||
addr = ":http"
|
||||
}
|
||||
|
||||
go srv.handleSignals()
|
||||
|
||||
l, err := srv.getListener(addr)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
srv.GraceListener = newGraceListener(l, srv)
|
||||
|
||||
if srv.isChild {
|
||||
process, err := os.FindProcess(os.Getppid())
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
err = process.Kill()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(os.Getpid(), srv.Addr)
|
||||
return srv.Serve()
|
||||
}
|
||||
|
||||
// ListenAndServeTLS listens on the TCP network address srv.Addr and then calls
|
||||
// Serve to handle requests on incoming TLS connections.
|
||||
//
|
||||
// Filenames containing a certificate and matching private key for the server must
|
||||
// be provided. If the certificate is signed by a certificate authority, the
|
||||
// certFile should be the concatenation of the server's certificate followed by the
|
||||
// CA's certificate.
|
||||
//
|
||||
// If srv.Addr is blank, ":https" is used.
|
||||
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) {
|
||||
addr := srv.Addr
|
||||
if addr == "" {
|
||||
addr = ":https"
|
||||
}
|
||||
|
||||
if srv.TLSConfig == nil {
|
||||
srv.TLSConfig = &tls.Config{}
|
||||
}
|
||||
if srv.TLSConfig.NextProtos == nil {
|
||||
srv.TLSConfig.NextProtos = []string{"http/1.1"}
|
||||
}
|
||||
|
||||
srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
|
||||
srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
go srv.handleSignals()
|
||||
|
||||
l, err := srv.getListener(addr)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
srv.tlsInnerListener = newGraceListener(l, srv)
|
||||
srv.GraceListener = tls.NewListener(srv.tlsInnerListener, srv.TLSConfig)
|
||||
|
||||
if srv.isChild {
|
||||
process, err := os.FindProcess(os.Getppid())
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
err = process.Kill()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Println(os.Getpid(), srv.Addr)
|
||||
return srv.Serve()
|
||||
}
|
||||
|
||||
// getListener either opens a new socket to listen on, or takes the acceptor socket
|
||||
// it got passed when restarted.
|
||||
func (srv *Server) getListener(laddr string) (l net.Listener, err error) {
|
||||
if srv.isChild {
|
||||
var ptrOffset uint
|
||||
if len(socketPtrOffsetMap) > 0 {
|
||||
ptrOffset = socketPtrOffsetMap[laddr]
|
||||
log.Println("laddr", laddr, "ptr offset", socketPtrOffsetMap[laddr])
|
||||
}
|
||||
|
||||
f := os.NewFile(uintptr(3+ptrOffset), "")
|
||||
l, err = net.FileListener(f)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("net.FileListener error: %v", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
l, err = net.Listen(srv.Network, laddr)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("net.Listen error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// handleSignals listens for os Signals and calls any hooked in function that the
|
||||
// user had registered with the signal.
|
||||
func (srv *Server) handleSignals() {
|
||||
var sig os.Signal
|
||||
|
||||
signal.Notify(
|
||||
srv.sigChan,
|
||||
hookableSignals...,
|
||||
)
|
||||
|
||||
pid := syscall.Getpid()
|
||||
for {
|
||||
sig = <-srv.sigChan
|
||||
srv.signalHooks(PreSignal, sig)
|
||||
switch sig {
|
||||
case syscall.SIGHUP:
|
||||
log.Println(pid, "Received SIGHUP. forking.")
|
||||
err := srv.fork()
|
||||
if err != nil {
|
||||
log.Println("Fork err:", err)
|
||||
}
|
||||
case syscall.SIGINT:
|
||||
log.Println(pid, "Received SIGINT.")
|
||||
srv.shutdown()
|
||||
case syscall.SIGTERM:
|
||||
log.Println(pid, "Received SIGTERM.")
|
||||
srv.shutdown()
|
||||
default:
|
||||
log.Printf("Received %v: nothing i care about...\n", sig)
|
||||
}
|
||||
srv.signalHooks(PostSignal, sig)
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Server) signalHooks(ppFlag int, sig os.Signal) {
|
||||
if _, notSet := srv.SignalHooks[ppFlag][sig]; !notSet {
|
||||
return
|
||||
}
|
||||
for _, f := range srv.SignalHooks[ppFlag][sig] {
|
||||
f()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// shutdown closes the listener so that no new connections are accepted. it also
|
||||
// starts a goroutine that will serverTimeout (stop all running requests) the server
|
||||
// after DefaultTimeout.
|
||||
func (srv *Server) shutdown() {
|
||||
if srv.state != StateRunning {
|
||||
return
|
||||
}
|
||||
|
||||
srv.state = StateShuttingDown
|
||||
if DefaultTimeout >= 0 {
|
||||
go srv.serverTimeout(DefaultTimeout)
|
||||
}
|
||||
err := srv.GraceListener.Close()
|
||||
if err != nil {
|
||||
log.Println(syscall.Getpid(), "Listener.Close() error:", err)
|
||||
} else {
|
||||
log.Println(syscall.Getpid(), srv.GraceListener.Addr(), "Listener closed.")
|
||||
}
|
||||
}
|
||||
|
||||
// serverTimeout forces the server to shutdown in a given timeout - whether it
|
||||
// finished outstanding requests or not. if Read/WriteTimeout are not set or the
|
||||
// max header size is very big a connection could hang
|
||||
func (srv *Server) serverTimeout(d time.Duration) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Println("WaitGroup at 0", r)
|
||||
}
|
||||
}()
|
||||
if srv.state != StateShuttingDown {
|
||||
return
|
||||
}
|
||||
time.Sleep(d)
|
||||
log.Println("[STOP - Hammer Time] Forcefully shutting down parent")
|
||||
for {
|
||||
if srv.state == StateTerminate {
|
||||
break
|
||||
}
|
||||
srv.wg.Done()
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Server) fork() (err error) {
|
||||
regLock.Lock()
|
||||
defer regLock.Unlock()
|
||||
if runningServersForked {
|
||||
return
|
||||
}
|
||||
runningServersForked = true
|
||||
|
||||
var files = make([]*os.File, len(runningServers))
|
||||
var orderArgs = make([]string, len(runningServers))
|
||||
for _, srvPtr := range runningServers {
|
||||
switch srvPtr.GraceListener.(type) {
|
||||
case *graceListener:
|
||||
files[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.GraceListener.(*graceListener).File()
|
||||
default:
|
||||
files[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.tlsInnerListener.File()
|
||||
}
|
||||
orderArgs[socketPtrOffsetMap[srvPtr.Server.Addr]] = srvPtr.Server.Addr
|
||||
}
|
||||
|
||||
log.Println(files)
|
||||
path := os.Args[0]
|
||||
var args []string
|
||||
if len(os.Args) > 1 {
|
||||
for _, arg := range os.Args[1:] {
|
||||
if arg == "-graceful" {
|
||||
break
|
||||
}
|
||||
args = append(args, arg)
|
||||
}
|
||||
}
|
||||
args = append(args, "-graceful")
|
||||
if len(runningServers) > 1 {
|
||||
args = append(args, fmt.Sprintf(`-socketorder=%s`, strings.Join(orderArgs, ",")))
|
||||
log.Println(args)
|
||||
}
|
||||
cmd := exec.Command(path, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.ExtraFiles = files
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("Restart: Failed to launch, error: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// RegisterSignalHook registers a function to be run PreSignal or PostSignal for a given signal.
|
||||
func (srv *Server) RegisterSignalHook(ppFlag int, sig os.Signal, f func()) (err error) {
|
||||
if ppFlag != PreSignal && ppFlag != PostSignal {
|
||||
err = fmt.Errorf("Invalid ppFlag argument. Must be either grace.PreSignal or grace.PostSignal.")
|
||||
return
|
||||
}
|
||||
for _, s := range hookableSignals {
|
||||
if s == sig {
|
||||
srv.SignalHooks[ppFlag][sig] = append(srv.SignalHooks[ppFlag][sig], f)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("Signal '%v' is not supported.", sig)
|
||||
return
|
||||
}
|
||||
101
vendor/github.com/fatedier/beego/hooks.go
generated
vendored
Normal file
101
vendor/github.com/fatedier/beego/hooks.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package beego
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/astaxie/beego/session"
|
||||
)
|
||||
|
||||
//
|
||||
func registerMime() error {
|
||||
for k, v := range mimemaps {
|
||||
mime.AddExtensionType(k, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// register default error http handlers, 404,401,403,500 and 503.
|
||||
func registerDefaultErrorHandler() error {
|
||||
m := map[string]func(http.ResponseWriter, *http.Request){
|
||||
"401": unauthorized,
|
||||
"402": paymentRequired,
|
||||
"403": forbidden,
|
||||
"404": notFound,
|
||||
"405": methodNotAllowed,
|
||||
"500": internalServerError,
|
||||
"501": notImplemented,
|
||||
"502": badGateway,
|
||||
"503": serviceUnavailable,
|
||||
"504": gatewayTimeout,
|
||||
}
|
||||
for e, h := range m {
|
||||
if _, ok := ErrorMaps[e]; !ok {
|
||||
ErrorHandler(e, h)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerSession() error {
|
||||
if BConfig.WebConfig.Session.SessionOn {
|
||||
var err error
|
||||
sessionConfig := AppConfig.String("sessionConfig")
|
||||
conf := new(session.ManagerConfig)
|
||||
if sessionConfig == "" {
|
||||
conf.CookieName = BConfig.WebConfig.Session.SessionName
|
||||
conf.EnableSetCookie = BConfig.WebConfig.Session.SessionAutoSetCookie
|
||||
conf.Gclifetime = BConfig.WebConfig.Session.SessionGCMaxLifetime
|
||||
conf.Secure = BConfig.Listen.EnableHTTPS
|
||||
conf.CookieLifeTime = BConfig.WebConfig.Session.SessionCookieLifeTime
|
||||
conf.ProviderConfig = filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig)
|
||||
conf.DisableHTTPOnly = BConfig.WebConfig.Session.SessionDisableHTTPOnly
|
||||
conf.Domain = BConfig.WebConfig.Session.SessionDomain
|
||||
conf.EnableSidInHttpHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader
|
||||
conf.SessionNameInHttpHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader
|
||||
conf.EnableSidInUrlQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery
|
||||
} else {
|
||||
if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, conf); err != nil {
|
||||
return err
|
||||
}
|
||||
go GlobalSessions.GC()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerTemplate() error {
|
||||
defer lockViewPaths()
|
||||
if err := AddViewPath(BConfig.WebConfig.ViewsPath); err != nil {
|
||||
if BConfig.RunMode == DEV {
|
||||
logs.Warn(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerAdmin() error {
|
||||
if BConfig.Listen.EnableAdmin {
|
||||
go beeAdminApp.Run()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerGzip() error {
|
||||
if BConfig.EnableGzip {
|
||||
context.InitGzip(
|
||||
AppConfig.DefaultInt("gzipMinLength", -1),
|
||||
AppConfig.DefaultInt("gzipCompressLevel", -1),
|
||||
AppConfig.DefaultStrings("includedMethods", []string{"GET"}),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
97
vendor/github.com/fatedier/beego/httplib/README.md
generated
vendored
Normal file
97
vendor/github.com/fatedier/beego/httplib/README.md
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
# httplib
|
||||
httplib is an libs help you to curl remote url.
|
||||
|
||||
# How to use?
|
||||
|
||||
## GET
|
||||
you can use Get to crawl data.
|
||||
|
||||
import "github.com/astaxie/beego/httplib"
|
||||
|
||||
str, err := httplib.Get("http://beego.me/").String()
|
||||
if err != nil {
|
||||
// error
|
||||
}
|
||||
fmt.Println(str)
|
||||
|
||||
## POST
|
||||
POST data to remote url
|
||||
|
||||
req := httplib.Post("http://beego.me/")
|
||||
req.Param("username","astaxie")
|
||||
req.Param("password","123456")
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
// error
|
||||
}
|
||||
fmt.Println(str)
|
||||
|
||||
## Set timeout
|
||||
|
||||
The default timeout is `60` seconds, function prototype:
|
||||
|
||||
SetTimeout(connectTimeout, readWriteTimeout time.Duration)
|
||||
|
||||
Exmaple:
|
||||
|
||||
// GET
|
||||
httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
|
||||
|
||||
// POST
|
||||
httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
|
||||
|
||||
|
||||
## Debug
|
||||
|
||||
If you want to debug the request info, set the debug on
|
||||
|
||||
httplib.Get("http://beego.me/").Debug(true)
|
||||
|
||||
## Set HTTP Basic Auth
|
||||
|
||||
str, err := Get("http://beego.me/").SetBasicAuth("user", "passwd").String()
|
||||
if err != nil {
|
||||
// error
|
||||
}
|
||||
fmt.Println(str)
|
||||
|
||||
## Set HTTPS
|
||||
|
||||
If request url is https, You can set the client support TSL:
|
||||
|
||||
httplib.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
|
||||
More info about the `tls.Config` please visit http://golang.org/pkg/crypto/tls/#Config
|
||||
|
||||
## Set HTTP Version
|
||||
|
||||
some servers need to specify the protocol version of HTTP
|
||||
|
||||
httplib.Get("http://beego.me/").SetProtocolVersion("HTTP/1.1")
|
||||
|
||||
## Set Cookie
|
||||
|
||||
some http request need setcookie. So set it like this:
|
||||
|
||||
cookie := &http.Cookie{}
|
||||
cookie.Name = "username"
|
||||
cookie.Value = "astaxie"
|
||||
httplib.Get("http://beego.me/").SetCookie(cookie)
|
||||
|
||||
## Upload file
|
||||
|
||||
httplib support mutil file upload, use `req.PostFile()`
|
||||
|
||||
req := httplib.Post("http://beego.me/")
|
||||
req.Param("username","astaxie")
|
||||
req.PostFile("uploadfile1", "httplib.pdf")
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
// error
|
||||
}
|
||||
fmt.Println(str)
|
||||
|
||||
|
||||
See godoc for further documentation and examples.
|
||||
|
||||
* [godoc.org/github.com/astaxie/beego/httplib](https://godoc.org/github.com/astaxie/beego/httplib)
|
||||
585
vendor/github.com/fatedier/beego/httplib/httplib.go
generated
vendored
Normal file
585
vendor/github.com/fatedier/beego/httplib/httplib.go
generated
vendored
Normal file
@@ -0,0 +1,585 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package httplib is used as http.Client
|
||||
// Usage:
|
||||
//
|
||||
// import "github.com/astaxie/beego/httplib"
|
||||
//
|
||||
// b := httplib.Post("http://beego.me/")
|
||||
// b.Param("username","astaxie")
|
||||
// b.Param("password","123456")
|
||||
// b.PostFile("uploadfile1", "httplib.pdf")
|
||||
// b.PostFile("uploadfile2", "httplib.txt")
|
||||
// str, err := b.String()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// fmt.Println(str)
|
||||
//
|
||||
// more docs http://beego.me/docs/module/httplib.md
|
||||
package httplib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var defaultSetting = BeegoHTTPSettings{
|
||||
UserAgent: "beegoServer",
|
||||
ConnectTimeout: 60 * time.Second,
|
||||
ReadWriteTimeout: 60 * time.Second,
|
||||
Gzip: true,
|
||||
DumpBody: true,
|
||||
}
|
||||
|
||||
var defaultCookieJar http.CookieJar
|
||||
var settingMutex sync.Mutex
|
||||
|
||||
// createDefaultCookie creates a global cookiejar to store cookies.
|
||||
func createDefaultCookie() {
|
||||
settingMutex.Lock()
|
||||
defer settingMutex.Unlock()
|
||||
defaultCookieJar, _ = cookiejar.New(nil)
|
||||
}
|
||||
|
||||
// SetDefaultSetting Overwrite default settings
|
||||
func SetDefaultSetting(setting BeegoHTTPSettings) {
|
||||
settingMutex.Lock()
|
||||
defer settingMutex.Unlock()
|
||||
defaultSetting = setting
|
||||
}
|
||||
|
||||
// NewBeegoRequest return *BeegoHttpRequest with specific method
|
||||
func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest {
|
||||
var resp http.Response
|
||||
u, err := url.Parse(rawurl)
|
||||
if err != nil {
|
||||
log.Println("Httplib:", err)
|
||||
}
|
||||
req := http.Request{
|
||||
URL: u,
|
||||
Method: method,
|
||||
Header: make(http.Header),
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
}
|
||||
return &BeegoHTTPRequest{
|
||||
url: rawurl,
|
||||
req: &req,
|
||||
params: map[string][]string{},
|
||||
files: map[string]string{},
|
||||
setting: defaultSetting,
|
||||
resp: &resp,
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns *BeegoHttpRequest with GET method.
|
||||
func Get(url string) *BeegoHTTPRequest {
|
||||
return NewBeegoRequest(url, "GET")
|
||||
}
|
||||
|
||||
// Post returns *BeegoHttpRequest with POST method.
|
||||
func Post(url string) *BeegoHTTPRequest {
|
||||
return NewBeegoRequest(url, "POST")
|
||||
}
|
||||
|
||||
// Put returns *BeegoHttpRequest with PUT method.
|
||||
func Put(url string) *BeegoHTTPRequest {
|
||||
return NewBeegoRequest(url, "PUT")
|
||||
}
|
||||
|
||||
// Delete returns *BeegoHttpRequest DELETE method.
|
||||
func Delete(url string) *BeegoHTTPRequest {
|
||||
return NewBeegoRequest(url, "DELETE")
|
||||
}
|
||||
|
||||
// Head returns *BeegoHttpRequest with HEAD method.
|
||||
func Head(url string) *BeegoHTTPRequest {
|
||||
return NewBeegoRequest(url, "HEAD")
|
||||
}
|
||||
|
||||
// BeegoHTTPSettings is the http.Client setting
|
||||
type BeegoHTTPSettings struct {
|
||||
ShowDebug bool
|
||||
UserAgent string
|
||||
ConnectTimeout time.Duration
|
||||
ReadWriteTimeout time.Duration
|
||||
TLSClientConfig *tls.Config
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
Transport http.RoundTripper
|
||||
CheckRedirect func(req *http.Request, via []*http.Request) error
|
||||
EnableCookie bool
|
||||
Gzip bool
|
||||
DumpBody bool
|
||||
Retries int // if set to -1 means will retry forever
|
||||
}
|
||||
|
||||
// BeegoHTTPRequest provides more useful methods for requesting one url than http.Request.
|
||||
type BeegoHTTPRequest struct {
|
||||
url string
|
||||
req *http.Request
|
||||
params map[string][]string
|
||||
files map[string]string
|
||||
setting BeegoHTTPSettings
|
||||
resp *http.Response
|
||||
body []byte
|
||||
dump []byte
|
||||
}
|
||||
|
||||
// GetRequest return the request object
|
||||
func (b *BeegoHTTPRequest) GetRequest() *http.Request {
|
||||
return b.req
|
||||
}
|
||||
|
||||
// Setting Change request settings
|
||||
func (b *BeegoHTTPRequest) Setting(setting BeegoHTTPSettings) *BeegoHTTPRequest {
|
||||
b.setting = setting
|
||||
return b
|
||||
}
|
||||
|
||||
// SetBasicAuth sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password.
|
||||
func (b *BeegoHTTPRequest) SetBasicAuth(username, password string) *BeegoHTTPRequest {
|
||||
b.req.SetBasicAuth(username, password)
|
||||
return b
|
||||
}
|
||||
|
||||
// SetEnableCookie sets enable/disable cookiejar
|
||||
func (b *BeegoHTTPRequest) SetEnableCookie(enable bool) *BeegoHTTPRequest {
|
||||
b.setting.EnableCookie = enable
|
||||
return b
|
||||
}
|
||||
|
||||
// SetUserAgent sets User-Agent header field
|
||||
func (b *BeegoHTTPRequest) SetUserAgent(useragent string) *BeegoHTTPRequest {
|
||||
b.setting.UserAgent = useragent
|
||||
return b
|
||||
}
|
||||
|
||||
// Debug sets show debug or not when executing request.
|
||||
func (b *BeegoHTTPRequest) Debug(isdebug bool) *BeegoHTTPRequest {
|
||||
b.setting.ShowDebug = isdebug
|
||||
return b
|
||||
}
|
||||
|
||||
// Retries sets Retries times.
|
||||
// default is 0 means no retried.
|
||||
// -1 means retried forever.
|
||||
// others means retried times.
|
||||
func (b *BeegoHTTPRequest) Retries(times int) *BeegoHTTPRequest {
|
||||
b.setting.Retries = times
|
||||
return b
|
||||
}
|
||||
|
||||
// DumpBody setting whether need to Dump the Body.
|
||||
func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
|
||||
b.setting.DumpBody = isdump
|
||||
return b
|
||||
}
|
||||
|
||||
// DumpRequest return the DumpRequest
|
||||
func (b *BeegoHTTPRequest) DumpRequest() []byte {
|
||||
return b.dump
|
||||
}
|
||||
|
||||
// SetTimeout sets connect time out and read-write time out for BeegoRequest.
|
||||
func (b *BeegoHTTPRequest) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *BeegoHTTPRequest {
|
||||
b.setting.ConnectTimeout = connectTimeout
|
||||
b.setting.ReadWriteTimeout = readWriteTimeout
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTLSClientConfig sets tls connection configurations if visiting https url.
|
||||
func (b *BeegoHTTPRequest) SetTLSClientConfig(config *tls.Config) *BeegoHTTPRequest {
|
||||
b.setting.TLSClientConfig = config
|
||||
return b
|
||||
}
|
||||
|
||||
// Header add header item string in request.
|
||||
func (b *BeegoHTTPRequest) Header(key, value string) *BeegoHTTPRequest {
|
||||
b.req.Header.Set(key, value)
|
||||
return b
|
||||
}
|
||||
|
||||
// SetHost set the request host
|
||||
func (b *BeegoHTTPRequest) SetHost(host string) *BeegoHTTPRequest {
|
||||
b.req.Host = host
|
||||
return b
|
||||
}
|
||||
|
||||
// SetProtocolVersion Set the protocol version for incoming requests.
|
||||
// Client requests always use HTTP/1.1.
|
||||
func (b *BeegoHTTPRequest) SetProtocolVersion(vers string) *BeegoHTTPRequest {
|
||||
if len(vers) == 0 {
|
||||
vers = "HTTP/1.1"
|
||||
}
|
||||
|
||||
major, minor, ok := http.ParseHTTPVersion(vers)
|
||||
if ok {
|
||||
b.req.Proto = vers
|
||||
b.req.ProtoMajor = major
|
||||
b.req.ProtoMinor = minor
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// SetCookie add cookie into request.
|
||||
func (b *BeegoHTTPRequest) SetCookie(cookie *http.Cookie) *BeegoHTTPRequest {
|
||||
b.req.Header.Add("Cookie", cookie.String())
|
||||
return b
|
||||
}
|
||||
|
||||
// SetTransport set the setting transport
|
||||
func (b *BeegoHTTPRequest) SetTransport(transport http.RoundTripper) *BeegoHTTPRequest {
|
||||
b.setting.Transport = transport
|
||||
return b
|
||||
}
|
||||
|
||||
// SetProxy set the http proxy
|
||||
// example:
|
||||
//
|
||||
// func(req *http.Request) (*url.URL, error) {
|
||||
// u, _ := url.ParseRequestURI("http://127.0.0.1:8118")
|
||||
// return u, nil
|
||||
// }
|
||||
func (b *BeegoHTTPRequest) SetProxy(proxy func(*http.Request) (*url.URL, error)) *BeegoHTTPRequest {
|
||||
b.setting.Proxy = proxy
|
||||
return b
|
||||
}
|
||||
|
||||
// SetCheckRedirect specifies the policy for handling redirects.
|
||||
//
|
||||
// If CheckRedirect is nil, the Client uses its default policy,
|
||||
// which is to stop after 10 consecutive requests.
|
||||
func (b *BeegoHTTPRequest) SetCheckRedirect(redirect func(req *http.Request, via []*http.Request) error) *BeegoHTTPRequest {
|
||||
b.setting.CheckRedirect = redirect
|
||||
return b
|
||||
}
|
||||
|
||||
// Param adds query param in to request.
|
||||
// params build query string as ?key1=value1&key2=value2...
|
||||
func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest {
|
||||
if param, ok := b.params[key]; ok {
|
||||
b.params[key] = append(param, value)
|
||||
} else {
|
||||
b.params[key] = []string{value}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// PostFile add a post file to the request
|
||||
func (b *BeegoHTTPRequest) PostFile(formname, filename string) *BeegoHTTPRequest {
|
||||
b.files[formname] = filename
|
||||
return b
|
||||
}
|
||||
|
||||
// Body adds request raw body.
|
||||
// it supports string and []byte.
|
||||
func (b *BeegoHTTPRequest) Body(data interface{}) *BeegoHTTPRequest {
|
||||
switch t := data.(type) {
|
||||
case string:
|
||||
bf := bytes.NewBufferString(t)
|
||||
b.req.Body = ioutil.NopCloser(bf)
|
||||
b.req.ContentLength = int64(len(t))
|
||||
case []byte:
|
||||
bf := bytes.NewBuffer(t)
|
||||
b.req.Body = ioutil.NopCloser(bf)
|
||||
b.req.ContentLength = int64(len(t))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// JSONBody adds request raw body encoding by JSON.
|
||||
func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) {
|
||||
if b.req.Body == nil && obj != nil {
|
||||
byts, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
b.req.Body = ioutil.NopCloser(bytes.NewReader(byts))
|
||||
b.req.ContentLength = int64(len(byts))
|
||||
b.req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *BeegoHTTPRequest) buildURL(paramBody string) {
|
||||
// build GET url with query string
|
||||
if b.req.Method == "GET" && len(paramBody) > 0 {
|
||||
if strings.Index(b.url, "?") != -1 {
|
||||
b.url += "&" + paramBody
|
||||
} else {
|
||||
b.url = b.url + "?" + paramBody
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// build POST/PUT/PATCH url and body
|
||||
if (b.req.Method == "POST" || b.req.Method == "PUT" || b.req.Method == "PATCH") && b.req.Body == nil {
|
||||
// with files
|
||||
if len(b.files) > 0 {
|
||||
pr, pw := io.Pipe()
|
||||
bodyWriter := multipart.NewWriter(pw)
|
||||
go func() {
|
||||
for formname, filename := range b.files {
|
||||
fileWriter, err := bodyWriter.CreateFormFile(formname, filename)
|
||||
if err != nil {
|
||||
log.Println("Httplib:", err)
|
||||
}
|
||||
fh, err := os.Open(filename)
|
||||
if err != nil {
|
||||
log.Println("Httplib:", err)
|
||||
}
|
||||
//iocopy
|
||||
_, err = io.Copy(fileWriter, fh)
|
||||
fh.Close()
|
||||
if err != nil {
|
||||
log.Println("Httplib:", err)
|
||||
}
|
||||
}
|
||||
for k, v := range b.params {
|
||||
for _, vv := range v {
|
||||
bodyWriter.WriteField(k, vv)
|
||||
}
|
||||
}
|
||||
bodyWriter.Close()
|
||||
pw.Close()
|
||||
}()
|
||||
b.Header("Content-Type", bodyWriter.FormDataContentType())
|
||||
b.req.Body = ioutil.NopCloser(pr)
|
||||
return
|
||||
}
|
||||
|
||||
// with params
|
||||
if len(paramBody) > 0 {
|
||||
b.Header("Content-Type", "application/x-www-form-urlencoded")
|
||||
b.Body(paramBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BeegoHTTPRequest) getResponse() (*http.Response, error) {
|
||||
if b.resp.StatusCode != 0 {
|
||||
return b.resp, nil
|
||||
}
|
||||
resp, err := b.DoRequest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.resp = resp
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DoRequest will do the client.Do
|
||||
func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
|
||||
var paramBody string
|
||||
if len(b.params) > 0 {
|
||||
var buf bytes.Buffer
|
||||
for k, v := range b.params {
|
||||
for _, vv := range v {
|
||||
buf.WriteString(url.QueryEscape(k))
|
||||
buf.WriteByte('=')
|
||||
buf.WriteString(url.QueryEscape(vv))
|
||||
buf.WriteByte('&')
|
||||
}
|
||||
}
|
||||
paramBody = buf.String()
|
||||
paramBody = paramBody[0 : len(paramBody)-1]
|
||||
}
|
||||
|
||||
b.buildURL(paramBody)
|
||||
url, err := url.Parse(b.url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.req.URL = url
|
||||
|
||||
trans := b.setting.Transport
|
||||
|
||||
if trans == nil {
|
||||
// create default transport
|
||||
trans = &http.Transport{
|
||||
TLSClientConfig: b.setting.TLSClientConfig,
|
||||
Proxy: b.setting.Proxy,
|
||||
Dial: TimeoutDialer(b.setting.ConnectTimeout, b.setting.ReadWriteTimeout),
|
||||
MaxIdleConnsPerHost: -1,
|
||||
}
|
||||
} else {
|
||||
// if b.transport is *http.Transport then set the settings.
|
||||
if t, ok := trans.(*http.Transport); ok {
|
||||
if t.TLSClientConfig == nil {
|
||||
t.TLSClientConfig = b.setting.TLSClientConfig
|
||||
}
|
||||
if t.Proxy == nil {
|
||||
t.Proxy = b.setting.Proxy
|
||||
}
|
||||
if t.Dial == nil {
|
||||
t.Dial = TimeoutDialer(b.setting.ConnectTimeout, b.setting.ReadWriteTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var jar http.CookieJar
|
||||
if b.setting.EnableCookie {
|
||||
if defaultCookieJar == nil {
|
||||
createDefaultCookie()
|
||||
}
|
||||
jar = defaultCookieJar
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: trans,
|
||||
Jar: jar,
|
||||
}
|
||||
|
||||
if b.setting.UserAgent != "" && b.req.Header.Get("User-Agent") == "" {
|
||||
b.req.Header.Set("User-Agent", b.setting.UserAgent)
|
||||
}
|
||||
|
||||
if b.setting.CheckRedirect != nil {
|
||||
client.CheckRedirect = b.setting.CheckRedirect
|
||||
}
|
||||
|
||||
if b.setting.ShowDebug {
|
||||
dump, err := httputil.DumpRequest(b.req, b.setting.DumpBody)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
b.dump = dump
|
||||
}
|
||||
// retries default value is 0, it will run once.
|
||||
// retries equal to -1, it will run forever until success
|
||||
// retries is setted, it will retries fixed times.
|
||||
for i := 0; b.setting.Retries == -1 || i <= b.setting.Retries; i++ {
|
||||
resp, err = client.Do(b.req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// String returns the body string in response.
|
||||
// it calls Response inner.
|
||||
func (b *BeegoHTTPRequest) String() (string, error) {
|
||||
data, err := b.Bytes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// Bytes returns the body []byte in response.
|
||||
// it calls Response inner.
|
||||
func (b *BeegoHTTPRequest) Bytes() ([]byte, error) {
|
||||
if b.body != nil {
|
||||
return b.body, nil
|
||||
}
|
||||
resp, err := b.getResponse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.Body == nil {
|
||||
return nil, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if b.setting.Gzip && resp.Header.Get("Content-Encoding") == "gzip" {
|
||||
reader, err := gzip.NewReader(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.body, err = ioutil.ReadAll(reader)
|
||||
} else {
|
||||
b.body, err = ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
return b.body, err
|
||||
}
|
||||
|
||||
// ToFile saves the body data in response to one file.
|
||||
// it calls Response inner.
|
||||
func (b *BeegoHTTPRequest) ToFile(filename string) error {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
resp, err := b.getResponse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Body == nil {
|
||||
return nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
return err
|
||||
}
|
||||
|
||||
// ToJSON returns the map that marshals from the body bytes as json in response .
|
||||
// it calls Response inner.
|
||||
func (b *BeegoHTTPRequest) ToJSON(v interface{}) error {
|
||||
data, err := b.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
// ToXML returns the map that marshals from the body bytes as xml in response .
|
||||
// it calls Response inner.
|
||||
func (b *BeegoHTTPRequest) ToXML(v interface{}) error {
|
||||
data, err := b.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return xml.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
// Response executes request client gets response mannually.
|
||||
func (b *BeegoHTTPRequest) Response() (*http.Response, error) {
|
||||
return b.getResponse()
|
||||
}
|
||||
|
||||
// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field.
|
||||
func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, addr string) (c net.Conn, err error) {
|
||||
return func(netw, addr string) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout(netw, addr, cTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(rwTimeout))
|
||||
return conn, err
|
||||
}
|
||||
}
|
||||
218
vendor/github.com/fatedier/beego/httplib/httplib_test.go
generated
vendored
Normal file
218
vendor/github.com/fatedier/beego/httplib/httplib_test.go
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package httplib
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestResponse(t *testing.T) {
|
||||
req := Get("http://httpbin.org/get")
|
||||
resp, err := req.Response()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(resp)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
req := Get("http://httpbin.org/get")
|
||||
b, err := req.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(b)
|
||||
|
||||
s, err := req.String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(s)
|
||||
|
||||
if string(b) != s {
|
||||
t.Fatal("request data not match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimplePost(t *testing.T) {
|
||||
v := "smallfish"
|
||||
req := Post("http://httpbin.org/post")
|
||||
req.Param("username", v)
|
||||
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
|
||||
n := strings.Index(str, v)
|
||||
if n == -1 {
|
||||
t.Fatal(v + " not found in post")
|
||||
}
|
||||
}
|
||||
|
||||
//func TestPostFile(t *testing.T) {
|
||||
// v := "smallfish"
|
||||
// req := Post("http://httpbin.org/post")
|
||||
// req.Debug(true)
|
||||
// req.Param("username", v)
|
||||
// req.PostFile("uploadfile", "httplib_test.go")
|
||||
|
||||
// str, err := req.String()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// t.Log(str)
|
||||
|
||||
// n := strings.Index(str, v)
|
||||
// if n == -1 {
|
||||
// t.Fatal(v + " not found in post")
|
||||
// }
|
||||
//}
|
||||
|
||||
func TestSimplePut(t *testing.T) {
|
||||
str, err := Put("http://httpbin.org/put").String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
}
|
||||
|
||||
func TestSimpleDelete(t *testing.T) {
|
||||
str, err := Delete("http://httpbin.org/delete").String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
}
|
||||
|
||||
func TestWithCookie(t *testing.T) {
|
||||
v := "smallfish"
|
||||
str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
|
||||
str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
|
||||
n := strings.Index(str, v)
|
||||
if n == -1 {
|
||||
t.Fatal(v + " not found in cookie")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithBasicAuth(t *testing.T) {
|
||||
str, err := Get("http://httpbin.org/basic-auth/user/passwd").SetBasicAuth("user", "passwd").String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
n := strings.Index(str, "authenticated")
|
||||
if n == -1 {
|
||||
t.Fatal("authenticated not found in response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithUserAgent(t *testing.T) {
|
||||
v := "beego"
|
||||
str, err := Get("http://httpbin.org/headers").SetUserAgent(v).String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
|
||||
n := strings.Index(str, v)
|
||||
if n == -1 {
|
||||
t.Fatal(v + " not found in user-agent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithSetting(t *testing.T) {
|
||||
v := "beego"
|
||||
var setting BeegoHTTPSettings
|
||||
setting.EnableCookie = true
|
||||
setting.UserAgent = v
|
||||
setting.Transport = nil
|
||||
setting.ReadWriteTimeout = 5 * time.Second
|
||||
SetDefaultSetting(setting)
|
||||
|
||||
str, err := Get("http://httpbin.org/get").String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
|
||||
n := strings.Index(str, v)
|
||||
if n == -1 {
|
||||
t.Fatal(v + " not found in user-agent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToJson(t *testing.T) {
|
||||
req := Get("http://httpbin.org/ip")
|
||||
resp, err := req.Response()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(resp)
|
||||
|
||||
// httpbin will return http remote addr
|
||||
type IP struct {
|
||||
Origin string `json:"origin"`
|
||||
}
|
||||
var ip IP
|
||||
err = req.ToJSON(&ip)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(ip.Origin)
|
||||
|
||||
if n := strings.Count(ip.Origin, "."); n != 3 {
|
||||
t.Fatal("response is not valid ip")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToFile(t *testing.T) {
|
||||
f := "beego_testfile"
|
||||
req := Get("http://httpbin.org/ip")
|
||||
err := req.ToFile(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f)
|
||||
b, err := ioutil.ReadFile(f)
|
||||
if n := strings.Index(string(b), "origin"); n == -1 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeader(t *testing.T) {
|
||||
req := Get("http://httpbin.org/headers")
|
||||
req.Header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36")
|
||||
str, err := req.String()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(str)
|
||||
}
|
||||
111
vendor/github.com/fatedier/beego/log.go
generated
vendored
Normal file
111
vendor/github.com/fatedier/beego/log.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/logs"
|
||||
)
|
||||
|
||||
// Log levels to control the logging output.
|
||||
const (
|
||||
LevelEmergency = iota
|
||||
LevelAlert
|
||||
LevelCritical
|
||||
LevelError
|
||||
LevelWarning
|
||||
LevelNotice
|
||||
LevelInformational
|
||||
LevelDebug
|
||||
)
|
||||
|
||||
// BeeLogger references the used application logger.
|
||||
var BeeLogger = logs.GetBeeLogger()
|
||||
|
||||
// SetLevel sets the global log level used by the simple logger.
|
||||
func SetLevel(l int) {
|
||||
logs.SetLevel(l)
|
||||
}
|
||||
|
||||
// SetLogFuncCall set the CallDepth, default is 3
|
||||
func SetLogFuncCall(b bool) {
|
||||
logs.SetLogFuncCall(b)
|
||||
}
|
||||
|
||||
// SetLogger sets a new logger.
|
||||
func SetLogger(adaptername string, config string) error {
|
||||
return logs.SetLogger(adaptername, config)
|
||||
}
|
||||
|
||||
// Emergency logs a message at emergency level.
|
||||
func Emergency(v ...interface{}) {
|
||||
logs.Emergency(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Alert logs a message at alert level.
|
||||
func Alert(v ...interface{}) {
|
||||
logs.Alert(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Critical logs a message at critical level.
|
||||
func Critical(v ...interface{}) {
|
||||
logs.Critical(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Error logs a message at error level.
|
||||
func Error(v ...interface{}) {
|
||||
logs.Error(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Warning logs a message at warning level.
|
||||
func Warning(v ...interface{}) {
|
||||
logs.Warning(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Warn compatibility alias for Warning()
|
||||
func Warn(v ...interface{}) {
|
||||
logs.Warn(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Notice logs a message at notice level.
|
||||
func Notice(v ...interface{}) {
|
||||
logs.Notice(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Informational logs a message at info level.
|
||||
func Informational(v ...interface{}) {
|
||||
logs.Informational(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Info compatibility alias for Warning()
|
||||
func Info(v ...interface{}) {
|
||||
logs.Info(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Debug logs a message at debug level.
|
||||
func Debug(v ...interface{}) {
|
||||
logs.Debug(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
// Trace logs a message at trace level.
|
||||
// compatibility alias for Warning()
|
||||
func Trace(v ...interface{}) {
|
||||
logs.Trace(generateFmtStr(len(v)), v...)
|
||||
}
|
||||
|
||||
func generateFmtStr(n int) string {
|
||||
return strings.Repeat("%v ", n)
|
||||
}
|
||||
192
vendor/github.com/fatedier/beego/logs/alils/alils.go
generated
vendored
Normal file
192
vendor/github.com/fatedier/beego/logs/alils/alils.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
package alils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
CacheSize int = 64
|
||||
Delimiter string = "##"
|
||||
)
|
||||
|
||||
type AliLSConfig struct {
|
||||
Project string `json:"project"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
KeyID string `json:"key_id"`
|
||||
KeySecret string `json:"key_secret"`
|
||||
LogStore string `json:"log_store"`
|
||||
Topics []string `json:"topics"`
|
||||
Source string `json:"source"`
|
||||
Level int `json:"level"`
|
||||
FlushWhen int `json:"flush_when"`
|
||||
}
|
||||
|
||||
// aliLSWriter implements LoggerInterface.
|
||||
// it writes messages in keep-live tcp connection.
|
||||
type aliLSWriter struct {
|
||||
store *LogStore
|
||||
group []*LogGroup
|
||||
withMap bool
|
||||
groupMap map[string]*LogGroup
|
||||
lock *sync.Mutex
|
||||
AliLSConfig
|
||||
}
|
||||
|
||||
// 创建提供Logger接口的日志服务
|
||||
func NewAliLS() logs.Logger {
|
||||
alils := new(aliLSWriter)
|
||||
alils.Level = logs.LevelTrace
|
||||
return alils
|
||||
}
|
||||
|
||||
// 读取配置
|
||||
// 初始化必要的数据结构
|
||||
func (c *aliLSWriter) Init(jsonConfig string) (err error) {
|
||||
|
||||
json.Unmarshal([]byte(jsonConfig), c)
|
||||
|
||||
if c.FlushWhen > CacheSize {
|
||||
c.FlushWhen = CacheSize
|
||||
}
|
||||
|
||||
// 初始化Project
|
||||
prj := &LogProject{
|
||||
Name: c.Project,
|
||||
Endpoint: c.Endpoint,
|
||||
AccessKeyId: c.KeyID,
|
||||
AccessKeySecret: c.KeySecret,
|
||||
}
|
||||
|
||||
// 获取logstore
|
||||
c.store, err = prj.GetLogStore(c.LogStore)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建默认Log Group
|
||||
c.group = append(c.group, &LogGroup{
|
||||
Topic: proto.String(""),
|
||||
Source: proto.String(c.Source),
|
||||
Logs: make([]*Log, 0, c.FlushWhen),
|
||||
})
|
||||
|
||||
// 创建其它Log Group
|
||||
c.groupMap = make(map[string]*LogGroup)
|
||||
for _, topic := range c.Topics {
|
||||
|
||||
lg := &LogGroup{
|
||||
Topic: proto.String(topic),
|
||||
Source: proto.String(c.Source),
|
||||
Logs: make([]*Log, 0, c.FlushWhen),
|
||||
}
|
||||
|
||||
c.group = append(c.group, lg)
|
||||
c.groupMap[topic] = lg
|
||||
}
|
||||
|
||||
if len(c.group) == 1 {
|
||||
c.withMap = false
|
||||
} else {
|
||||
c.withMap = true
|
||||
}
|
||||
|
||||
c.lock = &sync.Mutex{}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMsg write message in connection.
|
||||
// if connection is down, try to re-connect.
|
||||
func (c *aliLSWriter) WriteMsg(when time.Time, msg string, level int) (err error) {
|
||||
|
||||
if level > c.Level {
|
||||
return nil
|
||||
}
|
||||
|
||||
var topic string
|
||||
var content string
|
||||
var lg *LogGroup
|
||||
if c.withMap {
|
||||
|
||||
// 解析出Topic,并匹配LogGroup
|
||||
strs := strings.SplitN(msg, Delimiter, 2)
|
||||
if len(strs) == 2 {
|
||||
pos := strings.LastIndex(strs[0], " ")
|
||||
topic = strs[0][pos+1 : len(strs[0])]
|
||||
content = strs[0][0:pos] + strs[1]
|
||||
lg = c.groupMap[topic]
|
||||
}
|
||||
|
||||
// 默认发到空Topic
|
||||
if lg == nil {
|
||||
topic = ""
|
||||
content = msg
|
||||
lg = c.group[0]
|
||||
}
|
||||
} else {
|
||||
topic = ""
|
||||
content = msg
|
||||
lg = c.group[0]
|
||||
}
|
||||
|
||||
// 生成日志
|
||||
c1 := &Log_Content{
|
||||
Key: proto.String("msg"),
|
||||
Value: proto.String(content),
|
||||
}
|
||||
|
||||
l := &Log{
|
||||
Time: proto.Uint32(uint32(when.Unix())), // 填写日志时间
|
||||
Contents: []*Log_Content{
|
||||
c1,
|
||||
},
|
||||
}
|
||||
|
||||
c.lock.Lock()
|
||||
lg.Logs = append(lg.Logs, l)
|
||||
c.lock.Unlock()
|
||||
|
||||
// 满足条件则Flush
|
||||
if len(lg.Logs) >= c.FlushWhen {
|
||||
c.flush(lg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Flush implementing method. empty.
|
||||
func (c *aliLSWriter) Flush() {
|
||||
|
||||
// flush所有group
|
||||
for _, lg := range c.group {
|
||||
c.flush(lg)
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy destroy connection writer and close tcp listener.
|
||||
func (c *aliLSWriter) Destroy() {
|
||||
}
|
||||
|
||||
func (c *aliLSWriter) flush(lg *LogGroup) {
|
||||
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
// 把以上的LogGroup推送到SLS服务器,
|
||||
// SLS服务器会根据该logstore的shard个数自动进行负载均衡。
|
||||
err := c.store.PutLogs(lg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
lg.Logs = make([]*Log, 0, c.FlushWhen)
|
||||
}
|
||||
|
||||
func init() {
|
||||
logs.Register(logs.AdapterAliLS, NewAliLS)
|
||||
}
|
||||
13
vendor/github.com/fatedier/beego/logs/alils/config.go
generated
vendored
Executable file
13
vendor/github.com/fatedier/beego/logs/alils/config.go
generated
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
package alils
|
||||
|
||||
const (
|
||||
version = "0.5.0" // SDK version
|
||||
signatureMethod = "hmac-sha1" // Signature method
|
||||
|
||||
// OffsetNewest stands for the log head offset, i.e. the offset that will be
|
||||
// assigned to the next message that will be produced to the shard.
|
||||
OffsetNewest = "end"
|
||||
// OffsetOldest stands for the oldest offset available on the logstore for a
|
||||
// shard.
|
||||
OffsetOldest = "begin"
|
||||
)
|
||||
984
vendor/github.com/fatedier/beego/logs/alils/log.pb.go
generated
vendored
Executable file
984
vendor/github.com/fatedier/beego/logs/alils/log.pb.go
generated
vendored
Executable file
@@ -0,0 +1,984 @@
|
||||
package alils
|
||||
|
||||
import "github.com/gogo/protobuf/proto"
|
||||
import "fmt"
|
||||
import "math"
|
||||
|
||||
// discarding unused import gogoproto "."
|
||||
|
||||
import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
|
||||
|
||||
import "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Log struct {
|
||||
Time *uint32 `protobuf:"varint,1,req,name=Time" json:"Time,omitempty"`
|
||||
Contents []*Log_Content `protobuf:"bytes,2,rep,name=Contents" json:"Contents,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Log) Reset() { *m = Log{} }
|
||||
func (m *Log) String() string { return proto.CompactTextString(m) }
|
||||
func (*Log) ProtoMessage() {}
|
||||
|
||||
func (m *Log) GetTime() uint32 {
|
||||
if m != nil && m.Time != nil {
|
||||
return *m.Time
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Log) GetContents() []*Log_Content {
|
||||
if m != nil {
|
||||
return m.Contents
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Log_Content struct {
|
||||
Key *string `protobuf:"bytes,1,req,name=Key" json:"Key,omitempty"`
|
||||
Value *string `protobuf:"bytes,2,req,name=Value" json:"Value,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Log_Content) Reset() { *m = Log_Content{} }
|
||||
func (m *Log_Content) String() string { return proto.CompactTextString(m) }
|
||||
func (*Log_Content) ProtoMessage() {}
|
||||
|
||||
func (m *Log_Content) GetKey() string {
|
||||
if m != nil && m.Key != nil {
|
||||
return *m.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Log_Content) GetValue() string {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LogGroup struct {
|
||||
Logs []*Log `protobuf:"bytes,1,rep,name=Logs" json:"Logs,omitempty"`
|
||||
Reserved *string `protobuf:"bytes,2,opt,name=Reserved" json:"Reserved,omitempty"`
|
||||
Topic *string `protobuf:"bytes,3,opt,name=Topic" json:"Topic,omitempty"`
|
||||
Source *string `protobuf:"bytes,4,opt,name=Source" json:"Source,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LogGroup) Reset() { *m = LogGroup{} }
|
||||
func (m *LogGroup) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogGroup) ProtoMessage() {}
|
||||
|
||||
func (m *LogGroup) GetLogs() []*Log {
|
||||
if m != nil {
|
||||
return m.Logs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *LogGroup) GetReserved() string {
|
||||
if m != nil && m.Reserved != nil {
|
||||
return *m.Reserved
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *LogGroup) GetTopic() string {
|
||||
if m != nil && m.Topic != nil {
|
||||
return *m.Topic
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *LogGroup) GetSource() string {
|
||||
if m != nil && m.Source != nil {
|
||||
return *m.Source
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LogGroupList struct {
|
||||
LogGroups []*LogGroup `protobuf:"bytes,1,rep,name=logGroups" json:"logGroups,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LogGroupList) Reset() { *m = LogGroupList{} }
|
||||
func (m *LogGroupList) String() string { return proto.CompactTextString(m) }
|
||||
func (*LogGroupList) ProtoMessage() {}
|
||||
|
||||
func (m *LogGroupList) GetLogGroups() []*LogGroup {
|
||||
if m != nil {
|
||||
return m.LogGroups
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Log) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *Log) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Time == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Time")
|
||||
} else {
|
||||
data[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(*m.Time))
|
||||
}
|
||||
if len(m.Contents) > 0 {
|
||||
for _, msg := range m.Contents {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(data[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Log_Content) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *Log_Content) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Key")
|
||||
} else {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(len(*m.Key)))
|
||||
i += copy(data[i:], *m.Key)
|
||||
}
|
||||
if m.Value == nil {
|
||||
return 0, github_com_gogo_protobuf_proto.NewRequiredNotSetError("Value")
|
||||
} else {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(len(*m.Value)))
|
||||
i += copy(data[i:], *m.Value)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(data[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *LogGroup) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *LogGroup) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Logs) > 0 {
|
||||
for _, msg := range m.Logs {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.Reserved != nil {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(len(*m.Reserved)))
|
||||
i += copy(data[i:], *m.Reserved)
|
||||
}
|
||||
if m.Topic != nil {
|
||||
data[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(len(*m.Topic)))
|
||||
i += copy(data[i:], *m.Topic)
|
||||
}
|
||||
if m.Source != nil {
|
||||
data[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(len(*m.Source)))
|
||||
i += copy(data[i:], *m.Source)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(data[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *LogGroupList) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *LogGroupList) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.LogGroups) > 0 {
|
||||
for _, msg := range m.LogGroups {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintLog(data, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(data[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Log(data []byte, offset int, v uint64) int {
|
||||
data[offset] = uint8(v)
|
||||
data[offset+1] = uint8(v >> 8)
|
||||
data[offset+2] = uint8(v >> 16)
|
||||
data[offset+3] = uint8(v >> 24)
|
||||
data[offset+4] = uint8(v >> 32)
|
||||
data[offset+5] = uint8(v >> 40)
|
||||
data[offset+6] = uint8(v >> 48)
|
||||
data[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Log(data []byte, offset int, v uint32) int {
|
||||
data[offset] = uint8(v)
|
||||
data[offset+1] = uint8(v >> 8)
|
||||
data[offset+2] = uint8(v >> 16)
|
||||
data[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintLog(data []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
data[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
data[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *Log) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Time != nil {
|
||||
n += 1 + sovLog(uint64(*m.Time))
|
||||
}
|
||||
if len(m.Contents) > 0 {
|
||||
for _, e := range m.Contents {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Log_Content) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key != nil {
|
||||
l = len(*m.Key)
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
if m.Value != nil {
|
||||
l = len(*m.Value)
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *LogGroup) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Logs) > 0 {
|
||||
for _, e := range m.Logs {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.Reserved != nil {
|
||||
l = len(*m.Reserved)
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
if m.Topic != nil {
|
||||
l = len(*m.Topic)
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
if m.Source != nil {
|
||||
l = len(*m.Source)
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *LogGroupList) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.LogGroups) > 0 {
|
||||
for _, e := range m.LogGroups {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovLog(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovLog(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozLog(x uint64) (n int) {
|
||||
return sovLog(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Log) Unmarshal(data []byte) error {
|
||||
var hasFields [1]uint64
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Log: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Log: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var v uint32
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
v |= (uint32(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Time = &v
|
||||
hasFields[0] |= uint64(0x00000001)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Contents", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Contents = append(m.Contents, &Log_Content{})
|
||||
if err := m.Contents[len(m.Contents)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLog(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Time")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Log_Content) Unmarshal(data []byte) error {
|
||||
var hasFields [1]uint64
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Content: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Content: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
m.Key = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000001)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
m.Value = &s
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLog(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Key")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Value")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *LogGroup) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LogGroup: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LogGroup: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Logs", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Logs = append(m.Logs, &Log{})
|
||||
if err := m.Logs[len(m.Logs)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Reserved", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
m.Reserved = &s
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Topic", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
m.Topic = &s
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Source", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(data[iNdEx:postIndex])
|
||||
m.Source = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLog(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *LogGroupList) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: LogGroupList: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: LogGroupList: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LogGroups", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.LogGroups = append(m.LogGroups, &LogGroup{})
|
||||
if err := m.LogGroups[len(m.LogGroups)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipLog(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthLog
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, data[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipLog(data []byte) (n int, err error) {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if data[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthLog
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowLog
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipLog(data[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthLog = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowLog = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
39
vendor/github.com/fatedier/beego/logs/alils/log_config.go
generated
vendored
Executable file
39
vendor/github.com/fatedier/beego/logs/alils/log_config.go
generated
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
package alils
|
||||
|
||||
type InputDetail struct {
|
||||
LogType string `json:"logType"`
|
||||
LogPath string `json:"logPath"`
|
||||
FilePattern string `json:"filePattern"`
|
||||
LocalStorage bool `json:"localStorage"`
|
||||
TimeFormat string `json:"timeFormat"`
|
||||
LogBeginRegex string `json:"logBeginRegex"`
|
||||
Regex string `json:"regex"`
|
||||
Keys []string `json:"key"`
|
||||
FilterKeys []string `json:"filterKey"`
|
||||
FilterRegex []string `json:"filterRegex"`
|
||||
TopicFormat string `json:"topicFormat"`
|
||||
}
|
||||
|
||||
type OutputDetail struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
LogStoreName string `json:"logstoreName"`
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
Name string `json:"configName"`
|
||||
InputType string `json:"inputType"`
|
||||
InputDetail InputDetail `json:"inputDetail"`
|
||||
OutputType string `json:"outputType"`
|
||||
OutputDetail OutputDetail `json:"outputDetail"`
|
||||
|
||||
CreateTime uint32
|
||||
LastModifyTime uint32
|
||||
|
||||
project *LogProject
|
||||
}
|
||||
|
||||
// GetAppliedMachineGroup returns applied machine group of this config.
|
||||
func (c *LogConfig) GetAppliedMachineGroup(confName string) (groupNames []string, err error) {
|
||||
groupNames, err = c.project.GetAppliedMachineGroups(c.Name)
|
||||
return
|
||||
}
|
||||
818
vendor/github.com/fatedier/beego/logs/alils/log_project.go
generated
vendored
Executable file
818
vendor/github.com/fatedier/beego/logs/alils/log_project.go
generated
vendored
Executable file
@@ -0,0 +1,818 @@
|
||||
/*
|
||||
Package sls implements the SDK(v0.5.0) of Simple Log Service(abbr. SLS).
|
||||
|
||||
For more description about SLS, please read this article:
|
||||
http://gitlab.alibaba-inc.com/sls/doc.
|
||||
*/
|
||||
package alils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
)
|
||||
|
||||
// Error message in SLS HTTP response.
|
||||
type errorMessage struct {
|
||||
Code string `json:"errorCode"`
|
||||
Message string `json:"errorMessage"`
|
||||
}
|
||||
|
||||
type LogProject struct {
|
||||
Name string // Project name
|
||||
Endpoint string // IP or hostname of SLS endpoint
|
||||
AccessKeyId string
|
||||
AccessKeySecret string
|
||||
}
|
||||
|
||||
// NewLogProject creates a new SLS project.
|
||||
func NewLogProject(name, endpoint, accessKeyId, accessKeySecret string) (p *LogProject, err error) {
|
||||
p = &LogProject{
|
||||
Name: name,
|
||||
Endpoint: endpoint,
|
||||
AccessKeyId: accessKeyId,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// ListLogStore returns all logstore names of project p.
|
||||
func (p *LogProject) ListLogStore() (storeNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores")
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to list logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Count int
|
||||
LogStores []string
|
||||
}
|
||||
body := &Body{}
|
||||
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
storeNames = body.LogStores
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetLogStore returns logstore according by logstore name.
|
||||
func (p *LogProject) GetLogStore(name string) (s *LogStore, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "GET", "/logstores/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
s = &LogStore{}
|
||||
err = json.Unmarshal(buf, s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.project = p
|
||||
return
|
||||
}
|
||||
|
||||
// CreateLogStore creates a new logstore in SLS,
|
||||
// where name is logstore name,
|
||||
// and ttl is time-to-live(in day) of logs,
|
||||
// and shardCnt is the number of shards.
|
||||
func (p *LogProject) CreateLogStore(name string, ttl, shardCnt int) (err error) {
|
||||
|
||||
type Body struct {
|
||||
Name string `json:"logstoreName"`
|
||||
TTL int `json:"ttl"`
|
||||
ShardCount int `json:"shardCount"`
|
||||
}
|
||||
|
||||
store := &Body{
|
||||
Name: name,
|
||||
TTL: ttl,
|
||||
ShardCount: shardCnt,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(store)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/logstores", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteLogStore deletes a logstore according by logstore name.
|
||||
func (p *LogProject) DeleteLogStore(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/logstores/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateLogStore updates a logstore according by logstore name,
|
||||
// obviously we can't modify the logstore name itself.
|
||||
func (p *LogProject) UpdateLogStore(name string, ttl, shardCnt int) (err error) {
|
||||
|
||||
type Body struct {
|
||||
Name string `json:"logstoreName"`
|
||||
TTL int `json:"ttl"`
|
||||
ShardCount int `json:"shardCount"`
|
||||
}
|
||||
|
||||
store := &Body{
|
||||
Name: name,
|
||||
TTL: ttl,
|
||||
ShardCount: shardCnt,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(store)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/logstores", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ListMachineGroup returns machine group name list and the total number of machine groups.
|
||||
// The offset starts from 0 and the size is the max number of machine groups could be returned.
|
||||
func (p *LogProject) ListMachineGroup(offset, size int) (m []string, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
size = 500
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups?offset=%v&size=%v", offset, size)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to list machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
MachineGroups []string
|
||||
Count int
|
||||
Total int
|
||||
}
|
||||
body := &Body{}
|
||||
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
m = body.MachineGroups
|
||||
total = body.Total
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetMachineGroup retruns machine group according by machine group name.
|
||||
func (p *LogProject) GetMachineGroup(name string) (m *MachineGroup, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "GET", "/machinegroups/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get machine group:%v", name)
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
m = &MachineGroup{}
|
||||
err = json.Unmarshal(buf, m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m.project = p
|
||||
return
|
||||
}
|
||||
|
||||
// CreateMachineGroup creates a new machine group in SLS.
|
||||
func (p *LogProject) CreateMachineGroup(m *MachineGroup) (err error) {
|
||||
|
||||
body, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/machinegroups", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMachineGroup updates a machine group.
|
||||
func (p *LogProject) UpdateMachineGroup(m *MachineGroup) (err error) {
|
||||
|
||||
body, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/machinegroups/"+m.Name, h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMachineGroup deletes machine group according machine group name.
|
||||
func (p *LogProject) DeleteMachineGroup(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/machinegroups/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListConfig returns config names list and the total number of configs.
|
||||
// The offset starts from 0 and the size is the max number of configs could be returned.
|
||||
func (p *LogProject) ListConfig(offset, size int) (cfgNames []string, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
size = 100
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/configs?offset=%v&size=%v", offset, size)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Total int
|
||||
Configs []string
|
||||
}
|
||||
body := &Body{}
|
||||
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cfgNames = body.Configs
|
||||
total = body.Total
|
||||
return
|
||||
}
|
||||
|
||||
// GetConfig returns config according by config name.
|
||||
func (p *LogProject) GetConfig(name string) (c *LogConfig, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "GET", "/configs/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
c = &LogConfig{}
|
||||
err = json.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.project = p
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateConfig updates a config.
|
||||
func (p *LogProject) UpdateConfig(c *LogConfig) (err error) {
|
||||
|
||||
body, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "PUT", "/configs/"+c.Name, h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CreateConfig creates a new config in SLS.
|
||||
func (p *LogProject) CreateConfig(c *LogConfig) (err error) {
|
||||
|
||||
body, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "deflate", // TODO: support lz4
|
||||
}
|
||||
|
||||
r, err := request(p, "POST", "/configs", h, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteConfig deletes a config according by config name.
|
||||
func (p *LogProject) DeleteConfig(name string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
r, err := request(p, "DELETE", "/configs/"+name, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(body, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to delete config")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAppliedMachineGroups returns applied machine group names list according config name.
|
||||
func (p *LogProject) GetAppliedMachineGroups(confName string) (groupNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/configs/%v/machinegroups", confName)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get applied machine groups")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Count int
|
||||
Machinegroups []string
|
||||
}
|
||||
|
||||
body := &Body{}
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
groupNames = body.Machinegroups
|
||||
return
|
||||
}
|
||||
|
||||
// GetAppliedConfigs returns applied config names list according machine group name groupName.
|
||||
func (p *LogProject) GetAppliedConfigs(groupName string) (confNames []string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs", groupName)
|
||||
r, err := request(p, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to applied configs")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Cfg struct {
|
||||
Count int `json:"count"`
|
||||
Configs []string `json:"configs"`
|
||||
}
|
||||
|
||||
body := &Cfg{}
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
confNames = body.Configs
|
||||
return
|
||||
}
|
||||
|
||||
// ApplyConfigToMachineGroup applies config to machine group.
|
||||
func (p *LogProject) ApplyConfigToMachineGroup(confName, groupName string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
|
||||
r, err := request(p, "PUT", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to apply config to machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveConfigFromMachineGroup removes config from machine group.
|
||||
func (p *LogProject) RemoveConfigFromMachineGroup(confName, groupName string) (err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/configs/%v", groupName, confName)
|
||||
r, err := request(p, "DELETE", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to remove config from machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Printf("%s\n", dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
269
vendor/github.com/fatedier/beego/logs/alils/log_store.go
generated
vendored
Executable file
269
vendor/github.com/fatedier/beego/logs/alils/log_store.go
generated
vendored
Executable file
@@ -0,0 +1,269 @@
|
||||
package alils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strconv"
|
||||
|
||||
lz4 "github.com/cloudflare/golz4"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type LogStore struct {
|
||||
Name string `json:"logstoreName"`
|
||||
TTL int
|
||||
ShardCount int
|
||||
|
||||
CreateTime uint32
|
||||
LastModifyTime uint32
|
||||
|
||||
project *LogProject
|
||||
}
|
||||
|
||||
type Shard struct {
|
||||
ShardID int `json:"shardID"`
|
||||
}
|
||||
|
||||
// ListShards returns shard id list of this logstore.
|
||||
func (s *LogStore) ListShards() (shardIDs []int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v/shards", s.Name)
|
||||
r, err := request(s.project, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to list logstore")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Println(dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
var shards []*Shard
|
||||
err = json.Unmarshal(buf, &shards)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range shards {
|
||||
shardIDs = append(shardIDs, v.ShardID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PutLogs put logs into logstore.
|
||||
// The callers should transform user logs into LogGroup.
|
||||
func (s *LogStore) PutLogs(lg *LogGroup) (err error) {
|
||||
body, err := proto.Marshal(lg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Compresse body with lz4
|
||||
out := make([]byte, lz4.CompressBound(body))
|
||||
n, err := lz4.Compress(body, out)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-compresstype": "lz4",
|
||||
"x-sls-bodyrawsize": fmt.Sprintf("%v", len(body)),
|
||||
"Content-Type": "application/x-protobuf",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v", s.Name)
|
||||
r, err := request(s.project, "POST", uri, h, out[:n])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to put logs")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Println(dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetCursor gets log cursor of one shard specified by shardId.
|
||||
// The from can be in three form: a) unix timestamp in seccond, b) "begin", c) "end".
|
||||
// For more detail please read: http://gitlab.alibaba-inc.com/sls/doc/blob/master/api/shard.md#logstore
|
||||
func (s *LogStore) GetCursor(shardId int, from string) (cursor string, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=cursor&from=%v",
|
||||
s.Name, shardId, from)
|
||||
|
||||
r, err := request(s.project, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get cursor")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Println(dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
Cursor string
|
||||
}
|
||||
body := &Body{}
|
||||
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cursor = body.Cursor
|
||||
return
|
||||
}
|
||||
|
||||
// GetLogsBytes gets logs binary data from shard specified by shardId according cursor.
|
||||
// The logGroupMaxCount is the max number of logGroup could be returned.
|
||||
// The nextCursor is the next curosr can be used to read logs at next time.
|
||||
func (s *LogStore) GetLogsBytes(shardId int, cursor string,
|
||||
logGroupMaxCount int) (out []byte, nextCursor string, err error) {
|
||||
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
"Accept": "application/x-protobuf",
|
||||
"Accept-Encoding": "lz4",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/logstores/%v/shards/%v?type=logs&cursor=%v&count=%v",
|
||||
s.Name, shardId, cursor, logGroupMaxCount)
|
||||
|
||||
r, err := request(s.project, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to get cursor")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Println(dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := r.Header["X-Sls-Compresstype"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-compresstype' header")
|
||||
return
|
||||
}
|
||||
if v[0] != "lz4" {
|
||||
err = fmt.Errorf("unexpected compress type:%v", v[0])
|
||||
return
|
||||
}
|
||||
|
||||
v, ok = r.Header["X-Sls-Cursor"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-cursor' header")
|
||||
return
|
||||
}
|
||||
nextCursor = v[0]
|
||||
|
||||
v, ok = r.Header["X-Sls-Bodyrawsize"]
|
||||
if !ok || len(v) == 0 {
|
||||
err = fmt.Errorf("can't find 'x-sls-bodyrawsize' header")
|
||||
return
|
||||
}
|
||||
bodyRawSize, err := strconv.Atoi(v[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out = make([]byte, bodyRawSize)
|
||||
err = lz4.Uncompress(buf, out)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// LogsBytesDecode decodes logs binary data retruned by GetLogsBytes API
|
||||
func LogsBytesDecode(data []byte) (gl *LogGroupList, err error) {
|
||||
|
||||
gl = &LogGroupList{}
|
||||
err = proto.Unmarshal(data, gl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetLogs gets logs from shard specified by shardId according cursor.
|
||||
// The logGroupMaxCount is the max number of logGroup could be returned.
|
||||
// The nextCursor is the next curosr can be used to read logs at next time.
|
||||
func (s *LogStore) GetLogs(shardId int, cursor string,
|
||||
logGroupMaxCount int) (gl *LogGroupList, nextCursor string, err error) {
|
||||
|
||||
out, nextCursor, err := s.GetLogsBytes(shardId, cursor, logGroupMaxCount)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
gl, err = LogsBytesDecode(out)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
87
vendor/github.com/fatedier/beego/logs/alils/machine_group.go
generated
vendored
Executable file
87
vendor/github.com/fatedier/beego/logs/alils/machine_group.go
generated
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
package alils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
)
|
||||
|
||||
type MachinGroupAttribute struct {
|
||||
ExternalName string `json:"externalName"`
|
||||
TopicName string `json:"groupTopic"`
|
||||
}
|
||||
|
||||
type MachineGroup struct {
|
||||
Name string `json:"groupName"`
|
||||
Type string `json:"groupType"`
|
||||
MachineIdType string `json:"machineIdentifyType"`
|
||||
MachineIdList []string `json:"machineList"`
|
||||
|
||||
Attribute MachinGroupAttribute `json:"groupAttribute"`
|
||||
|
||||
CreateTime uint32
|
||||
LastModifyTime uint32
|
||||
|
||||
project *LogProject
|
||||
}
|
||||
|
||||
type Machine struct {
|
||||
IP string
|
||||
UniqueId string `json:"machine-uniqueid"`
|
||||
UserdefinedId string `json:"userdefined-id"`
|
||||
}
|
||||
|
||||
type MachineList struct {
|
||||
Total int
|
||||
Machines []*Machine
|
||||
}
|
||||
|
||||
// ListMachines returns machine list of this machine group.
|
||||
func (m *MachineGroup) ListMachines() (ms []*Machine, total int, err error) {
|
||||
h := map[string]string{
|
||||
"x-sls-bodyrawsize": "0",
|
||||
}
|
||||
|
||||
uri := fmt.Sprintf("/machinegroups/%v/machines", m.Name)
|
||||
r, err := request(m.project, "GET", uri, h, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if r.StatusCode != http.StatusOK {
|
||||
errMsg := &errorMessage{}
|
||||
err = json.Unmarshal(buf, errMsg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to remove config from machine group")
|
||||
dump, _ := httputil.DumpResponse(r, true)
|
||||
fmt.Println(dump)
|
||||
return
|
||||
}
|
||||
err = fmt.Errorf("%v:%v", errMsg.Code, errMsg.Message)
|
||||
return
|
||||
}
|
||||
|
||||
body := &MachineList{}
|
||||
err = json.Unmarshal(buf, body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ms = body.Machines
|
||||
total = body.Total
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAppliedConfigs returns applied configs of this machine group.
|
||||
func (m *MachineGroup) GetAppliedConfigs() (confNames []string, err error) {
|
||||
confNames, err = m.project.GetAppliedConfigs(m.Name)
|
||||
return
|
||||
}
|
||||
62
vendor/github.com/fatedier/beego/logs/alils/request.go
generated
vendored
Executable file
62
vendor/github.com/fatedier/beego/logs/alils/request.go
generated
vendored
Executable file
@@ -0,0 +1,62 @@
|
||||
package alils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// request sends a request to SLS.
|
||||
func request(project *LogProject, method, uri string, headers map[string]string,
|
||||
body []byte) (resp *http.Response, err error) {
|
||||
|
||||
// The caller should provide 'x-sls-bodyrawsize' header
|
||||
if _, ok := headers["x-sls-bodyrawsize"]; !ok {
|
||||
err = fmt.Errorf("Can't find 'x-sls-bodyrawsize' header")
|
||||
return
|
||||
}
|
||||
|
||||
// SLS public request headers
|
||||
headers["Host"] = project.Name + "." + project.Endpoint
|
||||
headers["Date"] = nowRFC1123()
|
||||
headers["x-sls-apiversion"] = version
|
||||
headers["x-sls-signaturemethod"] = signatureMethod
|
||||
if body != nil {
|
||||
bodyMD5 := fmt.Sprintf("%X", md5.Sum(body))
|
||||
headers["Content-MD5"] = bodyMD5
|
||||
|
||||
if _, ok := headers["Content-Type"]; !ok {
|
||||
err = fmt.Errorf("Can't find 'Content-Type' header")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Calc Authorization
|
||||
// Authorization = "SLS <AccessKeyId>:<Signature>"
|
||||
digest, err := signature(project, method, uri, headers)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
auth := fmt.Sprintf("SLS %v:%v", project.AccessKeyId, digest)
|
||||
headers["Authorization"] = auth
|
||||
|
||||
// Initialize http request
|
||||
reader := bytes.NewReader(body)
|
||||
urlStr := fmt.Sprintf("http://%v.%v%v", project.Name, project.Endpoint, uri)
|
||||
req, err := http.NewRequest(method, urlStr, reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
// Get ready to do request
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
112
vendor/github.com/fatedier/beego/logs/alils/signature.go
generated
vendored
Executable file
112
vendor/github.com/fatedier/beego/logs/alils/signature.go
generated
vendored
Executable file
@@ -0,0 +1,112 @@
|
||||
package alils
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GMT location
|
||||
var gmtLoc = time.FixedZone("GMT", 0)
|
||||
|
||||
// NowRFC1123 returns now time in RFC1123 format with GMT timezone,
|
||||
// eg. "Mon, 02 Jan 2006 15:04:05 GMT".
|
||||
func nowRFC1123() string {
|
||||
return time.Now().In(gmtLoc).Format(time.RFC1123)
|
||||
}
|
||||
|
||||
// signature calculates a request's signature digest.
|
||||
func signature(project *LogProject, method, uri string,
|
||||
headers map[string]string) (digest string, err error) {
|
||||
var contentMD5, contentType, date, canoHeaders, canoResource string
|
||||
var slsHeaderKeys sort.StringSlice
|
||||
|
||||
// SignString = VERB + "\n"
|
||||
// + CONTENT-MD5 + "\n"
|
||||
// + CONTENT-TYPE + "\n"
|
||||
// + DATE + "\n"
|
||||
// + CanonicalizedSLSHeaders + "\n"
|
||||
// + CanonicalizedResource
|
||||
|
||||
if val, ok := headers["Content-MD5"]; ok {
|
||||
contentMD5 = val
|
||||
}
|
||||
|
||||
if val, ok := headers["Content-Type"]; ok {
|
||||
contentType = val
|
||||
}
|
||||
|
||||
date, ok := headers["Date"]
|
||||
if !ok {
|
||||
err = fmt.Errorf("Can't find 'Date' header")
|
||||
return
|
||||
}
|
||||
|
||||
// Calc CanonicalizedSLSHeaders
|
||||
slsHeaders := make(map[string]string, len(headers))
|
||||
for k, v := range headers {
|
||||
l := strings.TrimSpace(strings.ToLower(k))
|
||||
if strings.HasPrefix(l, "x-sls-") {
|
||||
slsHeaders[l] = strings.TrimSpace(v)
|
||||
slsHeaderKeys = append(slsHeaderKeys, l)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(slsHeaderKeys)
|
||||
for i, k := range slsHeaderKeys {
|
||||
canoHeaders += k + ":" + slsHeaders[k]
|
||||
if i+1 < len(slsHeaderKeys) {
|
||||
canoHeaders += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
// Calc CanonicalizedResource
|
||||
u, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
canoResource += url.QueryEscape(u.Path)
|
||||
if u.RawQuery != "" {
|
||||
var keys sort.StringSlice
|
||||
|
||||
vals := u.Query()
|
||||
for k, _ := range vals {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Sort(keys)
|
||||
canoResource += "?"
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
canoResource += "&"
|
||||
}
|
||||
|
||||
for _, v := range vals[k] {
|
||||
canoResource += k + "=" + v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signStr := method + "\n" +
|
||||
contentMD5 + "\n" +
|
||||
contentType + "\n" +
|
||||
date + "\n" +
|
||||
canoHeaders + "\n" +
|
||||
canoResource
|
||||
|
||||
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))
|
||||
mac := hmac.New(sha1.New, []byte(project.AccessKeySecret))
|
||||
_, err = mac.Write([]byte(signStr))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
digest = base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
return
|
||||
}
|
||||
|
||||
294
vendor/github.com/fatedier/beego/logs/color_windows_test.go
generated
vendored
Normal file
294
vendor/github.com/fatedier/beego/logs/color_windows_test.go
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build windows
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo
|
||||
|
||||
func ChangeColor(color uint16) {
|
||||
setConsoleTextAttribute(uintptr(syscall.Stdout), color)
|
||||
}
|
||||
|
||||
func ResetColor() {
|
||||
ChangeColor(uint16(0x0007))
|
||||
}
|
||||
|
||||
func TestWritePlanText(t *testing.T) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w := NewAnsiColorWriter(inner)
|
||||
expected := "plain text"
|
||||
fmt.Fprintf(w, expected)
|
||||
actual := inner.String()
|
||||
if actual != expected {
|
||||
t.Errorf("Get %q, want %q", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteParseText(t *testing.T) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w := NewAnsiColorWriter(inner)
|
||||
|
||||
inputTail := "\x1b[0mtail text"
|
||||
expectedTail := "tail text"
|
||||
fmt.Fprintf(w, inputTail)
|
||||
actualTail := inner.String()
|
||||
inner.Reset()
|
||||
if actualTail != expectedTail {
|
||||
t.Errorf("Get %q, want %q", actualTail, expectedTail)
|
||||
}
|
||||
|
||||
inputHead := "head text\x1b[0m"
|
||||
expectedHead := "head text"
|
||||
fmt.Fprintf(w, inputHead)
|
||||
actualHead := inner.String()
|
||||
inner.Reset()
|
||||
if actualHead != expectedHead {
|
||||
t.Errorf("Get %q, want %q", actualHead, expectedHead)
|
||||
}
|
||||
|
||||
inputBothEnds := "both ends \x1b[0m text"
|
||||
expectedBothEnds := "both ends text"
|
||||
fmt.Fprintf(w, inputBothEnds)
|
||||
actualBothEnds := inner.String()
|
||||
inner.Reset()
|
||||
if actualBothEnds != expectedBothEnds {
|
||||
t.Errorf("Get %q, want %q", actualBothEnds, expectedBothEnds)
|
||||
}
|
||||
|
||||
inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc"
|
||||
expectedManyEsc := "\x1b\x1b\x1b many esc"
|
||||
fmt.Fprintf(w, inputManyEsc)
|
||||
actualManyEsc := inner.String()
|
||||
inner.Reset()
|
||||
if actualManyEsc != expectedManyEsc {
|
||||
t.Errorf("Get %q, want %q", actualManyEsc, expectedManyEsc)
|
||||
}
|
||||
|
||||
expectedSplit := "split text"
|
||||
for _, ch := range "split \x1b[0m text" {
|
||||
fmt.Fprintf(w, string(ch))
|
||||
}
|
||||
actualSplit := inner.String()
|
||||
inner.Reset()
|
||||
if actualSplit != expectedSplit {
|
||||
t.Errorf("Get %q, want %q", actualSplit, expectedSplit)
|
||||
}
|
||||
}
|
||||
|
||||
type screenNotFoundError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w := NewAnsiColorWriter(inner)
|
||||
fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)
|
||||
|
||||
actualText = inner.String()
|
||||
screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
|
||||
if screenInfo != nil {
|
||||
actualAttributes = screenInfo.WAttributes
|
||||
} else {
|
||||
err = &screenNotFoundError{}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type testParam struct {
|
||||
text string
|
||||
attributes uint16
|
||||
ansiColor string
|
||||
}
|
||||
|
||||
func TestWriteAnsiColorText(t *testing.T) {
|
||||
screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
|
||||
if screenInfo == nil {
|
||||
t.Fatal("Could not get ConsoleScreenBufferInfo")
|
||||
}
|
||||
defer ChangeColor(screenInfo.WAttributes)
|
||||
defaultFgColor := screenInfo.WAttributes & uint16(0x0007)
|
||||
defaultBgColor := screenInfo.WAttributes & uint16(0x0070)
|
||||
defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008)
|
||||
defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080)
|
||||
|
||||
fgParam := []testParam{
|
||||
{"foreground black ", uint16(0x0000 | 0x0000), "30"},
|
||||
{"foreground red ", uint16(0x0004 | 0x0000), "31"},
|
||||
{"foreground green ", uint16(0x0002 | 0x0000), "32"},
|
||||
{"foreground yellow ", uint16(0x0006 | 0x0000), "33"},
|
||||
{"foreground blue ", uint16(0x0001 | 0x0000), "34"},
|
||||
{"foreground magenta", uint16(0x0005 | 0x0000), "35"},
|
||||
{"foreground cyan ", uint16(0x0003 | 0x0000), "36"},
|
||||
{"foreground white ", uint16(0x0007 | 0x0000), "37"},
|
||||
{"foreground default", defaultFgColor | 0x0000, "39"},
|
||||
{"foreground light gray ", uint16(0x0000 | 0x0008 | 0x0000), "90"},
|
||||
{"foreground light red ", uint16(0x0004 | 0x0008 | 0x0000), "91"},
|
||||
{"foreground light green ", uint16(0x0002 | 0x0008 | 0x0000), "92"},
|
||||
{"foreground light yellow ", uint16(0x0006 | 0x0008 | 0x0000), "93"},
|
||||
{"foreground light blue ", uint16(0x0001 | 0x0008 | 0x0000), "94"},
|
||||
{"foreground light magenta", uint16(0x0005 | 0x0008 | 0x0000), "95"},
|
||||
{"foreground light cyan ", uint16(0x0003 | 0x0008 | 0x0000), "96"},
|
||||
{"foreground light white ", uint16(0x0007 | 0x0008 | 0x0000), "97"},
|
||||
}
|
||||
|
||||
bgParam := []testParam{
|
||||
{"background black ", uint16(0x0007 | 0x0000), "40"},
|
||||
{"background red ", uint16(0x0007 | 0x0040), "41"},
|
||||
{"background green ", uint16(0x0007 | 0x0020), "42"},
|
||||
{"background yellow ", uint16(0x0007 | 0x0060), "43"},
|
||||
{"background blue ", uint16(0x0007 | 0x0010), "44"},
|
||||
{"background magenta", uint16(0x0007 | 0x0050), "45"},
|
||||
{"background cyan ", uint16(0x0007 | 0x0030), "46"},
|
||||
{"background white ", uint16(0x0007 | 0x0070), "47"},
|
||||
{"background default", uint16(0x0007) | defaultBgColor, "49"},
|
||||
{"background light gray ", uint16(0x0007 | 0x0000 | 0x0080), "100"},
|
||||
{"background light red ", uint16(0x0007 | 0x0040 | 0x0080), "101"},
|
||||
{"background light green ", uint16(0x0007 | 0x0020 | 0x0080), "102"},
|
||||
{"background light yellow ", uint16(0x0007 | 0x0060 | 0x0080), "103"},
|
||||
{"background light blue ", uint16(0x0007 | 0x0010 | 0x0080), "104"},
|
||||
{"background light magenta", uint16(0x0007 | 0x0050 | 0x0080), "105"},
|
||||
{"background light cyan ", uint16(0x0007 | 0x0030 | 0x0080), "106"},
|
||||
{"background light white ", uint16(0x0007 | 0x0070 | 0x0080), "107"},
|
||||
}
|
||||
|
||||
resetParam := []testParam{
|
||||
{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"},
|
||||
{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""},
|
||||
}
|
||||
|
||||
boldParam := []testParam{
|
||||
{"bold on", uint16(0x0007 | 0x0008), "1"},
|
||||
{"bold off", uint16(0x0007), "21"},
|
||||
}
|
||||
|
||||
underscoreParam := []testParam{
|
||||
{"underscore on", uint16(0x0007 | 0x8000), "4"},
|
||||
{"underscore off", uint16(0x0007), "24"},
|
||||
}
|
||||
|
||||
blinkParam := []testParam{
|
||||
{"blink on", uint16(0x0007 | 0x0080), "5"},
|
||||
{"blink off", uint16(0x0007), "25"},
|
||||
}
|
||||
|
||||
mixedParam := []testParam{
|
||||
{"both black, bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"},
|
||||
{"both red, bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"},
|
||||
{"both green, bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"},
|
||||
{"both yellow, bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"},
|
||||
{"both blue, bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"},
|
||||
{"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"},
|
||||
{"both cyan, bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"},
|
||||
{"both white, bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"},
|
||||
{"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"},
|
||||
}
|
||||
|
||||
assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
|
||||
actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
|
||||
if actualText != expectedText {
|
||||
t.Errorf("Get %q, want %q", actualText, expectedText)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal("Could not get ConsoleScreenBufferInfo")
|
||||
}
|
||||
if actualAttributes != expectedAttributes {
|
||||
t.Errorf("Text: %q, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range fgParam {
|
||||
ResetColor()
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
for _, v := range bgParam {
|
||||
ChangeColor(uint16(0x0070 | 0x0007))
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
for _, v := range resetParam {
|
||||
ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
ResetColor()
|
||||
for _, v := range boldParam {
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
ResetColor()
|
||||
for _, v := range underscoreParam {
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
ResetColor()
|
||||
for _, v := range blinkParam {
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
|
||||
for _, v := range mixedParam {
|
||||
ResetColor()
|
||||
assertTextAttribute(v.text, v.attributes, v.ansiColor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoreUnknownSequences(t *testing.T) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w := NewModeAnsiColorWriter(inner, OutputNonColorEscSeq)
|
||||
|
||||
inputText := "\x1b[=decpath mode"
|
||||
expectedTail := inputText
|
||||
fmt.Fprintf(w, inputText)
|
||||
actualTail := inner.String()
|
||||
inner.Reset()
|
||||
if actualTail != expectedTail {
|
||||
t.Errorf("Get %q, want %q", actualTail, expectedTail)
|
||||
}
|
||||
|
||||
inputText = "\x1b[=tailing esc and bracket\x1b["
|
||||
expectedTail = inputText
|
||||
fmt.Fprintf(w, inputText)
|
||||
actualTail = inner.String()
|
||||
inner.Reset()
|
||||
if actualTail != expectedTail {
|
||||
t.Errorf("Get %q, want %q", actualTail, expectedTail)
|
||||
}
|
||||
|
||||
inputText = "\x1b[?tailing esc\x1b"
|
||||
expectedTail = inputText
|
||||
fmt.Fprintf(w, inputText)
|
||||
actualTail = inner.String()
|
||||
inner.Reset()
|
||||
if actualTail != expectedTail {
|
||||
t.Errorf("Get %q, want %q", actualTail, expectedTail)
|
||||
}
|
||||
|
||||
inputText = "\x1b[1h;3punended color code invalid\x1b3"
|
||||
expectedTail = inputText
|
||||
fmt.Fprintf(w, inputText)
|
||||
actualTail = inner.String()
|
||||
inner.Reset()
|
||||
if actualTail != expectedTail {
|
||||
t.Errorf("Get %q, want %q", actualTail, expectedTail)
|
||||
}
|
||||
}
|
||||
25
vendor/github.com/fatedier/beego/logs/conn_test.go
generated
vendored
Normal file
25
vendor/github.com/fatedier/beego/logs/conn_test.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConn(t *testing.T) {
|
||||
log := NewLogger(1000)
|
||||
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
|
||||
log.Informational("informational")
|
||||
}
|
||||
51
vendor/github.com/fatedier/beego/logs/console_test.go
generated
vendored
Normal file
51
vendor/github.com/fatedier/beego/logs/console_test.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Try each log level in decreasing order of priority.
|
||||
func testConsoleCalls(bl *BeeLogger) {
|
||||
bl.Emergency("emergency")
|
||||
bl.Alert("alert")
|
||||
bl.Critical("critical")
|
||||
bl.Error("error")
|
||||
bl.Warning("warning")
|
||||
bl.Notice("notice")
|
||||
bl.Informational("informational")
|
||||
bl.Debug("debug")
|
||||
}
|
||||
|
||||
// Test console logging by visually comparing the lines being output with and
|
||||
// without a log level specification.
|
||||
func TestConsole(t *testing.T) {
|
||||
log1 := NewLogger(10000)
|
||||
log1.EnableFuncCallDepth(true)
|
||||
log1.SetLogger("console", "")
|
||||
testConsoleCalls(log1)
|
||||
|
||||
log2 := NewLogger(100)
|
||||
log2.SetLogger("console", `{"level":3}`)
|
||||
testConsoleCalls(log2)
|
||||
}
|
||||
|
||||
// Test console without color
|
||||
func TestConsoleNoColor(t *testing.T) {
|
||||
log := NewLogger(100)
|
||||
log.SetLogger("console", `{"color":false}`)
|
||||
testConsoleCalls(log)
|
||||
}
|
||||
80
vendor/github.com/fatedier/beego/logs/es/es.go
generated
vendored
Normal file
80
vendor/github.com/fatedier/beego/logs/es/es.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package es
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/belogik/goes"
|
||||
)
|
||||
|
||||
// NewES return a LoggerInterface
|
||||
func NewES() logs.Logger {
|
||||
cw := &esLogger{
|
||||
Level: logs.LevelDebug,
|
||||
}
|
||||
return cw
|
||||
}
|
||||
|
||||
type esLogger struct {
|
||||
*goes.Connection
|
||||
DSN string `json:"dsn"`
|
||||
Level int `json:"level"`
|
||||
}
|
||||
|
||||
// {"dsn":"http://localhost:9200/","level":1}
|
||||
func (el *esLogger) Init(jsonconfig string) error {
|
||||
err := json.Unmarshal([]byte(jsonconfig), el)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if el.DSN == "" {
|
||||
return errors.New("empty dsn")
|
||||
} else if u, err := url.Parse(el.DSN); err != nil {
|
||||
return err
|
||||
} else if u.Path == "" {
|
||||
return errors.New("missing prefix")
|
||||
} else if host, port, err := net.SplitHostPort(u.Host); err != nil {
|
||||
return err
|
||||
} else {
|
||||
conn := goes.NewConnection(host, port)
|
||||
el.Connection = conn
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMsg will write the msg and level into es
|
||||
func (el *esLogger) WriteMsg(when time.Time, msg string, level int) error {
|
||||
if level > el.Level {
|
||||
return nil
|
||||
}
|
||||
|
||||
vals := make(map[string]interface{})
|
||||
vals["@timestamp"] = when.Format(time.RFC3339)
|
||||
vals["@msg"] = msg
|
||||
d := goes.Document{
|
||||
Index: fmt.Sprintf("%04d.%02d.%02d", when.Year(), when.Month(), when.Day()),
|
||||
Type: "logs",
|
||||
Fields: vals,
|
||||
}
|
||||
_, err := el.Index(d, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Destroy is a empty method
|
||||
func (el *esLogger) Destroy() {
|
||||
|
||||
}
|
||||
|
||||
// Flush is a empty method
|
||||
func (el *esLogger) Flush() {
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
logs.Register(logs.AdapterEs, NewES)
|
||||
}
|
||||
280
vendor/github.com/fatedier/beego/logs/file_test.go
generated
vendored
Normal file
280
vendor/github.com/fatedier/beego/logs/file_test.go
generated
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFilePerm(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
// use 0666 as test perm cause the default umask is 022
|
||||
log.SetLogger("file", `{"filename":"test.log", "perm": "0666"}`)
|
||||
log.Debug("debug")
|
||||
log.Informational("info")
|
||||
log.Notice("notice")
|
||||
log.Warning("warning")
|
||||
log.Error("error")
|
||||
log.Alert("alert")
|
||||
log.Critical("critical")
|
||||
log.Emergency("emergency")
|
||||
file, err := os.Stat("test.log")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if file.Mode() != 0666 {
|
||||
t.Fatal("unexpected log file permission")
|
||||
}
|
||||
os.Remove("test.log")
|
||||
}
|
||||
|
||||
func TestFile1(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
log.SetLogger("file", `{"filename":"test.log"}`)
|
||||
log.Debug("debug")
|
||||
log.Informational("info")
|
||||
log.Notice("notice")
|
||||
log.Warning("warning")
|
||||
log.Error("error")
|
||||
log.Alert("alert")
|
||||
log.Critical("critical")
|
||||
log.Emergency("emergency")
|
||||
f, err := os.Open("test.log")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := bufio.NewReader(f)
|
||||
lineNum := 0
|
||||
for {
|
||||
line, _, err := b.ReadLine()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(line) > 0 {
|
||||
lineNum++
|
||||
}
|
||||
}
|
||||
var expected = LevelDebug + 1
|
||||
if lineNum != expected {
|
||||
t.Fatal(lineNum, "not "+strconv.Itoa(expected)+" lines")
|
||||
}
|
||||
os.Remove("test.log")
|
||||
}
|
||||
|
||||
func TestFile2(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
log.SetLogger("file", fmt.Sprintf(`{"filename":"test2.log","level":%d}`, LevelError))
|
||||
log.Debug("debug")
|
||||
log.Info("info")
|
||||
log.Notice("notice")
|
||||
log.Warning("warning")
|
||||
log.Error("error")
|
||||
log.Alert("alert")
|
||||
log.Critical("critical")
|
||||
log.Emergency("emergency")
|
||||
f, err := os.Open("test2.log")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := bufio.NewReader(f)
|
||||
lineNum := 0
|
||||
for {
|
||||
line, _, err := b.ReadLine()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(line) > 0 {
|
||||
lineNum++
|
||||
}
|
||||
}
|
||||
var expected = LevelError + 1
|
||||
if lineNum != expected {
|
||||
t.Fatal(lineNum, "not "+strconv.Itoa(expected)+" lines")
|
||||
}
|
||||
os.Remove("test2.log")
|
||||
}
|
||||
|
||||
func TestFileRotate_01(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`)
|
||||
log.Debug("debug")
|
||||
log.Info("info")
|
||||
log.Notice("notice")
|
||||
log.Warning("warning")
|
||||
log.Error("error")
|
||||
log.Alert("alert")
|
||||
log.Critical("critical")
|
||||
log.Emergency("emergency")
|
||||
rotateName := "test3" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log"
|
||||
b, err := exists(rotateName)
|
||||
if !b || err != nil {
|
||||
os.Remove("test3.log")
|
||||
t.Fatal("rotate not generated")
|
||||
}
|
||||
os.Remove(rotateName)
|
||||
os.Remove("test3.log")
|
||||
}
|
||||
|
||||
func TestFileRotate_02(t *testing.T) {
|
||||
fn1 := "rotate_day.log"
|
||||
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||
testFileRotate(t, fn1, fn2)
|
||||
}
|
||||
|
||||
func TestFileRotate_03(t *testing.T) {
|
||||
fn1 := "rotate_day.log"
|
||||
fn := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||
os.Create(fn)
|
||||
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".001.log"
|
||||
testFileRotate(t, fn1, fn2)
|
||||
os.Remove(fn)
|
||||
}
|
||||
|
||||
func TestFileRotate_04(t *testing.T) {
|
||||
fn1 := "rotate_day.log"
|
||||
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||
testFileDailyRotate(t, fn1, fn2)
|
||||
}
|
||||
|
||||
func TestFileRotate_05(t *testing.T) {
|
||||
fn1 := "rotate_day.log"
|
||||
fn := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".log"
|
||||
os.Create(fn)
|
||||
fn2 := "rotate_day." + time.Now().Add(-24*time.Hour).Format("2006-01-02") + ".001.log"
|
||||
testFileDailyRotate(t, fn1, fn2)
|
||||
os.Remove(fn)
|
||||
}
|
||||
|
||||
func testFileRotate(t *testing.T, fn1, fn2 string) {
|
||||
fw := &fileLogWriter{
|
||||
Daily: true,
|
||||
MaxDays: 7,
|
||||
Rotate: true,
|
||||
Level: LevelTrace,
|
||||
Perm: "0660",
|
||||
}
|
||||
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
||||
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
||||
fw.dailyOpenDate = fw.dailyOpenTime.Day()
|
||||
fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
|
||||
|
||||
for _, file := range []string{fn1, fn2} {
|
||||
_, err := os.Stat(file)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
os.Remove(file)
|
||||
}
|
||||
fw.Destroy()
|
||||
}
|
||||
|
||||
func testFileDailyRotate(t *testing.T, fn1, fn2 string) {
|
||||
fw := &fileLogWriter{
|
||||
Daily: true,
|
||||
MaxDays: 7,
|
||||
Rotate: true,
|
||||
Level: LevelTrace,
|
||||
Perm: "0660",
|
||||
}
|
||||
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
||||
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
||||
fw.dailyOpenDate = fw.dailyOpenTime.Day()
|
||||
today, _ := time.ParseInLocation("2006-01-02", time.Now().Format("2006-01-02"), fw.dailyOpenTime.Location())
|
||||
today = today.Add(-1 * time.Second)
|
||||
fw.dailyRotate(today)
|
||||
for _, file := range []string{fn1, fn2} {
|
||||
_, err := os.Stat(file)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
content, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if len(content) > 0 {
|
||||
t.FailNow()
|
||||
}
|
||||
os.Remove(file)
|
||||
}
|
||||
fw.Destroy()
|
||||
}
|
||||
|
||||
func exists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func BenchmarkFile(b *testing.B) {
|
||||
log := NewLogger(100000)
|
||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||
for i := 0; i < b.N; i++ {
|
||||
log.Debug("debug")
|
||||
}
|
||||
os.Remove("test4.log")
|
||||
}
|
||||
|
||||
func BenchmarkFileAsynchronous(b *testing.B) {
|
||||
log := NewLogger(100000)
|
||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||
log.Async()
|
||||
for i := 0; i < b.N; i++ {
|
||||
log.Debug("debug")
|
||||
}
|
||||
os.Remove("test4.log")
|
||||
}
|
||||
|
||||
func BenchmarkFileCallDepth(b *testing.B) {
|
||||
log := NewLogger(100000)
|
||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||
log.EnableFuncCallDepth(true)
|
||||
log.SetLogFuncCallDepth(2)
|
||||
for i := 0; i < b.N; i++ {
|
||||
log.Debug("debug")
|
||||
}
|
||||
os.Remove("test4.log")
|
||||
}
|
||||
|
||||
func BenchmarkFileAsynchronousCallDepth(b *testing.B) {
|
||||
log := NewLogger(100000)
|
||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||
log.EnableFuncCallDepth(true)
|
||||
log.SetLogFuncCallDepth(2)
|
||||
log.Async()
|
||||
for i := 0; i < b.N; i++ {
|
||||
log.Debug("debug")
|
||||
}
|
||||
os.Remove("test4.log")
|
||||
}
|
||||
|
||||
func BenchmarkFileOnGoroutine(b *testing.B) {
|
||||
log := NewLogger(100000)
|
||||
log.SetLogger("file", `{"filename":"test4.log"}`)
|
||||
for i := 0; i < b.N; i++ {
|
||||
go log.Debug("debug")
|
||||
}
|
||||
os.Remove("test4.log")
|
||||
}
|
||||
75
vendor/github.com/fatedier/beego/logs/logger_test.go
generated
vendored
Normal file
75
vendor/github.com/fatedier/beego/logs/logger_test.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2016 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFormatHeader_0(t *testing.T) {
|
||||
tm := time.Now()
|
||||
if tm.Year() >= 2100 {
|
||||
t.FailNow()
|
||||
}
|
||||
dur := time.Second
|
||||
for {
|
||||
if tm.Year() >= 2100 {
|
||||
break
|
||||
}
|
||||
h, _ := formatTimeHeader(tm)
|
||||
if tm.Format("2006/01/02 15:04:05 ") != string(h) {
|
||||
t.Log(tm)
|
||||
t.FailNow()
|
||||
}
|
||||
tm = tm.Add(dur)
|
||||
dur *= 2
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatHeader_1(t *testing.T) {
|
||||
tm := time.Now()
|
||||
year := tm.Year()
|
||||
dur := time.Second
|
||||
for {
|
||||
if tm.Year() >= year+1 {
|
||||
break
|
||||
}
|
||||
h, _ := formatTimeHeader(tm)
|
||||
if tm.Format("2006/01/02 15:04:05 ") != string(h) {
|
||||
t.Log(tm)
|
||||
t.FailNow()
|
||||
}
|
||||
tm = tm.Add(dur)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAnsiColor1(t *testing.T) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w := NewAnsiColorWriter(inner)
|
||||
if w == inner {
|
||||
t.Errorf("Get %#v, want %#v", w, inner)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAnsiColor2(t *testing.T) {
|
||||
inner := bytes.NewBufferString("")
|
||||
w1 := NewAnsiColorWriter(inner)
|
||||
w2 := NewAnsiColorWriter(w1)
|
||||
if w1 != w2 {
|
||||
t.Errorf("Get %#v, want %#v", w1, w2)
|
||||
}
|
||||
}
|
||||
78
vendor/github.com/fatedier/beego/logs/multifile_test.go
generated
vendored
Normal file
78
vendor/github.com/fatedier/beego/logs/multifile_test.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFiles_1(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
log.SetLogger("multifile", `{"filename":"test.log","separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"]}`)
|
||||
log.Debug("debug")
|
||||
log.Informational("info")
|
||||
log.Notice("notice")
|
||||
log.Warning("warning")
|
||||
log.Error("error")
|
||||
log.Alert("alert")
|
||||
log.Critical("critical")
|
||||
log.Emergency("emergency")
|
||||
fns := []string{""}
|
||||
fns = append(fns, levelNames[0:]...)
|
||||
name := "test"
|
||||
suffix := ".log"
|
||||
for _, fn := range fns {
|
||||
|
||||
file := name + suffix
|
||||
if fn != "" {
|
||||
file = name + "." + fn + suffix
|
||||
}
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := bufio.NewReader(f)
|
||||
lineNum := 0
|
||||
lastLine := ""
|
||||
for {
|
||||
line, _, err := b.ReadLine()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(line) > 0 {
|
||||
lastLine = string(line)
|
||||
lineNum++
|
||||
}
|
||||
}
|
||||
var expected = 1
|
||||
if fn == "" {
|
||||
expected = LevelDebug + 1
|
||||
}
|
||||
if lineNum != expected {
|
||||
t.Fatal(file, "has", lineNum, "lines not "+strconv.Itoa(expected)+" lines")
|
||||
}
|
||||
if lineNum == 1 {
|
||||
if !strings.Contains(lastLine, fn) {
|
||||
t.Fatal(file + " " + lastLine + " not contains the log msg " + fn)
|
||||
}
|
||||
}
|
||||
os.Remove(file)
|
||||
}
|
||||
|
||||
}
|
||||
27
vendor/github.com/fatedier/beego/logs/smtp_test.go
generated
vendored
Normal file
27
vendor/github.com/fatedier/beego/logs/smtp_test.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSmtp(t *testing.T) {
|
||||
log := NewLogger(10000)
|
||||
log.SetLogger("smtp", `{"username":"beegotest@gmail.com","password":"xxxxxxxx","host":"smtp.gmail.com:587","sendTos":["xiemengjun@gmail.com"]}`)
|
||||
log.Critical("sendmail critical")
|
||||
time.Sleep(time.Second * 30)
|
||||
}
|
||||
53
vendor/github.com/fatedier/beego/migration/ddl.go
generated
vendored
Normal file
53
vendor/github.com/fatedier/beego/migration/ddl.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package migration
|
||||
|
||||
// Table store the tablename and Column
|
||||
type Table struct {
|
||||
TableName string
|
||||
Columns []*Column
|
||||
}
|
||||
|
||||
// Create return the create sql
|
||||
func (t *Table) Create() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Drop return the drop sql
|
||||
func (t *Table) Drop() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Column define the columns name type and Default
|
||||
type Column struct {
|
||||
Name string
|
||||
Type string
|
||||
Default interface{}
|
||||
}
|
||||
|
||||
// Create return create sql with the provided tbname and columns
|
||||
func Create(tbname string, columns ...Column) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Drop return the drop sql with the provided tbname and columns
|
||||
func Drop(tbname string, columns ...Column) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TableDDL is still in think
|
||||
func TableDDL(tbname string, columns ...Column) string {
|
||||
return ""
|
||||
}
|
||||
278
vendor/github.com/fatedier/beego/migration/migration.go
generated
vendored
Normal file
278
vendor/github.com/fatedier/beego/migration/migration.go
generated
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package migration is used for migration
|
||||
//
|
||||
// The table structure is as follow:
|
||||
//
|
||||
// CREATE TABLE `migrations` (
|
||||
// `id_migration` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key',
|
||||
// `name` varchar(255) DEFAULT NULL COMMENT 'migration name, unique',
|
||||
// `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'date migrated or rolled back',
|
||||
// `statements` longtext COMMENT 'SQL statements for this migration',
|
||||
// `rollback_statements` longtext,
|
||||
// `status` enum('update','rollback') DEFAULT NULL COMMENT 'update indicates it is a normal migration while rollback means this migration is rolled back',
|
||||
// PRIMARY KEY (`id_migration`)
|
||||
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
package migration
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/astaxie/beego/orm"
|
||||
)
|
||||
|
||||
// const the data format for the bee generate migration datatype
|
||||
const (
|
||||
DateFormat = "20060102_150405"
|
||||
DBDateFormat = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
||||
// Migrationer is an interface for all Migration struct
|
||||
type Migrationer interface {
|
||||
Up()
|
||||
Down()
|
||||
Reset()
|
||||
Exec(name, status string) error
|
||||
GetCreated() int64
|
||||
}
|
||||
|
||||
var (
|
||||
migrationMap map[string]Migrationer
|
||||
)
|
||||
|
||||
func init() {
|
||||
migrationMap = make(map[string]Migrationer)
|
||||
}
|
||||
|
||||
// Migration the basic type which will implement the basic type
|
||||
type Migration struct {
|
||||
sqls []string
|
||||
Created string
|
||||
}
|
||||
|
||||
// Up implement in the Inheritance struct for upgrade
|
||||
func (m *Migration) Up() {
|
||||
|
||||
}
|
||||
|
||||
// Down implement in the Inheritance struct for down
|
||||
func (m *Migration) Down() {
|
||||
|
||||
}
|
||||
|
||||
// SQL add sql want to execute
|
||||
func (m *Migration) SQL(sql string) {
|
||||
m.sqls = append(m.sqls, sql)
|
||||
}
|
||||
|
||||
// Reset the sqls
|
||||
func (m *Migration) Reset() {
|
||||
m.sqls = make([]string, 0)
|
||||
}
|
||||
|
||||
// Exec execute the sql already add in the sql
|
||||
func (m *Migration) Exec(name, status string) error {
|
||||
o := orm.NewOrm()
|
||||
for _, s := range m.sqls {
|
||||
logs.Info("exec sql:", s)
|
||||
r := o.Raw(s)
|
||||
_, err := r.Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return m.addOrUpdateRecord(name, status)
|
||||
}
|
||||
|
||||
func (m *Migration) addOrUpdateRecord(name, status string) error {
|
||||
o := orm.NewOrm()
|
||||
if status == "down" {
|
||||
status = "rollback"
|
||||
p, err := o.Raw("update migrations set status = ?, rollback_statements = ?, created_at = ? where name = ?").Prepare()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
_, err = p.Exec(status, strings.Join(m.sqls, "; "), time.Now().Format(DBDateFormat), name)
|
||||
return err
|
||||
}
|
||||
status = "update"
|
||||
p, err := o.Raw("insert into migrations(name, created_at, statements, status) values(?,?,?,?)").Prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = p.Exec(name, time.Now().Format(DBDateFormat), strings.Join(m.sqls, "; "), status)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetCreated get the unixtime from the Created
|
||||
func (m *Migration) GetCreated() int64 {
|
||||
t, err := time.Parse(DateFormat, m.Created)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// Register register the Migration in the map
|
||||
func Register(name string, m Migrationer) error {
|
||||
if _, ok := migrationMap[name]; ok {
|
||||
return errors.New("already exist name:" + name)
|
||||
}
|
||||
migrationMap[name] = m
|
||||
return nil
|
||||
}
|
||||
|
||||
// Upgrade upgrate the migration from lasttime
|
||||
func Upgrade(lasttime int64) error {
|
||||
sm := sortMap(migrationMap)
|
||||
i := 0
|
||||
for _, v := range sm {
|
||||
if v.created > lasttime {
|
||||
logs.Info("start upgrade", v.name)
|
||||
v.m.Reset()
|
||||
v.m.Up()
|
||||
err := v.m.Exec(v.name, "up")
|
||||
if err != nil {
|
||||
logs.Error("execute error:", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
return err
|
||||
}
|
||||
logs.Info("end upgrade:", v.name)
|
||||
i++
|
||||
}
|
||||
}
|
||||
logs.Info("total success upgrade:", i, " migration")
|
||||
time.Sleep(2 * time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rollback rollback the migration by the name
|
||||
func Rollback(name string) error {
|
||||
if v, ok := migrationMap[name]; ok {
|
||||
logs.Info("start rollback")
|
||||
v.Reset()
|
||||
v.Down()
|
||||
err := v.Exec(name, "down")
|
||||
if err != nil {
|
||||
logs.Error("execute error:", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
return err
|
||||
}
|
||||
logs.Info("end rollback")
|
||||
time.Sleep(2 * time.Second)
|
||||
return nil
|
||||
}
|
||||
logs.Error("not exist the migrationMap name:" + name)
|
||||
time.Sleep(2 * time.Second)
|
||||
return errors.New("not exist the migrationMap name:" + name)
|
||||
}
|
||||
|
||||
// Reset reset all migration
|
||||
// run all migration's down function
|
||||
func Reset() error {
|
||||
sm := sortMap(migrationMap)
|
||||
i := 0
|
||||
for j := len(sm) - 1; j >= 0; j-- {
|
||||
v := sm[j]
|
||||
if isRollBack(v.name) {
|
||||
logs.Info("skip the", v.name)
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
logs.Info("start reset:", v.name)
|
||||
v.m.Reset()
|
||||
v.m.Down()
|
||||
err := v.m.Exec(v.name, "down")
|
||||
if err != nil {
|
||||
logs.Error("execute error:", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
return err
|
||||
}
|
||||
i++
|
||||
logs.Info("end reset:", v.name)
|
||||
}
|
||||
logs.Info("total success reset:", i, " migration")
|
||||
time.Sleep(2 * time.Second)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Refresh first Reset, then Upgrade
|
||||
func Refresh() error {
|
||||
err := Reset()
|
||||
if err != nil {
|
||||
logs.Error("execute error:", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
return err
|
||||
}
|
||||
err = Upgrade(0)
|
||||
return err
|
||||
}
|
||||
|
||||
type dataSlice []data
|
||||
|
||||
type data struct {
|
||||
created int64
|
||||
name string
|
||||
m Migrationer
|
||||
}
|
||||
|
||||
// Len is part of sort.Interface.
|
||||
func (d dataSlice) Len() int {
|
||||
return len(d)
|
||||
}
|
||||
|
||||
// Swap is part of sort.Interface.
|
||||
func (d dataSlice) Swap(i, j int) {
|
||||
d[i], d[j] = d[j], d[i]
|
||||
}
|
||||
|
||||
// Less is part of sort.Interface. We use count as the value to sort by
|
||||
func (d dataSlice) Less(i, j int) bool {
|
||||
return d[i].created < d[j].created
|
||||
}
|
||||
|
||||
func sortMap(m map[string]Migrationer) dataSlice {
|
||||
s := make(dataSlice, 0, len(m))
|
||||
for k, v := range m {
|
||||
d := data{}
|
||||
d.created = v.GetCreated()
|
||||
d.name = k
|
||||
d.m = v
|
||||
s = append(s, d)
|
||||
}
|
||||
sort.Sort(s)
|
||||
return s
|
||||
}
|
||||
|
||||
func isRollBack(name string) bool {
|
||||
o := orm.NewOrm()
|
||||
var maps []orm.Params
|
||||
num, err := o.Raw("select * from migrations where `name` = ? order by id_migration desc", name).Values(&maps)
|
||||
if err != nil {
|
||||
logs.Info("get name has error", err)
|
||||
return false
|
||||
}
|
||||
if num <= 0 {
|
||||
return false
|
||||
}
|
||||
if maps[0]["status"] == "rollback" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
556
vendor/github.com/fatedier/beego/mime.go
generated
vendored
Normal file
556
vendor/github.com/fatedier/beego/mime.go
generated
vendored
Normal file
@@ -0,0 +1,556 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
var mimemaps = map[string]string{
|
||||
".3dm": "x-world/x-3dmf",
|
||||
".3dmf": "x-world/x-3dmf",
|
||||
".7z": "application/x-7z-compressed",
|
||||
".a": "application/octet-stream",
|
||||
".aab": "application/x-authorware-bin",
|
||||
".aam": "application/x-authorware-map",
|
||||
".aas": "application/x-authorware-seg",
|
||||
".abc": "text/vndabc",
|
||||
".ace": "application/x-ace-compressed",
|
||||
".acgi": "text/html",
|
||||
".afl": "video/animaflex",
|
||||
".ai": "application/postscript",
|
||||
".aif": "audio/aiff",
|
||||
".aifc": "audio/aiff",
|
||||
".aiff": "audio/aiff",
|
||||
".aim": "application/x-aim",
|
||||
".aip": "text/x-audiosoft-intra",
|
||||
".alz": "application/x-alz-compressed",
|
||||
".ani": "application/x-navi-animation",
|
||||
".aos": "application/x-nokia-9000-communicator-add-on-software",
|
||||
".aps": "application/mime",
|
||||
".apk": "application/vnd.android.package-archive",
|
||||
".arc": "application/x-arc-compressed",
|
||||
".arj": "application/arj",
|
||||
".art": "image/x-jg",
|
||||
".asf": "video/x-ms-asf",
|
||||
".asm": "text/x-asm",
|
||||
".asp": "text/asp",
|
||||
".asx": "application/x-mplayer2",
|
||||
".au": "audio/basic",
|
||||
".avi": "video/x-msvideo",
|
||||
".avs": "video/avs-video",
|
||||
".bcpio": "application/x-bcpio",
|
||||
".bin": "application/mac-binary",
|
||||
".bmp": "image/bmp",
|
||||
".boo": "application/book",
|
||||
".book": "application/book",
|
||||
".boz": "application/x-bzip2",
|
||||
".bsh": "application/x-bsh",
|
||||
".bz2": "application/x-bzip2",
|
||||
".bz": "application/x-bzip",
|
||||
".c++": "text/plain",
|
||||
".c": "text/x-c",
|
||||
".cab": "application/vnd.ms-cab-compressed",
|
||||
".cat": "application/vndms-pkiseccat",
|
||||
".cc": "text/x-c",
|
||||
".ccad": "application/clariscad",
|
||||
".cco": "application/x-cocoa",
|
||||
".cdf": "application/cdf",
|
||||
".cer": "application/pkix-cert",
|
||||
".cha": "application/x-chat",
|
||||
".chat": "application/x-chat",
|
||||
".chrt": "application/vnd.kde.kchart",
|
||||
".class": "application/java",
|
||||
".com": "text/plain",
|
||||
".conf": "text/plain",
|
||||
".cpio": "application/x-cpio",
|
||||
".cpp": "text/x-c",
|
||||
".cpt": "application/mac-compactpro",
|
||||
".crl": "application/pkcs-crl",
|
||||
".crt": "application/pkix-cert",
|
||||
".crx": "application/x-chrome-extension",
|
||||
".csh": "text/x-scriptcsh",
|
||||
".css": "text/css",
|
||||
".csv": "text/csv",
|
||||
".cxx": "text/plain",
|
||||
".dar": "application/x-dar",
|
||||
".dcr": "application/x-director",
|
||||
".deb": "application/x-debian-package",
|
||||
".deepv": "application/x-deepv",
|
||||
".def": "text/plain",
|
||||
".der": "application/x-x509-ca-cert",
|
||||
".dif": "video/x-dv",
|
||||
".dir": "application/x-director",
|
||||
".divx": "video/divx",
|
||||
".dl": "video/dl",
|
||||
".dmg": "application/x-apple-diskimage",
|
||||
".doc": "application/msword",
|
||||
".dot": "application/msword",
|
||||
".dp": "application/commonground",
|
||||
".drw": "application/drafting",
|
||||
".dump": "application/octet-stream",
|
||||
".dv": "video/x-dv",
|
||||
".dvi": "application/x-dvi",
|
||||
".dwf": "drawing/x-dwf=(old)",
|
||||
".dwg": "application/acad",
|
||||
".dxf": "application/dxf",
|
||||
".dxr": "application/x-director",
|
||||
".el": "text/x-scriptelisp",
|
||||
".elc": "application/x-bytecodeelisp=(compiled=elisp)",
|
||||
".eml": "message/rfc822",
|
||||
".env": "application/x-envoy",
|
||||
".eps": "application/postscript",
|
||||
".es": "application/x-esrehber",
|
||||
".etx": "text/x-setext",
|
||||
".evy": "application/envoy",
|
||||
".exe": "application/octet-stream",
|
||||
".f77": "text/x-fortran",
|
||||
".f90": "text/x-fortran",
|
||||
".f": "text/x-fortran",
|
||||
".fdf": "application/vndfdf",
|
||||
".fif": "application/fractals",
|
||||
".fli": "video/fli",
|
||||
".flo": "image/florian",
|
||||
".flv": "video/x-flv",
|
||||
".flx": "text/vndfmiflexstor",
|
||||
".fmf": "video/x-atomic3d-feature",
|
||||
".for": "text/x-fortran",
|
||||
".fpx": "image/vndfpx",
|
||||
".frl": "application/freeloader",
|
||||
".funk": "audio/make",
|
||||
".g3": "image/g3fax",
|
||||
".g": "text/plain",
|
||||
".gif": "image/gif",
|
||||
".gl": "video/gl",
|
||||
".gsd": "audio/x-gsm",
|
||||
".gsm": "audio/x-gsm",
|
||||
".gsp": "application/x-gsp",
|
||||
".gss": "application/x-gss",
|
||||
".gtar": "application/x-gtar",
|
||||
".gz": "application/x-compressed",
|
||||
".gzip": "application/x-gzip",
|
||||
".h": "text/x-h",
|
||||
".hdf": "application/x-hdf",
|
||||
".help": "application/x-helpfile",
|
||||
".hgl": "application/vndhp-hpgl",
|
||||
".hh": "text/x-h",
|
||||
".hlb": "text/x-script",
|
||||
".hlp": "application/hlp",
|
||||
".hpg": "application/vndhp-hpgl",
|
||||
".hpgl": "application/vndhp-hpgl",
|
||||
".hqx": "application/binhex",
|
||||
".hta": "application/hta",
|
||||
".htc": "text/x-component",
|
||||
".htm": "text/html",
|
||||
".html": "text/html",
|
||||
".htmls": "text/html",
|
||||
".htt": "text/webviewhtml",
|
||||
".htx": "text/html",
|
||||
".ice": "x-conference/x-cooltalk",
|
||||
".ico": "image/x-icon",
|
||||
".ics": "text/calendar",
|
||||
".icz": "text/calendar",
|
||||
".idc": "text/plain",
|
||||
".ief": "image/ief",
|
||||
".iefs": "image/ief",
|
||||
".iges": "application/iges",
|
||||
".igs": "application/iges",
|
||||
".ima": "application/x-ima",
|
||||
".imap": "application/x-httpd-imap",
|
||||
".inf": "application/inf",
|
||||
".ins": "application/x-internett-signup",
|
||||
".ip": "application/x-ip2",
|
||||
".isu": "video/x-isvideo",
|
||||
".it": "audio/it",
|
||||
".iv": "application/x-inventor",
|
||||
".ivr": "i-world/i-vrml",
|
||||
".ivy": "application/x-livescreen",
|
||||
".jam": "audio/x-jam",
|
||||
".jav": "text/x-java-source",
|
||||
".java": "text/x-java-source",
|
||||
".jcm": "application/x-java-commerce",
|
||||
".jfif-tbnl": "image/jpeg",
|
||||
".jfif": "image/jpeg",
|
||||
".jnlp": "application/x-java-jnlp-file",
|
||||
".jpe": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".jpg": "image/jpeg",
|
||||
".jps": "image/x-jps",
|
||||
".js": "application/javascript",
|
||||
".json": "application/json",
|
||||
".jut": "image/jutvision",
|
||||
".kar": "audio/midi",
|
||||
".karbon": "application/vnd.kde.karbon",
|
||||
".kfo": "application/vnd.kde.kformula",
|
||||
".flw": "application/vnd.kde.kivio",
|
||||
".kml": "application/vnd.google-earth.kml+xml",
|
||||
".kmz": "application/vnd.google-earth.kmz",
|
||||
".kon": "application/vnd.kde.kontour",
|
||||
".kpr": "application/vnd.kde.kpresenter",
|
||||
".kpt": "application/vnd.kde.kpresenter",
|
||||
".ksp": "application/vnd.kde.kspread",
|
||||
".kwd": "application/vnd.kde.kword",
|
||||
".kwt": "application/vnd.kde.kword",
|
||||
".ksh": "text/x-scriptksh",
|
||||
".la": "audio/nspaudio",
|
||||
".lam": "audio/x-liveaudio",
|
||||
".latex": "application/x-latex",
|
||||
".lha": "application/lha",
|
||||
".lhx": "application/octet-stream",
|
||||
".list": "text/plain",
|
||||
".lma": "audio/nspaudio",
|
||||
".log": "text/plain",
|
||||
".lsp": "text/x-scriptlisp",
|
||||
".lst": "text/plain",
|
||||
".lsx": "text/x-la-asf",
|
||||
".ltx": "application/x-latex",
|
||||
".lzh": "application/octet-stream",
|
||||
".lzx": "application/lzx",
|
||||
".m1v": "video/mpeg",
|
||||
".m2a": "audio/mpeg",
|
||||
".m2v": "video/mpeg",
|
||||
".m3u": "audio/x-mpegurl",
|
||||
".m": "text/x-m",
|
||||
".man": "application/x-troff-man",
|
||||
".manifest": "text/cache-manifest",
|
||||
".map": "application/x-navimap",
|
||||
".mar": "text/plain",
|
||||
".mbd": "application/mbedlet",
|
||||
".mc$": "application/x-magic-cap-package-10",
|
||||
".mcd": "application/mcad",
|
||||
".mcf": "text/mcf",
|
||||
".mcp": "application/netmc",
|
||||
".me": "application/x-troff-me",
|
||||
".mht": "message/rfc822",
|
||||
".mhtml": "message/rfc822",
|
||||
".mid": "application/x-midi",
|
||||
".midi": "application/x-midi",
|
||||
".mif": "application/x-frame",
|
||||
".mime": "message/rfc822",
|
||||
".mjf": "audio/x-vndaudioexplosionmjuicemediafile",
|
||||
".mjpg": "video/x-motion-jpeg",
|
||||
".mm": "application/base64",
|
||||
".mme": "application/base64",
|
||||
".mod": "audio/mod",
|
||||
".moov": "video/quicktime",
|
||||
".mov": "video/quicktime",
|
||||
".movie": "video/x-sgi-movie",
|
||||
".mp2": "audio/mpeg",
|
||||
".mp3": "audio/mpeg3",
|
||||
".mp4": "video/mp4",
|
||||
".mpa": "audio/mpeg",
|
||||
".mpc": "application/x-project",
|
||||
".mpe": "video/mpeg",
|
||||
".mpeg": "video/mpeg",
|
||||
".mpg": "video/mpeg",
|
||||
".mpga": "audio/mpeg",
|
||||
".mpp": "application/vndms-project",
|
||||
".mpt": "application/x-project",
|
||||
".mpv": "application/x-project",
|
||||
".mpx": "application/x-project",
|
||||
".mrc": "application/marc",
|
||||
".ms": "application/x-troff-ms",
|
||||
".mv": "video/x-sgi-movie",
|
||||
".my": "audio/make",
|
||||
".mzz": "application/x-vndaudioexplosionmzz",
|
||||
".nap": "image/naplps",
|
||||
".naplps": "image/naplps",
|
||||
".nc": "application/x-netcdf",
|
||||
".ncm": "application/vndnokiaconfiguration-message",
|
||||
".nif": "image/x-niff",
|
||||
".niff": "image/x-niff",
|
||||
".nix": "application/x-mix-transfer",
|
||||
".nsc": "application/x-conference",
|
||||
".nvd": "application/x-navidoc",
|
||||
".o": "application/octet-stream",
|
||||
".oda": "application/oda",
|
||||
".odb": "application/vnd.oasis.opendocument.database",
|
||||
".odc": "application/vnd.oasis.opendocument.chart",
|
||||
".odf": "application/vnd.oasis.opendocument.formula",
|
||||
".odg": "application/vnd.oasis.opendocument.graphics",
|
||||
".odi": "application/vnd.oasis.opendocument.image",
|
||||
".odm": "application/vnd.oasis.opendocument.text-master",
|
||||
".odp": "application/vnd.oasis.opendocument.presentation",
|
||||
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
||||
".odt": "application/vnd.oasis.opendocument.text",
|
||||
".oga": "audio/ogg",
|
||||
".ogg": "audio/ogg",
|
||||
".ogv": "video/ogg",
|
||||
".omc": "application/x-omc",
|
||||
".omcd": "application/x-omcdatamaker",
|
||||
".omcr": "application/x-omcregerator",
|
||||
".otc": "application/vnd.oasis.opendocument.chart-template",
|
||||
".otf": "application/vnd.oasis.opendocument.formula-template",
|
||||
".otg": "application/vnd.oasis.opendocument.graphics-template",
|
||||
".oth": "application/vnd.oasis.opendocument.text-web",
|
||||
".oti": "application/vnd.oasis.opendocument.image-template",
|
||||
".otm": "application/vnd.oasis.opendocument.text-master",
|
||||
".otp": "application/vnd.oasis.opendocument.presentation-template",
|
||||
".ots": "application/vnd.oasis.opendocument.spreadsheet-template",
|
||||
".ott": "application/vnd.oasis.opendocument.text-template",
|
||||
".p10": "application/pkcs10",
|
||||
".p12": "application/pkcs-12",
|
||||
".p7a": "application/x-pkcs7-signature",
|
||||
".p7c": "application/pkcs7-mime",
|
||||
".p7m": "application/pkcs7-mime",
|
||||
".p7r": "application/x-pkcs7-certreqresp",
|
||||
".p7s": "application/pkcs7-signature",
|
||||
".p": "text/x-pascal",
|
||||
".part": "application/pro_eng",
|
||||
".pas": "text/pascal",
|
||||
".pbm": "image/x-portable-bitmap",
|
||||
".pcl": "application/vndhp-pcl",
|
||||
".pct": "image/x-pict",
|
||||
".pcx": "image/x-pcx",
|
||||
".pdb": "chemical/x-pdb",
|
||||
".pdf": "application/pdf",
|
||||
".pfunk": "audio/make",
|
||||
".pgm": "image/x-portable-graymap",
|
||||
".pic": "image/pict",
|
||||
".pict": "image/pict",
|
||||
".pkg": "application/x-newton-compatible-pkg",
|
||||
".pko": "application/vndms-pkipko",
|
||||
".pl": "text/x-scriptperl",
|
||||
".plx": "application/x-pixclscript",
|
||||
".pm4": "application/x-pagemaker",
|
||||
".pm5": "application/x-pagemaker",
|
||||
".pm": "text/x-scriptperl-module",
|
||||
".png": "image/png",
|
||||
".pnm": "application/x-portable-anymap",
|
||||
".pot": "application/mspowerpoint",
|
||||
".pov": "model/x-pov",
|
||||
".ppa": "application/vndms-powerpoint",
|
||||
".ppm": "image/x-portable-pixmap",
|
||||
".pps": "application/mspowerpoint",
|
||||
".ppt": "application/mspowerpoint",
|
||||
".ppz": "application/mspowerpoint",
|
||||
".pre": "application/x-freelance",
|
||||
".prt": "application/pro_eng",
|
||||
".ps": "application/postscript",
|
||||
".psd": "application/octet-stream",
|
||||
".pvu": "paleovu/x-pv",
|
||||
".pwz": "application/vndms-powerpoint",
|
||||
".py": "text/x-scriptphyton",
|
||||
".pyc": "application/x-bytecodepython",
|
||||
".qcp": "audio/vndqcelp",
|
||||
".qd3": "x-world/x-3dmf",
|
||||
".qd3d": "x-world/x-3dmf",
|
||||
".qif": "image/x-quicktime",
|
||||
".qt": "video/quicktime",
|
||||
".qtc": "video/x-qtc",
|
||||
".qti": "image/x-quicktime",
|
||||
".qtif": "image/x-quicktime",
|
||||
".ra": "audio/x-pn-realaudio",
|
||||
".ram": "audio/x-pn-realaudio",
|
||||
".rar": "application/x-rar-compressed",
|
||||
".ras": "application/x-cmu-raster",
|
||||
".rast": "image/cmu-raster",
|
||||
".rexx": "text/x-scriptrexx",
|
||||
".rf": "image/vndrn-realflash",
|
||||
".rgb": "image/x-rgb",
|
||||
".rm": "application/vndrn-realmedia",
|
||||
".rmi": "audio/mid",
|
||||
".rmm": "audio/x-pn-realaudio",
|
||||
".rmp": "audio/x-pn-realaudio",
|
||||
".rng": "application/ringing-tones",
|
||||
".rnx": "application/vndrn-realplayer",
|
||||
".roff": "application/x-troff",
|
||||
".rp": "image/vndrn-realpix",
|
||||
".rpm": "audio/x-pn-realaudio-plugin",
|
||||
".rt": "text/vndrn-realtext",
|
||||
".rtf": "text/richtext",
|
||||
".rtx": "text/richtext",
|
||||
".rv": "video/vndrn-realvideo",
|
||||
".s": "text/x-asm",
|
||||
".s3m": "audio/s3m",
|
||||
".s7z": "application/x-7z-compressed",
|
||||
".saveme": "application/octet-stream",
|
||||
".sbk": "application/x-tbook",
|
||||
".scm": "text/x-scriptscheme",
|
||||
".sdml": "text/plain",
|
||||
".sdp": "application/sdp",
|
||||
".sdr": "application/sounder",
|
||||
".sea": "application/sea",
|
||||
".set": "application/set",
|
||||
".sgm": "text/x-sgml",
|
||||
".sgml": "text/x-sgml",
|
||||
".sh": "text/x-scriptsh",
|
||||
".shar": "application/x-bsh",
|
||||
".shtml": "text/x-server-parsed-html",
|
||||
".sid": "audio/x-psid",
|
||||
".skd": "application/x-koan",
|
||||
".skm": "application/x-koan",
|
||||
".skp": "application/x-koan",
|
||||
".skt": "application/x-koan",
|
||||
".sit": "application/x-stuffit",
|
||||
".sitx": "application/x-stuffitx",
|
||||
".sl": "application/x-seelogo",
|
||||
".smi": "application/smil",
|
||||
".smil": "application/smil",
|
||||
".snd": "audio/basic",
|
||||
".sol": "application/solids",
|
||||
".spc": "text/x-speech",
|
||||
".spl": "application/futuresplash",
|
||||
".spr": "application/x-sprite",
|
||||
".sprite": "application/x-sprite",
|
||||
".spx": "audio/ogg",
|
||||
".src": "application/x-wais-source",
|
||||
".ssi": "text/x-server-parsed-html",
|
||||
".ssm": "application/streamingmedia",
|
||||
".sst": "application/vndms-pkicertstore",
|
||||
".step": "application/step",
|
||||
".stl": "application/sla",
|
||||
".stp": "application/step",
|
||||
".sv4cpio": "application/x-sv4cpio",
|
||||
".sv4crc": "application/x-sv4crc",
|
||||
".svf": "image/vnddwg",
|
||||
".svg": "image/svg+xml",
|
||||
".svr": "application/x-world",
|
||||
".swf": "application/x-shockwave-flash",
|
||||
".t": "application/x-troff",
|
||||
".talk": "text/x-speech",
|
||||
".tar": "application/x-tar",
|
||||
".tbk": "application/toolbook",
|
||||
".tcl": "text/x-scripttcl",
|
||||
".tcsh": "text/x-scripttcsh",
|
||||
".tex": "application/x-tex",
|
||||
".texi": "application/x-texinfo",
|
||||
".texinfo": "application/x-texinfo",
|
||||
".text": "text/plain",
|
||||
".tgz": "application/gnutar",
|
||||
".tif": "image/tiff",
|
||||
".tiff": "image/tiff",
|
||||
".tr": "application/x-troff",
|
||||
".tsi": "audio/tsp-audio",
|
||||
".tsp": "application/dsptype",
|
||||
".tsv": "text/tab-separated-values",
|
||||
".turbot": "image/florian",
|
||||
".txt": "text/plain",
|
||||
".uil": "text/x-uil",
|
||||
".uni": "text/uri-list",
|
||||
".unis": "text/uri-list",
|
||||
".unv": "application/i-deas",
|
||||
".uri": "text/uri-list",
|
||||
".uris": "text/uri-list",
|
||||
".ustar": "application/x-ustar",
|
||||
".uu": "text/x-uuencode",
|
||||
".uue": "text/x-uuencode",
|
||||
".vcd": "application/x-cdlink",
|
||||
".vcf": "text/x-vcard",
|
||||
".vcard": "text/x-vcard",
|
||||
".vcs": "text/x-vcalendar",
|
||||
".vda": "application/vda",
|
||||
".vdo": "video/vdo",
|
||||
".vew": "application/groupwise",
|
||||
".viv": "video/vivo",
|
||||
".vivo": "video/vivo",
|
||||
".vmd": "application/vocaltec-media-desc",
|
||||
".vmf": "application/vocaltec-media-file",
|
||||
".voc": "audio/voc",
|
||||
".vos": "video/vosaic",
|
||||
".vox": "audio/voxware",
|
||||
".vqe": "audio/x-twinvq-plugin",
|
||||
".vqf": "audio/x-twinvq",
|
||||
".vql": "audio/x-twinvq-plugin",
|
||||
".vrml": "application/x-vrml",
|
||||
".vrt": "x-world/x-vrt",
|
||||
".vsd": "application/x-visio",
|
||||
".vst": "application/x-visio",
|
||||
".vsw": "application/x-visio",
|
||||
".w60": "application/wordperfect60",
|
||||
".w61": "application/wordperfect61",
|
||||
".w6w": "application/msword",
|
||||
".wav": "audio/wav",
|
||||
".wb1": "application/x-qpro",
|
||||
".wbmp": "image/vnd.wap.wbmp",
|
||||
".web": "application/vndxara",
|
||||
".wiz": "application/msword",
|
||||
".wk1": "application/x-123",
|
||||
".wmf": "windows/metafile",
|
||||
".wml": "text/vnd.wap.wml",
|
||||
".wmlc": "application/vnd.wap.wmlc",
|
||||
".wmls": "text/vnd.wap.wmlscript",
|
||||
".wmlsc": "application/vnd.wap.wmlscriptc",
|
||||
".word": "application/msword",
|
||||
".wp5": "application/wordperfect",
|
||||
".wp6": "application/wordperfect",
|
||||
".wp": "application/wordperfect",
|
||||
".wpd": "application/wordperfect",
|
||||
".wq1": "application/x-lotus",
|
||||
".wri": "application/mswrite",
|
||||
".wrl": "application/x-world",
|
||||
".wrz": "model/vrml",
|
||||
".wsc": "text/scriplet",
|
||||
".wsrc": "application/x-wais-source",
|
||||
".wtk": "application/x-wintalk",
|
||||
".x-png": "image/png",
|
||||
".xbm": "image/x-xbitmap",
|
||||
".xdr": "video/x-amt-demorun",
|
||||
".xgz": "xgl/drawing",
|
||||
".xif": "image/vndxiff",
|
||||
".xl": "application/excel",
|
||||
".xla": "application/excel",
|
||||
".xlb": "application/excel",
|
||||
".xlc": "application/excel",
|
||||
".xld": "application/excel",
|
||||
".xlk": "application/excel",
|
||||
".xll": "application/excel",
|
||||
".xlm": "application/excel",
|
||||
".xls": "application/excel",
|
||||
".xlt": "application/excel",
|
||||
".xlv": "application/excel",
|
||||
".xlw": "application/excel",
|
||||
".xm": "audio/xm",
|
||||
".xml": "text/xml",
|
||||
".xmz": "xgl/movie",
|
||||
".xpix": "application/x-vndls-xpix",
|
||||
".xpm": "image/x-xpixmap",
|
||||
".xsr": "video/x-amt-showrun",
|
||||
".xwd": "image/x-xwd",
|
||||
".xyz": "chemical/x-pdb",
|
||||
".z": "application/x-compress",
|
||||
".zip": "application/zip",
|
||||
".zoo": "application/octet-stream",
|
||||
".zsh": "text/x-scriptzsh",
|
||||
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
".docm": "application/vnd.ms-word.document.macroEnabled.12",
|
||||
".dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
||||
".dotm": "application/vnd.ms-word.template.macroEnabled.12",
|
||||
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
".xlsm": "application/vnd.ms-excel.sheet.macroEnabled.12",
|
||||
".xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
||||
".xltm": "application/vnd.ms-excel.template.macroEnabled.12",
|
||||
".xlsb": "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
||||
".xlam": "application/vnd.ms-excel.addin.macroEnabled.12",
|
||||
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
".pptm": "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
||||
".ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
||||
".ppsm": "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
|
||||
".potx": "application/vnd.openxmlformats-officedocument.presentationml.template",
|
||||
".potm": "application/vnd.ms-powerpoint.template.macroEnabled.12",
|
||||
".ppam": "application/vnd.ms-powerpoint.addin.macroEnabled.12",
|
||||
".sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide",
|
||||
".sldm": "application/vnd.ms-powerpoint.slide.macroEnabled.12",
|
||||
".thmx": "application/vnd.ms-officetheme",
|
||||
".onetoc": "application/onenote",
|
||||
".onetoc2": "application/onenote",
|
||||
".onetmp": "application/onenote",
|
||||
".onepkg": "application/onenote",
|
||||
".key": "application/x-iwork-keynote-sffkey",
|
||||
".kth": "application/x-iwork-keynote-sffkth",
|
||||
".nmbtemplate": "application/x-iwork-numbers-sfftemplate",
|
||||
".numbers": "application/x-iwork-numbers-sffnumbers",
|
||||
".pages": "application/x-iwork-pages-sffpages",
|
||||
".template": "application/x-iwork-pages-sfftemplate",
|
||||
".xpi": "application/x-xpinstall",
|
||||
".oex": "application/x-opera-extension",
|
||||
".mustache": "text/html",
|
||||
}
|
||||
397
vendor/github.com/fatedier/beego/namespace.go
generated
vendored
Normal file
397
vendor/github.com/fatedier/beego/namespace.go
generated
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
beecontext "github.com/astaxie/beego/context"
|
||||
)
|
||||
|
||||
type namespaceCond func(*beecontext.Context) bool
|
||||
|
||||
// LinkNamespace used as link action
|
||||
type LinkNamespace func(*Namespace)
|
||||
|
||||
// Namespace is store all the info
|
||||
type Namespace struct {
|
||||
prefix string
|
||||
handlers *ControllerRegister
|
||||
}
|
||||
|
||||
// NewNamespace get new Namespace
|
||||
func NewNamespace(prefix string, params ...LinkNamespace) *Namespace {
|
||||
ns := &Namespace{
|
||||
prefix: prefix,
|
||||
handlers: NewControllerRegister(),
|
||||
}
|
||||
for _, p := range params {
|
||||
p(ns)
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// Cond set condition function
|
||||
// if cond return true can run this namespace, else can't
|
||||
// usage:
|
||||
// ns.Cond(func (ctx *context.Context) bool{
|
||||
// if ctx.Input.Domain() == "api.beego.me" {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// })
|
||||
// Cond as the first filter
|
||||
func (n *Namespace) Cond(cond namespaceCond) *Namespace {
|
||||
fn := func(ctx *beecontext.Context) {
|
||||
if !cond(ctx) {
|
||||
exception("405", ctx)
|
||||
}
|
||||
}
|
||||
if v := n.handlers.filters[BeforeRouter]; len(v) > 0 {
|
||||
mr := new(FilterRouter)
|
||||
mr.tree = NewTree()
|
||||
mr.pattern = "*"
|
||||
mr.filterFunc = fn
|
||||
mr.tree.AddRouter("*", true)
|
||||
n.handlers.filters[BeforeRouter] = append([]*FilterRouter{mr}, v...)
|
||||
} else {
|
||||
n.handlers.InsertFilter("*", BeforeRouter, fn)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Filter add filter in the Namespace
|
||||
// action has before & after
|
||||
// FilterFunc
|
||||
// usage:
|
||||
// Filter("before", func (ctx *context.Context){
|
||||
// _, ok := ctx.Input.Session("uid").(int)
|
||||
// if !ok && ctx.Request.RequestURI != "/login" {
|
||||
// ctx.Redirect(302, "/login")
|
||||
// }
|
||||
// })
|
||||
func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace {
|
||||
var a int
|
||||
if action == "before" {
|
||||
a = BeforeRouter
|
||||
} else if action == "after" {
|
||||
a = FinishRouter
|
||||
}
|
||||
for _, f := range filter {
|
||||
n.handlers.InsertFilter("*", a, f)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Router same as beego.Rourer
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Router
|
||||
func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace {
|
||||
n.handlers.Add(rootpath, c, mappingMethods...)
|
||||
return n
|
||||
}
|
||||
|
||||
// AutoRouter same as beego.AutoRouter
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#AutoRouter
|
||||
func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace {
|
||||
n.handlers.AddAuto(c)
|
||||
return n
|
||||
}
|
||||
|
||||
// AutoPrefix same as beego.AutoPrefix
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#AutoPrefix
|
||||
func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace {
|
||||
n.handlers.AddAutoPrefix(prefix, c)
|
||||
return n
|
||||
}
|
||||
|
||||
// Get same as beego.Get
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Get
|
||||
func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Get(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Post same as beego.Post
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Post
|
||||
func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Post(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Delete same as beego.Delete
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Delete
|
||||
func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Delete(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Put same as beego.Put
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Put
|
||||
func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Put(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Head same as beego.Head
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Head
|
||||
func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Head(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Options same as beego.Options
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Options
|
||||
func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Options(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Patch same as beego.Patch
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Patch
|
||||
func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Patch(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Any same as beego.Any
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Any
|
||||
func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace {
|
||||
n.handlers.Any(rootpath, f)
|
||||
return n
|
||||
}
|
||||
|
||||
// Handler same as beego.Handler
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Handler
|
||||
func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace {
|
||||
n.handlers.Handler(rootpath, h)
|
||||
return n
|
||||
}
|
||||
|
||||
// Include add include class
|
||||
// refer: https://godoc.org/github.com/astaxie/beego#Include
|
||||
func (n *Namespace) Include(cList ...ControllerInterface) *Namespace {
|
||||
n.handlers.Include(cList...)
|
||||
return n
|
||||
}
|
||||
|
||||
// Namespace add nest Namespace
|
||||
// usage:
|
||||
//ns := beego.NewNamespace(“/v1”).
|
||||
//Namespace(
|
||||
// beego.NewNamespace("/shop").
|
||||
// Get("/:id", func(ctx *context.Context) {
|
||||
// ctx.Output.Body([]byte("shopinfo"))
|
||||
// }),
|
||||
// beego.NewNamespace("/order").
|
||||
// Get("/:id", func(ctx *context.Context) {
|
||||
// ctx.Output.Body([]byte("orderinfo"))
|
||||
// }),
|
||||
// beego.NewNamespace("/crm").
|
||||
// Get("/:id", func(ctx *context.Context) {
|
||||
// ctx.Output.Body([]byte("crminfo"))
|
||||
// }),
|
||||
//)
|
||||
func (n *Namespace) Namespace(ns ...*Namespace) *Namespace {
|
||||
for _, ni := range ns {
|
||||
for k, v := range ni.handlers.routers {
|
||||
if t, ok := n.handlers.routers[k]; ok {
|
||||
addPrefix(v, ni.prefix)
|
||||
n.handlers.routers[k].AddTree(ni.prefix, v)
|
||||
} else {
|
||||
t = NewTree()
|
||||
t.AddTree(ni.prefix, v)
|
||||
addPrefix(t, ni.prefix)
|
||||
n.handlers.routers[k] = t
|
||||
}
|
||||
}
|
||||
if ni.handlers.enableFilter {
|
||||
for pos, filterList := range ni.handlers.filters {
|
||||
for _, mr := range filterList {
|
||||
t := NewTree()
|
||||
t.AddTree(ni.prefix, mr.tree)
|
||||
mr.tree = t
|
||||
n.handlers.insertFilterRouter(pos, mr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// AddNamespace register Namespace into beego.Handler
|
||||
// support multi Namespace
|
||||
func AddNamespace(nl ...*Namespace) {
|
||||
for _, n := range nl {
|
||||
for k, v := range n.handlers.routers {
|
||||
if t, ok := BeeApp.Handlers.routers[k]; ok {
|
||||
addPrefix(v, n.prefix)
|
||||
BeeApp.Handlers.routers[k].AddTree(n.prefix, v)
|
||||
} else {
|
||||
t = NewTree()
|
||||
t.AddTree(n.prefix, v)
|
||||
addPrefix(t, n.prefix)
|
||||
BeeApp.Handlers.routers[k] = t
|
||||
}
|
||||
}
|
||||
if n.handlers.enableFilter {
|
||||
for pos, filterList := range n.handlers.filters {
|
||||
for _, mr := range filterList {
|
||||
t := NewTree()
|
||||
t.AddTree(n.prefix, mr.tree)
|
||||
mr.tree = t
|
||||
BeeApp.Handlers.insertFilterRouter(pos, mr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addPrefix(t *Tree, prefix string) {
|
||||
for _, v := range t.fixrouters {
|
||||
addPrefix(v, prefix)
|
||||
}
|
||||
if t.wildcard != nil {
|
||||
addPrefix(t.wildcard, prefix)
|
||||
}
|
||||
for _, l := range t.leaves {
|
||||
if c, ok := l.runObject.(*controllerInfo); ok {
|
||||
if !strings.HasPrefix(c.pattern, prefix) {
|
||||
c.pattern = prefix + c.pattern
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// NSCond is Namespace Condition
|
||||
func NSCond(cond namespaceCond) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Cond(cond)
|
||||
}
|
||||
}
|
||||
|
||||
// NSBefore Namespace BeforeRouter filter
|
||||
func NSBefore(filiterList ...FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Filter("before", filiterList...)
|
||||
}
|
||||
}
|
||||
|
||||
// NSAfter add Namespace FinishRouter filter
|
||||
func NSAfter(filiterList ...FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Filter("after", filiterList...)
|
||||
}
|
||||
}
|
||||
|
||||
// NSInclude Namespace Include ControllerInterface
|
||||
func NSInclude(cList ...ControllerInterface) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Include(cList...)
|
||||
}
|
||||
}
|
||||
|
||||
// NSRouter call Namespace Router
|
||||
func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Router(rootpath, c, mappingMethods...)
|
||||
}
|
||||
}
|
||||
|
||||
// NSGet call Namespace Get
|
||||
func NSGet(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Get(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSPost call Namespace Post
|
||||
func NSPost(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Post(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSHead call Namespace Head
|
||||
func NSHead(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Head(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSPut call Namespace Put
|
||||
func NSPut(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Put(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSDelete call Namespace Delete
|
||||
func NSDelete(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Delete(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSAny call Namespace Any
|
||||
func NSAny(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Any(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSOptions call Namespace Options
|
||||
func NSOptions(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Options(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSPatch call Namespace Patch
|
||||
func NSPatch(rootpath string, f FilterFunc) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Patch(rootpath, f)
|
||||
}
|
||||
}
|
||||
|
||||
// NSAutoRouter call Namespace AutoRouter
|
||||
func NSAutoRouter(c ControllerInterface) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.AutoRouter(c)
|
||||
}
|
||||
}
|
||||
|
||||
// NSAutoPrefix call Namespace AutoPrefix
|
||||
func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.AutoPrefix(prefix, c)
|
||||
}
|
||||
}
|
||||
|
||||
// NSNamespace add sub Namespace
|
||||
func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
n := NewNamespace(prefix, params...)
|
||||
ns.Namespace(n)
|
||||
}
|
||||
}
|
||||
|
||||
// NSHandler add handler
|
||||
func NSHandler(rootpath string, h http.Handler) LinkNamespace {
|
||||
return func(ns *Namespace) {
|
||||
ns.Handler(rootpath, h)
|
||||
}
|
||||
}
|
||||
171
vendor/github.com/fatedier/beego/namespace_test.go
generated
vendored
Normal file
171
vendor/github.com/fatedier/beego/namespace_test.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package beego
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego/context"
|
||||
)
|
||||
|
||||
func TestNamespaceGet(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/user", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Get("/user", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte("v1_user"))
|
||||
})
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "v1_user" {
|
||||
t.Errorf("TestNamespaceGet can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespacePost(t *testing.T) {
|
||||
r, _ := http.NewRequest("POST", "/v1/user/123", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Post("/user/:id", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
|
||||
})
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "123" {
|
||||
t.Errorf("TestNamespacePost can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceNest(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/admin/order", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Namespace(
|
||||
NewNamespace("/admin").
|
||||
Get("/order", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte("order"))
|
||||
}),
|
||||
)
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "order" {
|
||||
t.Errorf("TestNamespaceNest can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceNestParam(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/admin/order/123", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Namespace(
|
||||
NewNamespace("/admin").
|
||||
Get("/order/:id", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
|
||||
}),
|
||||
)
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "123" {
|
||||
t.Errorf("TestNamespaceNestParam can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceRouter(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/api/list", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Router("/api/list", &TestController{}, "*:List")
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "i am list" {
|
||||
t.Errorf("TestNamespaceRouter can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceAutoFunc(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/test/list", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.AutoRouter(&TestController{})
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "i am list" {
|
||||
t.Errorf("user define func can't run")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceFilter(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v1/user/123", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v1")
|
||||
ns.Filter("before", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte("this is Filter"))
|
||||
}).
|
||||
Get("/user/:id", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
|
||||
})
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "this is Filter" {
|
||||
t.Errorf("TestNamespaceFilter can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceCond(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v2/test/list", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
ns := NewNamespace("/v2")
|
||||
ns.Cond(func(ctx *context.Context) bool {
|
||||
if ctx.Input.Domain() == "beego.me" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}).
|
||||
AutoRouter(&TestController{})
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Code != 405 {
|
||||
t.Errorf("TestNamespaceCond can't run get the result " + strconv.Itoa(w.Code))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceInside(t *testing.T) {
|
||||
r, _ := http.NewRequest("GET", "/v3/shop/order/123", nil)
|
||||
w := httptest.NewRecorder()
|
||||
ns := NewNamespace("/v3",
|
||||
NSAutoRouter(&TestController{}),
|
||||
NSNamespace("/shop",
|
||||
NSGet("/order/:id", func(ctx *context.Context) {
|
||||
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
|
||||
}),
|
||||
),
|
||||
)
|
||||
AddNamespace(ns)
|
||||
BeeApp.Handlers.ServeHTTP(w, r)
|
||||
if w.Body.String() != "123" {
|
||||
t.Errorf("TestNamespaceInside can't run, get the response is " + w.Body.String())
|
||||
}
|
||||
}
|
||||
156
vendor/github.com/fatedier/beego/orm/README.md
generated
vendored
Normal file
156
vendor/github.com/fatedier/beego/orm/README.md
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
# beego orm
|
||||
|
||||
[](https://drone.io/github.com/astaxie/beego/latest)
|
||||
|
||||
A powerful orm framework for go.
|
||||
|
||||
It is heavily influenced by Django ORM, SQLAlchemy.
|
||||
|
||||
**Support Database:**
|
||||
|
||||
* MySQL: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
|
||||
* PostgreSQL: [github.com/lib/pq](https://github.com/lib/pq)
|
||||
* Sqlite3: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
||||
|
||||
Passed all test, but need more feedback.
|
||||
|
||||
**Features:**
|
||||
|
||||
* full go type support
|
||||
* easy for usage, simple CRUD operation
|
||||
* auto join with relation table
|
||||
* cross DataBase compatible query
|
||||
* Raw SQL query / mapper without orm model
|
||||
* full test keep stable and strong
|
||||
|
||||
more features please read the docs
|
||||
|
||||
**Install:**
|
||||
|
||||
go get github.com/astaxie/beego/orm
|
||||
|
||||
## Changelog
|
||||
|
||||
* 2013-08-19: support table auto create
|
||||
* 2013-08-13: update test for database types
|
||||
* 2013-08-13: go type support, such as int8, uint8, byte, rune
|
||||
* 2013-08-13: date / datetime timezone support very well
|
||||
|
||||
## Quick Start
|
||||
|
||||
#### Simple Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/orm"
|
||||
_ "github.com/go-sql-driver/mysql" // import your used driver
|
||||
)
|
||||
|
||||
// Model Struct
|
||||
type User struct {
|
||||
Id int `orm:"auto"`
|
||||
Name string `orm:"size(100)"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// register model
|
||||
orm.RegisterModel(new(User))
|
||||
|
||||
// set default database
|
||||
orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30)
|
||||
}
|
||||
|
||||
func main() {
|
||||
o := orm.NewOrm()
|
||||
|
||||
user := User{Name: "slene"}
|
||||
|
||||
// insert
|
||||
id, err := o.Insert(&user)
|
||||
|
||||
// update
|
||||
user.Name = "astaxie"
|
||||
num, err := o.Update(&user)
|
||||
|
||||
// read one
|
||||
u := User{Id: user.Id}
|
||||
err = o.Read(&u)
|
||||
|
||||
// delete
|
||||
num, err = o.Delete(&u)
|
||||
}
|
||||
```
|
||||
|
||||
#### Next with relation
|
||||
|
||||
```go
|
||||
type Post struct {
|
||||
Id int `orm:"auto"`
|
||||
Title string `orm:"size(100)"`
|
||||
User *User `orm:"rel(fk)"`
|
||||
}
|
||||
|
||||
var posts []*Post
|
||||
qs := o.QueryTable("post")
|
||||
num, err := qs.Filter("User__Name", "slene").All(&posts)
|
||||
```
|
||||
|
||||
#### Use Raw sql
|
||||
|
||||
If you don't like ORM,use Raw SQL to query / mapping without ORM setting
|
||||
|
||||
```go
|
||||
var maps []Params
|
||||
num, err := o.Raw("SELECT id FROM user WHERE name = ?", "slene").Values(&maps)
|
||||
if num > 0 {
|
||||
fmt.Println(maps[0]["id"])
|
||||
}
|
||||
```
|
||||
|
||||
#### Transaction
|
||||
|
||||
```go
|
||||
o.Begin()
|
||||
...
|
||||
user := User{Name: "slene"}
|
||||
id, err := o.Insert(&user)
|
||||
if err == nil {
|
||||
o.Commit()
|
||||
} else {
|
||||
o.Rollback()
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Debug Log Queries
|
||||
|
||||
In development env, you can simple use
|
||||
|
||||
```go
|
||||
func main() {
|
||||
orm.Debug = true
|
||||
...
|
||||
```
|
||||
|
||||
enable log queries.
|
||||
|
||||
output include all queries, such as exec / prepare / transaction.
|
||||
|
||||
like this:
|
||||
|
||||
```go
|
||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `user` (`name`) VALUES (?)] - `slene`
|
||||
...
|
||||
```
|
||||
|
||||
note: not recommend use this in product env.
|
||||
|
||||
## Docs
|
||||
|
||||
more details and examples in docs and test
|
||||
|
||||
[documents](http://beego.me/docs/mvc/model/overview.md)
|
||||
|
||||
283
vendor/github.com/fatedier/beego/orm/cmd.go
generated
vendored
Normal file
283
vendor/github.com/fatedier/beego/orm/cmd.go
generated
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type commander interface {
|
||||
Parse([]string)
|
||||
Run() error
|
||||
}
|
||||
|
||||
var (
|
||||
commands = make(map[string]commander)
|
||||
)
|
||||
|
||||
// print help.
|
||||
func printHelp(errs ...string) {
|
||||
content := `orm command usage:
|
||||
|
||||
syncdb - auto create tables
|
||||
sqlall - print sql of create tables
|
||||
help - print this help
|
||||
`
|
||||
|
||||
if len(errs) > 0 {
|
||||
fmt.Println(errs[0])
|
||||
}
|
||||
fmt.Println(content)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// RunCommand listen for orm command and then run it if command arguments passed.
|
||||
func RunCommand() {
|
||||
if len(os.Args) < 2 || os.Args[1] != "orm" {
|
||||
return
|
||||
}
|
||||
|
||||
BootStrap()
|
||||
|
||||
args := argString(os.Args[2:])
|
||||
name := args.Get(0)
|
||||
|
||||
if name == "help" {
|
||||
printHelp()
|
||||
}
|
||||
|
||||
if cmd, ok := commands[name]; ok {
|
||||
cmd.Parse(os.Args[3:])
|
||||
cmd.Run()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if name == "" {
|
||||
printHelp()
|
||||
} else {
|
||||
printHelp(fmt.Sprintf("unknown command %s", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sync database struct command interface.
|
||||
type commandSyncDb struct {
|
||||
al *alias
|
||||
force bool
|
||||
verbose bool
|
||||
noInfo bool
|
||||
rtOnError bool
|
||||
}
|
||||
|
||||
// parse orm command line arguments.
|
||||
func (d *commandSyncDb) Parse(args []string) {
|
||||
var name string
|
||||
|
||||
flagSet := flag.NewFlagSet("orm command: syncdb", flag.ExitOnError)
|
||||
flagSet.StringVar(&name, "db", "default", "DataBase alias name")
|
||||
flagSet.BoolVar(&d.force, "force", false, "drop tables before create")
|
||||
flagSet.BoolVar(&d.verbose, "v", false, "verbose info")
|
||||
flagSet.Parse(args)
|
||||
|
||||
d.al = getDbAlias(name)
|
||||
}
|
||||
|
||||
// run orm line command.
|
||||
func (d *commandSyncDb) Run() error {
|
||||
var drops []string
|
||||
if d.force {
|
||||
drops = getDbDropSQL(d.al)
|
||||
}
|
||||
|
||||
db := d.al.DB
|
||||
|
||||
if d.force {
|
||||
for i, mi := range modelCache.allOrdered() {
|
||||
query := drops[i]
|
||||
if !d.noInfo {
|
||||
fmt.Printf("drop table `%s`\n", mi.table)
|
||||
}
|
||||
_, err := db.Exec(query)
|
||||
if d.verbose {
|
||||
fmt.Printf(" %s\n\n", query)
|
||||
}
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqls, indexes := getDbCreateSQL(d.al)
|
||||
|
||||
tables, err := d.al.DbBaser.GetTables(db)
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
|
||||
for i, mi := range modelCache.allOrdered() {
|
||||
if tables[mi.table] {
|
||||
if !d.noInfo {
|
||||
fmt.Printf("table `%s` already exists, skip\n", mi.table)
|
||||
}
|
||||
|
||||
var fields []*fieldInfo
|
||||
columns, err := d.al.DbBaser.GetColumns(db, mi.table)
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
|
||||
for _, fi := range mi.fields.fieldsDB {
|
||||
if _, ok := columns[fi.column]; ok == false {
|
||||
fields = append(fields, fi)
|
||||
}
|
||||
}
|
||||
|
||||
for _, fi := range fields {
|
||||
query := getColumnAddQuery(d.al, fi)
|
||||
|
||||
if !d.noInfo {
|
||||
fmt.Printf("add column `%s` for table `%s`\n", fi.fullName, mi.table)
|
||||
}
|
||||
|
||||
_, err := db.Exec(query)
|
||||
if d.verbose {
|
||||
fmt.Printf(" %s\n", query)
|
||||
}
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, idx := range indexes[mi.table] {
|
||||
if d.al.DbBaser.IndexExists(db, idx.Table, idx.Name) == false {
|
||||
if !d.noInfo {
|
||||
fmt.Printf("create index `%s` for table `%s`\n", idx.Name, idx.Table)
|
||||
}
|
||||
|
||||
query := idx.SQL
|
||||
_, err := db.Exec(query)
|
||||
if d.verbose {
|
||||
fmt.Printf(" %s\n", query)
|
||||
}
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !d.noInfo {
|
||||
fmt.Printf("create table `%s` \n", mi.table)
|
||||
}
|
||||
|
||||
queries := []string{sqls[i]}
|
||||
for _, idx := range indexes[mi.table] {
|
||||
queries = append(queries, idx.SQL)
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
_, err := db.Exec(query)
|
||||
if d.verbose {
|
||||
query = " " + strings.Join(strings.Split(query, "\n"), "\n ")
|
||||
fmt.Println(query)
|
||||
}
|
||||
if err != nil {
|
||||
if d.rtOnError {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
if d.verbose {
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// database creation commander interface implement.
|
||||
type commandSQLAll struct {
|
||||
al *alias
|
||||
}
|
||||
|
||||
// parse orm command line arguments.
|
||||
func (d *commandSQLAll) Parse(args []string) {
|
||||
var name string
|
||||
|
||||
flagSet := flag.NewFlagSet("orm command: sqlall", flag.ExitOnError)
|
||||
flagSet.StringVar(&name, "db", "default", "DataBase alias name")
|
||||
flagSet.Parse(args)
|
||||
|
||||
d.al = getDbAlias(name)
|
||||
}
|
||||
|
||||
// run orm line command.
|
||||
func (d *commandSQLAll) Run() error {
|
||||
sqls, indexes := getDbCreateSQL(d.al)
|
||||
var all []string
|
||||
for i, mi := range modelCache.allOrdered() {
|
||||
queries := []string{sqls[i]}
|
||||
for _, idx := range indexes[mi.table] {
|
||||
queries = append(queries, idx.SQL)
|
||||
}
|
||||
sql := strings.Join(queries, "\n")
|
||||
all = append(all, sql)
|
||||
}
|
||||
fmt.Println(strings.Join(all, "\n\n"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
commands["syncdb"] = new(commandSyncDb)
|
||||
commands["sqlall"] = new(commandSQLAll)
|
||||
}
|
||||
|
||||
// RunSyncdb run syncdb command line.
|
||||
// name means table's alias name. default is "default".
|
||||
// force means run next sql if the current is error.
|
||||
// verbose means show all info when running command or not.
|
||||
func RunSyncdb(name string, force bool, verbose bool) error {
|
||||
BootStrap()
|
||||
|
||||
al := getDbAlias(name)
|
||||
cmd := new(commandSyncDb)
|
||||
cmd.al = al
|
||||
cmd.force = force
|
||||
cmd.noInfo = !verbose
|
||||
cmd.verbose = verbose
|
||||
cmd.rtOnError = true
|
||||
return cmd.Run()
|
||||
}
|
||||
314
vendor/github.com/fatedier/beego/orm/cmd_utils.go
generated
vendored
Normal file
314
vendor/github.com/fatedier/beego/orm/cmd_utils.go
generated
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type dbIndex struct {
|
||||
Table string
|
||||
Name string
|
||||
SQL string
|
||||
}
|
||||
|
||||
// create database drop sql.
|
||||
func getDbDropSQL(al *alias) (sqls []string) {
|
||||
if len(modelCache.cache) == 0 {
|
||||
fmt.Println("no Model found, need register your model")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
Q := al.DbBaser.TableQuote()
|
||||
|
||||
for _, mi := range modelCache.allOrdered() {
|
||||
sqls = append(sqls, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.table, Q))
|
||||
}
|
||||
return sqls
|
||||
}
|
||||
|
||||
// get database column type string.
|
||||
func getColumnTyp(al *alias, fi *fieldInfo) (col string) {
|
||||
T := al.DbBaser.DbTypes()
|
||||
fieldType := fi.fieldType
|
||||
fieldSize := fi.size
|
||||
|
||||
checkColumn:
|
||||
switch fieldType {
|
||||
case TypeBooleanField:
|
||||
col = T["bool"]
|
||||
case TypeCharField:
|
||||
if al.Driver == DRPostgres && fi.toText {
|
||||
col = T["string-text"]
|
||||
} else {
|
||||
col = fmt.Sprintf(T["string"], fieldSize)
|
||||
}
|
||||
case TypeTextField:
|
||||
col = T["string-text"]
|
||||
case TypeTimeField:
|
||||
col = T["time.Time-clock"]
|
||||
case TypeDateField:
|
||||
col = T["time.Time-date"]
|
||||
case TypeDateTimeField:
|
||||
col = T["time.Time"]
|
||||
case TypeBitField:
|
||||
col = T["int8"]
|
||||
case TypeSmallIntegerField:
|
||||
col = T["int16"]
|
||||
case TypeIntegerField:
|
||||
col = T["int32"]
|
||||
case TypeBigIntegerField:
|
||||
if al.Driver == DRSqlite {
|
||||
fieldType = TypeIntegerField
|
||||
goto checkColumn
|
||||
}
|
||||
col = T["int64"]
|
||||
case TypePositiveBitField:
|
||||
col = T["uint8"]
|
||||
case TypePositiveSmallIntegerField:
|
||||
col = T["uint16"]
|
||||
case TypePositiveIntegerField:
|
||||
col = T["uint32"]
|
||||
case TypePositiveBigIntegerField:
|
||||
col = T["uint64"]
|
||||
case TypeFloatField:
|
||||
col = T["float64"]
|
||||
case TypeDecimalField:
|
||||
s := T["float64-decimal"]
|
||||
if strings.Index(s, "%d") == -1 {
|
||||
col = s
|
||||
} else {
|
||||
col = fmt.Sprintf(s, fi.digits, fi.decimals)
|
||||
}
|
||||
case TypeJSONField:
|
||||
if al.Driver != DRPostgres {
|
||||
fieldType = TypeCharField
|
||||
goto checkColumn
|
||||
}
|
||||
col = T["json"]
|
||||
case TypeJsonbField:
|
||||
if al.Driver != DRPostgres {
|
||||
fieldType = TypeCharField
|
||||
goto checkColumn
|
||||
}
|
||||
col = T["jsonb"]
|
||||
case RelForeignKey, RelOneToOne:
|
||||
fieldType = fi.relModelInfo.fields.pk.fieldType
|
||||
fieldSize = fi.relModelInfo.fields.pk.size
|
||||
goto checkColumn
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// create alter sql string.
|
||||
func getColumnAddQuery(al *alias, fi *fieldInfo) string {
|
||||
Q := al.DbBaser.TableQuote()
|
||||
typ := getColumnTyp(al, fi)
|
||||
|
||||
if fi.null == false {
|
||||
typ += " " + "NOT NULL"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s %s",
|
||||
Q, fi.mi.table, Q,
|
||||
Q, fi.column, Q,
|
||||
typ, getColumnDefault(fi),
|
||||
)
|
||||
}
|
||||
|
||||
// create database creation string.
|
||||
func getDbCreateSQL(al *alias) (sqls []string, tableIndexes map[string][]dbIndex) {
|
||||
if len(modelCache.cache) == 0 {
|
||||
fmt.Println("no Model found, need register your model")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
Q := al.DbBaser.TableQuote()
|
||||
T := al.DbBaser.DbTypes()
|
||||
sep := fmt.Sprintf("%s, %s", Q, Q)
|
||||
|
||||
tableIndexes = make(map[string][]dbIndex)
|
||||
|
||||
for _, mi := range modelCache.allOrdered() {
|
||||
sql := fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
|
||||
sql += fmt.Sprintf("-- Table Structure for `%s`\n", mi.fullName)
|
||||
sql += fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
|
||||
|
||||
sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.table, Q)
|
||||
|
||||
columns := make([]string, 0, len(mi.fields.fieldsDB))
|
||||
|
||||
sqlIndexes := [][]string{}
|
||||
|
||||
for _, fi := range mi.fields.fieldsDB {
|
||||
|
||||
column := fmt.Sprintf(" %s%s%s ", Q, fi.column, Q)
|
||||
col := getColumnTyp(al, fi)
|
||||
|
||||
if fi.auto {
|
||||
switch al.Driver {
|
||||
case DRSqlite, DRPostgres:
|
||||
column += T["auto"]
|
||||
default:
|
||||
column += col + " " + T["auto"]
|
||||
}
|
||||
} else if fi.pk {
|
||||
column += col + " " + T["pk"]
|
||||
} else {
|
||||
column += col
|
||||
|
||||
if fi.null == false {
|
||||
column += " " + "NOT NULL"
|
||||
}
|
||||
|
||||
//if fi.initial.String() != "" {
|
||||
// column += " DEFAULT " + fi.initial.String()
|
||||
//}
|
||||
|
||||
// Append attribute DEFAULT
|
||||
column += getColumnDefault(fi)
|
||||
|
||||
if fi.unique {
|
||||
column += " " + "UNIQUE"
|
||||
}
|
||||
|
||||
if fi.index {
|
||||
sqlIndexes = append(sqlIndexes, []string{fi.column})
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Index(column, "%COL%") != -1 {
|
||||
column = strings.Replace(column, "%COL%", fi.column, -1)
|
||||
}
|
||||
|
||||
columns = append(columns, column)
|
||||
}
|
||||
|
||||
if mi.model != nil {
|
||||
allnames := getTableUnique(mi.addrField)
|
||||
if !mi.manual && len(mi.uniques) > 0 {
|
||||
allnames = append(allnames, mi.uniques)
|
||||
}
|
||||
for _, names := range allnames {
|
||||
cols := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
|
||||
cols = append(cols, fi.column)
|
||||
} else {
|
||||
panic(fmt.Errorf("cannot found column `%s` when parse UNIQUE in `%s.TableUnique`", name, mi.fullName))
|
||||
}
|
||||
}
|
||||
column := fmt.Sprintf(" UNIQUE (%s%s%s)", Q, strings.Join(cols, sep), Q)
|
||||
columns = append(columns, column)
|
||||
}
|
||||
}
|
||||
|
||||
sql += strings.Join(columns, ",\n")
|
||||
sql += "\n)"
|
||||
|
||||
if al.Driver == DRMySQL {
|
||||
var engine string
|
||||
if mi.model != nil {
|
||||
engine = getTableEngine(mi.addrField)
|
||||
}
|
||||
if engine == "" {
|
||||
engine = al.Engine
|
||||
}
|
||||
sql += " ENGINE=" + engine
|
||||
}
|
||||
|
||||
sql += ";"
|
||||
sqls = append(sqls, sql)
|
||||
|
||||
if mi.model != nil {
|
||||
for _, names := range getTableIndex(mi.addrField) {
|
||||
cols := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
|
||||
cols = append(cols, fi.column)
|
||||
} else {
|
||||
panic(fmt.Errorf("cannot found column `%s` when parse INDEX in `%s.TableIndex`", name, mi.fullName))
|
||||
}
|
||||
}
|
||||
sqlIndexes = append(sqlIndexes, cols)
|
||||
}
|
||||
}
|
||||
|
||||
for _, names := range sqlIndexes {
|
||||
name := mi.table + "_" + strings.Join(names, "_")
|
||||
cols := strings.Join(names, sep)
|
||||
sql := fmt.Sprintf("CREATE INDEX %s%s%s ON %s%s%s (%s%s%s);", Q, name, Q, Q, mi.table, Q, Q, cols, Q)
|
||||
|
||||
index := dbIndex{}
|
||||
index.Table = mi.table
|
||||
index.Name = name
|
||||
index.SQL = sql
|
||||
|
||||
tableIndexes[mi.table] = append(tableIndexes[mi.table], index)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Get string value for the attribute "DEFAULT" for the CREATE, ALTER commands
|
||||
func getColumnDefault(fi *fieldInfo) string {
|
||||
var (
|
||||
v, t, d string
|
||||
)
|
||||
|
||||
// Skip default attribute if field is in relations
|
||||
if fi.rel || fi.reverse {
|
||||
return v
|
||||
}
|
||||
|
||||
t = " DEFAULT '%s' "
|
||||
|
||||
// These defaults will be useful if there no config value orm:"default" and NOT NULL is on
|
||||
switch fi.fieldType {
|
||||
case TypeTimeField, TypeDateField, TypeDateTimeField, TypeTextField:
|
||||
return v
|
||||
|
||||
case TypeBitField, TypeSmallIntegerField, TypeIntegerField,
|
||||
TypeBigIntegerField, TypePositiveBitField, TypePositiveSmallIntegerField,
|
||||
TypePositiveIntegerField, TypePositiveBigIntegerField, TypeFloatField,
|
||||
TypeDecimalField:
|
||||
t = " DEFAULT %s "
|
||||
d = "0"
|
||||
case TypeBooleanField:
|
||||
t = " DEFAULT %s "
|
||||
d = "FALSE"
|
||||
case TypeJSONField, TypeJsonbField:
|
||||
d = "{}"
|
||||
}
|
||||
|
||||
if fi.colDefault {
|
||||
if !fi.initial.Exist() {
|
||||
v = fmt.Sprintf(t, "")
|
||||
} else {
|
||||
v = fmt.Sprintf(t, fi.initial.String())
|
||||
}
|
||||
} else {
|
||||
if !fi.null {
|
||||
v = fmt.Sprintf(t, d)
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
1836
vendor/github.com/fatedier/beego/orm/db.go
generated
vendored
Normal file
1836
vendor/github.com/fatedier/beego/orm/db.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
298
vendor/github.com/fatedier/beego/orm/db_alias.go
generated
vendored
Normal file
298
vendor/github.com/fatedier/beego/orm/db_alias.go
generated
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DriverType database driver constant int.
|
||||
type DriverType int
|
||||
|
||||
// Enum the Database driver
|
||||
const (
|
||||
_ DriverType = iota // int enum type
|
||||
DRMySQL // mysql
|
||||
DRSqlite // sqlite
|
||||
DROracle // oracle
|
||||
DRPostgres // pgsql
|
||||
DRTiDB // TiDB
|
||||
)
|
||||
|
||||
// database driver string.
|
||||
type driver string
|
||||
|
||||
// get type constant int of current driver..
|
||||
func (d driver) Type() DriverType {
|
||||
a, _ := dataBaseCache.get(string(d))
|
||||
return a.Driver
|
||||
}
|
||||
|
||||
// get name of current driver
|
||||
func (d driver) Name() string {
|
||||
return string(d)
|
||||
}
|
||||
|
||||
// check driver iis implemented Driver interface or not.
|
||||
var _ Driver = new(driver)
|
||||
|
||||
var (
|
||||
dataBaseCache = &_dbCache{cache: make(map[string]*alias)}
|
||||
drivers = map[string]DriverType{
|
||||
"mysql": DRMySQL,
|
||||
"postgres": DRPostgres,
|
||||
"sqlite3": DRSqlite,
|
||||
"tidb": DRTiDB,
|
||||
"oracle": DROracle,
|
||||
}
|
||||
dbBasers = map[DriverType]dbBaser{
|
||||
DRMySQL: newdbBaseMysql(),
|
||||
DRSqlite: newdbBaseSqlite(),
|
||||
DROracle: newdbBaseOracle(),
|
||||
DRPostgres: newdbBasePostgres(),
|
||||
DRTiDB: newdbBaseTidb(),
|
||||
}
|
||||
)
|
||||
|
||||
// database alias cacher.
|
||||
type _dbCache struct {
|
||||
mux sync.RWMutex
|
||||
cache map[string]*alias
|
||||
}
|
||||
|
||||
// add database alias with original name.
|
||||
func (ac *_dbCache) add(name string, al *alias) (added bool) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
if _, ok := ac.cache[name]; !ok {
|
||||
ac.cache[name] = al
|
||||
added = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// get database alias if cached.
|
||||
func (ac *_dbCache) get(name string) (al *alias, ok bool) {
|
||||
ac.mux.RLock()
|
||||
defer ac.mux.RUnlock()
|
||||
al, ok = ac.cache[name]
|
||||
return
|
||||
}
|
||||
|
||||
// get default alias.
|
||||
func (ac *_dbCache) getDefault() (al *alias) {
|
||||
al, _ = ac.get("default")
|
||||
return
|
||||
}
|
||||
|
||||
type alias struct {
|
||||
Name string
|
||||
Driver DriverType
|
||||
DriverName string
|
||||
DataSource string
|
||||
MaxIdleConns int
|
||||
MaxOpenConns int
|
||||
DB *sql.DB
|
||||
DbBaser dbBaser
|
||||
TZ *time.Location
|
||||
Engine string
|
||||
}
|
||||
|
||||
func detectTZ(al *alias) {
|
||||
// orm timezone system match database
|
||||
// default use Local
|
||||
al.TZ = time.Local
|
||||
|
||||
if al.DriverName == "sphinx" {
|
||||
return
|
||||
}
|
||||
|
||||
switch al.Driver {
|
||||
case DRMySQL:
|
||||
row := al.DB.QueryRow("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)")
|
||||
var tz string
|
||||
row.Scan(&tz)
|
||||
if len(tz) >= 8 {
|
||||
if tz[0] != '-' {
|
||||
tz = "+" + tz
|
||||
}
|
||||
t, err := time.Parse("-07:00:00", tz)
|
||||
if err == nil {
|
||||
al.TZ = t.Location()
|
||||
} else {
|
||||
DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// get default engine from current database
|
||||
row = al.DB.QueryRow("SELECT ENGINE, TRANSACTIONS FROM information_schema.engines WHERE SUPPORT = 'DEFAULT'")
|
||||
var engine string
|
||||
var tx bool
|
||||
row.Scan(&engine, &tx)
|
||||
|
||||
if engine != "" {
|
||||
al.Engine = engine
|
||||
} else {
|
||||
al.Engine = "INNODB"
|
||||
}
|
||||
|
||||
case DRSqlite, DROracle:
|
||||
al.TZ = time.UTC
|
||||
|
||||
case DRPostgres:
|
||||
row := al.DB.QueryRow("SELECT current_setting('TIMEZONE')")
|
||||
var tz string
|
||||
row.Scan(&tz)
|
||||
loc, err := time.LoadLocation(tz)
|
||||
if err == nil {
|
||||
al.TZ = loc
|
||||
} else {
|
||||
DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
|
||||
al := new(alias)
|
||||
al.Name = aliasName
|
||||
al.DriverName = driverName
|
||||
al.DB = db
|
||||
|
||||
if dr, ok := drivers[driverName]; ok {
|
||||
al.DbBaser = dbBasers[dr]
|
||||
al.Driver = dr
|
||||
} else {
|
||||
return nil, fmt.Errorf("driver name `%s` have not registered", driverName)
|
||||
}
|
||||
|
||||
err := db.Ping()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("register db Ping `%s`, %s", aliasName, err.Error())
|
||||
}
|
||||
|
||||
if dataBaseCache.add(aliasName, al) == false {
|
||||
return nil, fmt.Errorf("DataBase alias name `%s` already registered, cannot reuse", aliasName)
|
||||
}
|
||||
|
||||
return al, nil
|
||||
}
|
||||
|
||||
// AddAliasWthDB add a aliasName for the drivename
|
||||
func AddAliasWthDB(aliasName, driverName string, db *sql.DB) error {
|
||||
_, err := addAliasWthDB(aliasName, driverName, db)
|
||||
return err
|
||||
}
|
||||
|
||||
// RegisterDataBase Setting the database connect params. Use the database driver self dataSource args.
|
||||
func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) error {
|
||||
var (
|
||||
err error
|
||||
db *sql.DB
|
||||
al *alias
|
||||
)
|
||||
|
||||
db, err = sql.Open(driverName, dataSource)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
|
||||
goto end
|
||||
}
|
||||
|
||||
al, err = addAliasWthDB(aliasName, driverName, db)
|
||||
if err != nil {
|
||||
goto end
|
||||
}
|
||||
|
||||
al.DataSource = dataSource
|
||||
|
||||
detectTZ(al)
|
||||
|
||||
for i, v := range params {
|
||||
switch i {
|
||||
case 0:
|
||||
SetMaxIdleConns(al.Name, v)
|
||||
case 1:
|
||||
SetMaxOpenConns(al.Name, v)
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if err != nil {
|
||||
if db != nil {
|
||||
db.Close()
|
||||
}
|
||||
DebugLog.Println(err.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// RegisterDriver Register a database driver use specify driver name, this can be definition the driver is which database type.
|
||||
func RegisterDriver(driverName string, typ DriverType) error {
|
||||
if t, ok := drivers[driverName]; ok == false {
|
||||
drivers[driverName] = typ
|
||||
} else {
|
||||
if t != typ {
|
||||
return fmt.Errorf("driverName `%s` db driver already registered and is other type\n", driverName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetDataBaseTZ Change the database default used timezone
|
||||
func SetDataBaseTZ(aliasName string, tz *time.Location) error {
|
||||
if al, ok := dataBaseCache.get(aliasName); ok {
|
||||
al.TZ = tz
|
||||
} else {
|
||||
return fmt.Errorf("DataBase alias name `%s` not registered\n", aliasName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetMaxIdleConns Change the max idle conns for *sql.DB, use specify database alias name
|
||||
func SetMaxIdleConns(aliasName string, maxIdleConns int) {
|
||||
al := getDbAlias(aliasName)
|
||||
al.MaxIdleConns = maxIdleConns
|
||||
al.DB.SetMaxIdleConns(maxIdleConns)
|
||||
}
|
||||
|
||||
// SetMaxOpenConns Change the max open conns for *sql.DB, use specify database alias name
|
||||
func SetMaxOpenConns(aliasName string, maxOpenConns int) {
|
||||
al := getDbAlias(aliasName)
|
||||
al.MaxOpenConns = maxOpenConns
|
||||
// for tip go 1.2
|
||||
if fun := reflect.ValueOf(al.DB).MethodByName("SetMaxOpenConns"); fun.IsValid() {
|
||||
fun.Call([]reflect.Value{reflect.ValueOf(maxOpenConns)})
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB Get *sql.DB from registered database by db alias name.
|
||||
// Use "default" as alias name if you not set.
|
||||
func GetDB(aliasNames ...string) (*sql.DB, error) {
|
||||
var name string
|
||||
if len(aliasNames) > 0 {
|
||||
name = aliasNames[0]
|
||||
} else {
|
||||
name = "default"
|
||||
}
|
||||
al, ok := dataBaseCache.get(name)
|
||||
if ok {
|
||||
return al.DB, nil
|
||||
}
|
||||
return nil, fmt.Errorf("DataBase of alias name `%s` not found\n", name)
|
||||
}
|
||||
183
vendor/github.com/fatedier/beego/orm/db_mysql.go
generated
vendored
Normal file
183
vendor/github.com/fatedier/beego/orm/db_mysql.go
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// mysql operators.
|
||||
var mysqlOperators = map[string]string{
|
||||
"exact": "= ?",
|
||||
"iexact": "LIKE ?",
|
||||
"contains": "LIKE BINARY ?",
|
||||
"icontains": "LIKE ?",
|
||||
// "regex": "REGEXP BINARY ?",
|
||||
// "iregex": "REGEXP ?",
|
||||
"gt": "> ?",
|
||||
"gte": ">= ?",
|
||||
"lt": "< ?",
|
||||
"lte": "<= ?",
|
||||
"eq": "= ?",
|
||||
"ne": "!= ?",
|
||||
"startswith": "LIKE BINARY ?",
|
||||
"endswith": "LIKE BINARY ?",
|
||||
"istartswith": "LIKE ?",
|
||||
"iendswith": "LIKE ?",
|
||||
}
|
||||
|
||||
// mysql column field types.
|
||||
var mysqlTypes = map[string]string{
|
||||
"auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY",
|
||||
"pk": "NOT NULL PRIMARY KEY",
|
||||
"bool": "bool",
|
||||
"string": "varchar(%d)",
|
||||
"string-text": "longtext",
|
||||
"time.Time-date": "date",
|
||||
"time.Time": "datetime",
|
||||
"int8": "tinyint",
|
||||
"int16": "smallint",
|
||||
"int32": "integer",
|
||||
"int64": "bigint",
|
||||
"uint8": "tinyint unsigned",
|
||||
"uint16": "smallint unsigned",
|
||||
"uint32": "integer unsigned",
|
||||
"uint64": "bigint unsigned",
|
||||
"float64": "double precision",
|
||||
"float64-decimal": "numeric(%d, %d)",
|
||||
}
|
||||
|
||||
// mysql dbBaser implementation.
|
||||
type dbBaseMysql struct {
|
||||
dbBase
|
||||
}
|
||||
|
||||
var _ dbBaser = new(dbBaseMysql)
|
||||
|
||||
// get mysql operator.
|
||||
func (d *dbBaseMysql) OperatorSQL(operator string) string {
|
||||
return mysqlOperators[operator]
|
||||
}
|
||||
|
||||
// get mysql table field types.
|
||||
func (d *dbBaseMysql) DbTypes() map[string]string {
|
||||
return mysqlTypes
|
||||
}
|
||||
|
||||
// show table sql for mysql.
|
||||
func (d *dbBaseMysql) ShowTablesQuery() string {
|
||||
return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()"
|
||||
}
|
||||
|
||||
// show columns sql of table for mysql.
|
||||
func (d *dbBaseMysql) ShowColumnsQuery(table string) string {
|
||||
return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+
|
||||
"WHERE table_schema = DATABASE() AND table_name = '%s'", table)
|
||||
}
|
||||
|
||||
// execute sql to check index exist.
|
||||
func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool {
|
||||
row := db.QueryRow("SELECT count(*) FROM information_schema.statistics "+
|
||||
"WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, name)
|
||||
var cnt int
|
||||
row.Scan(&cnt)
|
||||
return cnt > 0
|
||||
}
|
||||
|
||||
// InsertOrUpdate a row
|
||||
// If your primary key or unique column conflict will update
|
||||
// If no will insert
|
||||
// Add "`" for mysql sql building
|
||||
func (d *dbBaseMysql) InsertOrUpdate(q dbQuerier, mi *modelInfo, ind reflect.Value, a *alias, args ...string) (int64, error) {
|
||||
|
||||
iouStr := ""
|
||||
argsMap := map[string]string{}
|
||||
|
||||
iouStr = "ON DUPLICATE KEY UPDATE"
|
||||
|
||||
//Get on the key-value pairs
|
||||
for _, v := range args {
|
||||
kv := strings.Split(v, "=")
|
||||
if len(kv) == 2 {
|
||||
argsMap[strings.ToLower(kv[0])] = kv[1]
|
||||
}
|
||||
}
|
||||
|
||||
isMulti := false
|
||||
names := make([]string, 0, len(mi.fields.dbcols)-1)
|
||||
Q := d.ins.TableQuote()
|
||||
values, _, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, a.TZ)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
marks := make([]string, len(names))
|
||||
updateValues := make([]interface{}, 0)
|
||||
updates := make([]string, len(names))
|
||||
|
||||
for i, v := range names {
|
||||
marks[i] = "?"
|
||||
valueStr := argsMap[strings.ToLower(v)]
|
||||
if valueStr != "" {
|
||||
updates[i] = "`" + v + "`" + "=" + valueStr
|
||||
} else {
|
||||
updates[i] = "`" + v + "`" + "=?"
|
||||
updateValues = append(updateValues, values[i])
|
||||
}
|
||||
}
|
||||
|
||||
values = append(values, updateValues...)
|
||||
|
||||
sep := fmt.Sprintf("%s, %s", Q, Q)
|
||||
qmarks := strings.Join(marks, ", ")
|
||||
qupdates := strings.Join(updates, ", ")
|
||||
columns := strings.Join(names, sep)
|
||||
|
||||
multi := len(values) / len(names)
|
||||
|
||||
if isMulti {
|
||||
qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks
|
||||
}
|
||||
//conflitValue maybe is a int,can`t use fmt.Sprintf
|
||||
query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr)
|
||||
|
||||
d.ins.ReplaceMarks(&query)
|
||||
|
||||
if isMulti || !d.ins.HasReturningID(mi, &query) {
|
||||
res, err := q.Exec(query, values...)
|
||||
if err == nil {
|
||||
if isMulti {
|
||||
return res.RowsAffected()
|
||||
}
|
||||
return res.LastInsertId()
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
row := q.QueryRow(query, values...)
|
||||
var id int64
|
||||
err = row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
// create new mysql dbBaser.
|
||||
func newdbBaseMysql() dbBaser {
|
||||
b := new(dbBaseMysql)
|
||||
b.ins = b
|
||||
return b
|
||||
}
|
||||
96
vendor/github.com/fatedier/beego/orm/db_oracle.go
generated
vendored
Normal file
96
vendor/github.com/fatedier/beego/orm/db_oracle.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// oracle operators.
|
||||
var oracleOperators = map[string]string{
|
||||
"exact": "= ?",
|
||||
"gt": "> ?",
|
||||
"gte": ">= ?",
|
||||
"lt": "< ?",
|
||||
"lte": "<= ?",
|
||||
"//iendswith": "LIKE ?",
|
||||
}
|
||||
|
||||
// oracle column field types.
|
||||
var oracleTypes = map[string]string{
|
||||
"pk": "NOT NULL PRIMARY KEY",
|
||||
"bool": "bool",
|
||||
"string": "VARCHAR2(%d)",
|
||||
"string-text": "VARCHAR2(%d)",
|
||||
"time.Time-date": "DATE",
|
||||
"time.Time": "TIMESTAMP",
|
||||
"int8": "INTEGER",
|
||||
"int16": "INTEGER",
|
||||
"int32": "INTEGER",
|
||||
"int64": "INTEGER",
|
||||
"uint8": "INTEGER",
|
||||
"uint16": "INTEGER",
|
||||
"uint32": "INTEGER",
|
||||
"uint64": "INTEGER",
|
||||
"float64": "NUMBER",
|
||||
"float64-decimal": "NUMBER(%d, %d)",
|
||||
}
|
||||
|
||||
// oracle dbBaser
|
||||
type dbBaseOracle struct {
|
||||
dbBase
|
||||
}
|
||||
|
||||
var _ dbBaser = new(dbBaseOracle)
|
||||
|
||||
// create oracle dbBaser.
|
||||
func newdbBaseOracle() dbBaser {
|
||||
b := new(dbBaseOracle)
|
||||
b.ins = b
|
||||
return b
|
||||
}
|
||||
|
||||
// OperatorSQL get oracle operator.
|
||||
func (d *dbBaseOracle) OperatorSQL(operator string) string {
|
||||
return oracleOperators[operator]
|
||||
}
|
||||
|
||||
// DbTypes get oracle table field types.
|
||||
func (d *dbBaseOracle) DbTypes() map[string]string {
|
||||
return oracleTypes
|
||||
}
|
||||
|
||||
//ShowTablesQuery show all the tables in database
|
||||
func (d *dbBaseOracle) ShowTablesQuery() string {
|
||||
return "SELECT TABLE_NAME FROM USER_TABLES"
|
||||
}
|
||||
|
||||
// Oracle
|
||||
func (d *dbBaseOracle) ShowColumnsQuery(table string) string {
|
||||
return fmt.Sprintf("SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS "+
|
||||
"WHERE TABLE_NAME ='%s'", strings.ToUpper(table))
|
||||
}
|
||||
|
||||
// check index is exist
|
||||
func (d *dbBaseOracle) IndexExists(db dbQuerier, table string, name string) bool {
|
||||
row := db.QueryRow("SELECT COUNT(*) FROM USER_IND_COLUMNS, USER_INDEXES "+
|
||||
"WHERE USER_IND_COLUMNS.INDEX_NAME = USER_INDEXES.INDEX_NAME "+
|
||||
"AND USER_IND_COLUMNS.TABLE_NAME = ? AND USER_IND_COLUMNS.INDEX_NAME = ?", strings.ToUpper(table), strings.ToUpper(name))
|
||||
|
||||
var cnt int
|
||||
row.Scan(&cnt)
|
||||
return cnt > 0
|
||||
}
|
||||
188
vendor/github.com/fatedier/beego/orm/db_postgres.go
generated
vendored
Normal file
188
vendor/github.com/fatedier/beego/orm/db_postgres.go
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// postgresql operators.
|
||||
var postgresOperators = map[string]string{
|
||||
"exact": "= ?",
|
||||
"iexact": "= UPPER(?)",
|
||||
"contains": "LIKE ?",
|
||||
"icontains": "LIKE UPPER(?)",
|
||||
"gt": "> ?",
|
||||
"gte": ">= ?",
|
||||
"lt": "< ?",
|
||||
"lte": "<= ?",
|
||||
"eq": "= ?",
|
||||
"ne": "!= ?",
|
||||
"startswith": "LIKE ?",
|
||||
"endswith": "LIKE ?",
|
||||
"istartswith": "LIKE UPPER(?)",
|
||||
"iendswith": "LIKE UPPER(?)",
|
||||
}
|
||||
|
||||
// postgresql column field types.
|
||||
var postgresTypes = map[string]string{
|
||||
"auto": "serial NOT NULL PRIMARY KEY",
|
||||
"pk": "NOT NULL PRIMARY KEY",
|
||||
"bool": "bool",
|
||||
"string": "varchar(%d)",
|
||||
"string-text": "text",
|
||||
"time.Time-date": "date",
|
||||
"time.Time": "timestamp with time zone",
|
||||
"int8": `smallint CHECK("%COL%" >= -127 AND "%COL%" <= 128)`,
|
||||
"int16": "smallint",
|
||||
"int32": "integer",
|
||||
"int64": "bigint",
|
||||
"uint8": `smallint CHECK("%COL%" >= 0 AND "%COL%" <= 255)`,
|
||||
"uint16": `integer CHECK("%COL%" >= 0)`,
|
||||
"uint32": `bigint CHECK("%COL%" >= 0)`,
|
||||
"uint64": `bigint CHECK("%COL%" >= 0)`,
|
||||
"float64": "double precision",
|
||||
"float64-decimal": "numeric(%d, %d)",
|
||||
"json": "json",
|
||||
"jsonb": "jsonb",
|
||||
}
|
||||
|
||||
// postgresql dbBaser.
|
||||
type dbBasePostgres struct {
|
||||
dbBase
|
||||
}
|
||||
|
||||
var _ dbBaser = new(dbBasePostgres)
|
||||
|
||||
// get postgresql operator.
|
||||
func (d *dbBasePostgres) OperatorSQL(operator string) string {
|
||||
return postgresOperators[operator]
|
||||
}
|
||||
|
||||
// generate functioned sql string, such as contains(text).
|
||||
func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) {
|
||||
switch operator {
|
||||
case "contains", "startswith", "endswith":
|
||||
*leftCol = fmt.Sprintf("%s::text", *leftCol)
|
||||
case "iexact", "icontains", "istartswith", "iendswith":
|
||||
*leftCol = fmt.Sprintf("UPPER(%s::text)", *leftCol)
|
||||
}
|
||||
}
|
||||
|
||||
// postgresql unsupports updating joined record.
|
||||
func (d *dbBasePostgres) SupportUpdateJoin() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *dbBasePostgres) MaxLimit() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// postgresql quote is ".
|
||||
func (d *dbBasePostgres) TableQuote() string {
|
||||
return `"`
|
||||
}
|
||||
|
||||
// postgresql value placeholder is $n.
|
||||
// replace default ? to $n.
|
||||
func (d *dbBasePostgres) ReplaceMarks(query *string) {
|
||||
q := *query
|
||||
num := 0
|
||||
for _, c := range q {
|
||||
if c == '?' {
|
||||
num++
|
||||
}
|
||||
}
|
||||
if num == 0 {
|
||||
return
|
||||
}
|
||||
data := make([]byte, 0, len(q)+num)
|
||||
num = 1
|
||||
for i := 0; i < len(q); i++ {
|
||||
c := q[i]
|
||||
if c == '?' {
|
||||
data = append(data, '$')
|
||||
data = append(data, []byte(strconv.Itoa(num))...)
|
||||
num++
|
||||
} else {
|
||||
data = append(data, c)
|
||||
}
|
||||
}
|
||||
*query = string(data)
|
||||
}
|
||||
|
||||
// make returning sql support for postgresql.
|
||||
func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) bool {
|
||||
fi := mi.fields.pk
|
||||
if fi.fieldType&IsPositiveIntegerField == 0 && fi.fieldType&IsIntegerField == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if query != nil {
|
||||
*query = fmt.Sprintf(`%s RETURNING "%s"`, *query, fi.column)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// sync auto key
|
||||
func (d *dbBasePostgres) setval(db dbQuerier, mi *modelInfo, autoFields []string) error {
|
||||
if len(autoFields) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
Q := d.ins.TableQuote()
|
||||
for _, name := range autoFields {
|
||||
query := fmt.Sprintf("SELECT setval(pg_get_serial_sequence('%s', '%s'), (SELECT MAX(%s%s%s) FROM %s%s%s));",
|
||||
mi.table, name,
|
||||
Q, name, Q,
|
||||
Q, mi.table, Q)
|
||||
if _, err := db.Exec(query); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// show table sql for postgresql.
|
||||
func (d *dbBasePostgres) ShowTablesQuery() string {
|
||||
return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')"
|
||||
}
|
||||
|
||||
// show table columns sql for postgresql.
|
||||
func (d *dbBasePostgres) ShowColumnsQuery(table string) string {
|
||||
return fmt.Sprintf("SELECT column_name, data_type, is_nullable FROM information_schema.columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'", table)
|
||||
}
|
||||
|
||||
// get column types of postgresql.
|
||||
func (d *dbBasePostgres) DbTypes() map[string]string {
|
||||
return postgresTypes
|
||||
}
|
||||
|
||||
// check index exist in postgresql.
|
||||
func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bool {
|
||||
query := fmt.Sprintf("SELECT COUNT(*) FROM pg_indexes WHERE tablename = '%s' AND indexname = '%s'", table, name)
|
||||
row := db.QueryRow(query)
|
||||
var cnt int
|
||||
row.Scan(&cnt)
|
||||
return cnt > 0
|
||||
}
|
||||
|
||||
// create new postgresql dbBaser.
|
||||
func newdbBasePostgres() dbBaser {
|
||||
b := new(dbBasePostgres)
|
||||
b.ins = b
|
||||
return b
|
||||
}
|
||||
150
vendor/github.com/fatedier/beego/orm/db_sqlite.go
generated
vendored
Normal file
150
vendor/github.com/fatedier/beego/orm/db_sqlite.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// sqlite operators.
|
||||
var sqliteOperators = map[string]string{
|
||||
"exact": "= ?",
|
||||
"iexact": "LIKE ? ESCAPE '\\'",
|
||||
"contains": "LIKE ? ESCAPE '\\'",
|
||||
"icontains": "LIKE ? ESCAPE '\\'",
|
||||
"gt": "> ?",
|
||||
"gte": ">= ?",
|
||||
"lt": "< ?",
|
||||
"lte": "<= ?",
|
||||
"eq": "= ?",
|
||||
"ne": "!= ?",
|
||||
"startswith": "LIKE ? ESCAPE '\\'",
|
||||
"endswith": "LIKE ? ESCAPE '\\'",
|
||||
"istartswith": "LIKE ? ESCAPE '\\'",
|
||||
"iendswith": "LIKE ? ESCAPE '\\'",
|
||||
}
|
||||
|
||||
// sqlite column types.
|
||||
var sqliteTypes = map[string]string{
|
||||
"auto": "integer NOT NULL PRIMARY KEY AUTOINCREMENT",
|
||||
"pk": "NOT NULL PRIMARY KEY",
|
||||
"bool": "bool",
|
||||
"string": "varchar(%d)",
|
||||
"string-text": "text",
|
||||
"time.Time-date": "date",
|
||||
"time.Time": "datetime",
|
||||
"int8": "tinyint",
|
||||
"int16": "smallint",
|
||||
"int32": "integer",
|
||||
"int64": "bigint",
|
||||
"uint8": "tinyint unsigned",
|
||||
"uint16": "smallint unsigned",
|
||||
"uint32": "integer unsigned",
|
||||
"uint64": "bigint unsigned",
|
||||
"float64": "real",
|
||||
"float64-decimal": "decimal",
|
||||
}
|
||||
|
||||
// sqlite dbBaser.
|
||||
type dbBaseSqlite struct {
|
||||
dbBase
|
||||
}
|
||||
|
||||
var _ dbBaser = new(dbBaseSqlite)
|
||||
|
||||
// get sqlite operator.
|
||||
func (d *dbBaseSqlite) OperatorSQL(operator string) string {
|
||||
return sqliteOperators[operator]
|
||||
}
|
||||
|
||||
// generate functioned sql for sqlite.
|
||||
// only support DATE(text).
|
||||
func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) {
|
||||
if fi.fieldType == TypeDateField {
|
||||
*leftCol = fmt.Sprintf("DATE(%s)", *leftCol)
|
||||
}
|
||||
}
|
||||
|
||||
// unable updating joined record in sqlite.
|
||||
func (d *dbBaseSqlite) SupportUpdateJoin() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// max int in sqlite.
|
||||
func (d *dbBaseSqlite) MaxLimit() uint64 {
|
||||
return 9223372036854775807
|
||||
}
|
||||
|
||||
// get column types in sqlite.
|
||||
func (d *dbBaseSqlite) DbTypes() map[string]string {
|
||||
return sqliteTypes
|
||||
}
|
||||
|
||||
// get show tables sql in sqlite.
|
||||
func (d *dbBaseSqlite) ShowTablesQuery() string {
|
||||
return "SELECT name FROM sqlite_master WHERE type = 'table'"
|
||||
}
|
||||
|
||||
// get columns in sqlite.
|
||||
func (d *dbBaseSqlite) GetColumns(db dbQuerier, table string) (map[string][3]string, error) {
|
||||
query := d.ins.ShowColumnsQuery(table)
|
||||
rows, err := db.Query(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
columns := make(map[string][3]string)
|
||||
for rows.Next() {
|
||||
var tmp, name, typ, null sql.NullString
|
||||
err := rows.Scan(&tmp, &name, &typ, &null, &tmp, &tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columns[name.String] = [3]string{name.String, typ.String, null.String}
|
||||
}
|
||||
|
||||
return columns, nil
|
||||
}
|
||||
|
||||
// get show columns sql in sqlite.
|
||||
func (d *dbBaseSqlite) ShowColumnsQuery(table string) string {
|
||||
return fmt.Sprintf("pragma table_info('%s')", table)
|
||||
}
|
||||
|
||||
// check index exist in sqlite.
|
||||
func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool {
|
||||
query := fmt.Sprintf("PRAGMA index_list('%s')", table)
|
||||
rows, err := db.Query(query)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var tmp, index sql.NullString
|
||||
rows.Scan(&tmp, &index, &tmp)
|
||||
if name == index.String {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// create new sqlite dbBaser.
|
||||
func newdbBaseSqlite() dbBaser {
|
||||
b := new(dbBaseSqlite)
|
||||
b.ins = b
|
||||
return b
|
||||
}
|
||||
476
vendor/github.com/fatedier/beego/orm/db_tables.go
generated
vendored
Normal file
476
vendor/github.com/fatedier/beego/orm/db_tables.go
generated
vendored
Normal file
@@ -0,0 +1,476 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// table info struct.
|
||||
type dbTable struct {
|
||||
id int
|
||||
index string
|
||||
name string
|
||||
names []string
|
||||
sel bool
|
||||
inner bool
|
||||
mi *modelInfo
|
||||
fi *fieldInfo
|
||||
jtl *dbTable
|
||||
}
|
||||
|
||||
// tables collection struct, contains some tables.
|
||||
type dbTables struct {
|
||||
tablesM map[string]*dbTable
|
||||
tables []*dbTable
|
||||
mi *modelInfo
|
||||
base dbBaser
|
||||
skipEnd bool
|
||||
}
|
||||
|
||||
// set table info to collection.
|
||||
// if not exist, create new.
|
||||
func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) *dbTable {
|
||||
name := strings.Join(names, ExprSep)
|
||||
if j, ok := t.tablesM[name]; ok {
|
||||
j.name = name
|
||||
j.mi = mi
|
||||
j.fi = fi
|
||||
j.inner = inner
|
||||
} else {
|
||||
i := len(t.tables) + 1
|
||||
jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil}
|
||||
t.tablesM[name] = jt
|
||||
t.tables = append(t.tables, jt)
|
||||
}
|
||||
return t.tablesM[name]
|
||||
}
|
||||
|
||||
// add table info to collection.
|
||||
func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) {
|
||||
name := strings.Join(names, ExprSep)
|
||||
if _, ok := t.tablesM[name]; ok == false {
|
||||
i := len(t.tables) + 1
|
||||
jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil}
|
||||
t.tablesM[name] = jt
|
||||
t.tables = append(t.tables, jt)
|
||||
return jt, true
|
||||
}
|
||||
return t.tablesM[name], false
|
||||
}
|
||||
|
||||
// get table info in collection.
|
||||
func (t *dbTables) get(name string) (*dbTable, bool) {
|
||||
j, ok := t.tablesM[name]
|
||||
return j, ok
|
||||
}
|
||||
|
||||
// get related fields info in recursive depth loop.
|
||||
// loop once, depth decreases one.
|
||||
func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related []string) []string {
|
||||
if depth < 0 || fi.fieldType == RelManyToMany {
|
||||
return related
|
||||
}
|
||||
|
||||
if prefix == "" {
|
||||
prefix = fi.name
|
||||
} else {
|
||||
prefix = prefix + ExprSep + fi.name
|
||||
}
|
||||
related = append(related, prefix)
|
||||
|
||||
depth--
|
||||
for _, fi := range fi.relModelInfo.fields.fieldsRel {
|
||||
related = t.loopDepth(depth, prefix, fi, related)
|
||||
}
|
||||
|
||||
return related
|
||||
}
|
||||
|
||||
// parse related fields.
|
||||
func (t *dbTables) parseRelated(rels []string, depth int) {
|
||||
|
||||
relsNum := len(rels)
|
||||
related := make([]string, relsNum)
|
||||
copy(related, rels)
|
||||
|
||||
relDepth := depth
|
||||
|
||||
if relsNum != 0 {
|
||||
relDepth = 0
|
||||
}
|
||||
|
||||
relDepth--
|
||||
for _, fi := range t.mi.fields.fieldsRel {
|
||||
related = t.loopDepth(relDepth, "", fi, related)
|
||||
}
|
||||
|
||||
for i, s := range related {
|
||||
var (
|
||||
exs = strings.Split(s, ExprSep)
|
||||
names = make([]string, 0, len(exs))
|
||||
mmi = t.mi
|
||||
cancel = true
|
||||
jtl *dbTable
|
||||
)
|
||||
|
||||
inner := true
|
||||
|
||||
for _, ex := range exs {
|
||||
if fi, ok := mmi.fields.GetByAny(ex); ok && fi.rel && fi.fieldType != RelManyToMany {
|
||||
names = append(names, fi.name)
|
||||
mmi = fi.relModelInfo
|
||||
|
||||
if fi.null || t.skipEnd {
|
||||
inner = false
|
||||
}
|
||||
|
||||
jt := t.set(names, mmi, fi, inner)
|
||||
jt.jtl = jtl
|
||||
|
||||
if fi.reverse {
|
||||
cancel = false
|
||||
}
|
||||
|
||||
if cancel {
|
||||
jt.sel = depth > 0
|
||||
|
||||
if i < relsNum {
|
||||
jt.sel = true
|
||||
}
|
||||
}
|
||||
|
||||
jtl = jt
|
||||
|
||||
} else {
|
||||
panic(fmt.Errorf("unknown model/table name `%s`", ex))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate join string.
|
||||
func (t *dbTables) getJoinSQL() (join string) {
|
||||
Q := t.base.TableQuote()
|
||||
|
||||
for _, jt := range t.tables {
|
||||
if jt.inner {
|
||||
join += "INNER JOIN "
|
||||
} else {
|
||||
join += "LEFT OUTER JOIN "
|
||||
}
|
||||
var (
|
||||
table string
|
||||
t1, t2 string
|
||||
c1, c2 string
|
||||
)
|
||||
t1 = "T0"
|
||||
if jt.jtl != nil {
|
||||
t1 = jt.jtl.index
|
||||
}
|
||||
t2 = jt.index
|
||||
table = jt.mi.table
|
||||
|
||||
switch {
|
||||
case jt.fi.fieldType == RelManyToMany || jt.fi.fieldType == RelReverseMany || jt.fi.reverse && jt.fi.reverseFieldInfo.fieldType == RelManyToMany:
|
||||
c1 = jt.fi.mi.fields.pk.column
|
||||
for _, ffi := range jt.mi.fields.fieldsRel {
|
||||
if jt.fi.mi == ffi.relModelInfo {
|
||||
c2 = ffi.column
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
c1 = jt.fi.column
|
||||
c2 = jt.fi.relModelInfo.fields.pk.column
|
||||
|
||||
if jt.fi.reverse {
|
||||
c1 = jt.mi.fields.pk.column
|
||||
c2 = jt.fi.reverseFieldInfo.column
|
||||
}
|
||||
}
|
||||
|
||||
join += fmt.Sprintf("%s%s%s %s ON %s.%s%s%s = %s.%s%s%s ", Q, table, Q, t2,
|
||||
t2, Q, c2, Q, t1, Q, c1, Q)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// parse orm model struct field tag expression.
|
||||
func (t *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string, info *fieldInfo, success bool) {
|
||||
var (
|
||||
jtl *dbTable
|
||||
fi *fieldInfo
|
||||
fiN *fieldInfo
|
||||
mmi = mi
|
||||
)
|
||||
|
||||
num := len(exprs) - 1
|
||||
var names []string
|
||||
|
||||
inner := true
|
||||
|
||||
loopFor:
|
||||
for i, ex := range exprs {
|
||||
|
||||
var ok, okN bool
|
||||
|
||||
if fiN != nil {
|
||||
fi = fiN
|
||||
ok = true
|
||||
fiN = nil
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
fi, ok = mmi.fields.GetByAny(ex)
|
||||
}
|
||||
|
||||
_ = okN
|
||||
|
||||
if ok {
|
||||
|
||||
isRel := fi.rel || fi.reverse
|
||||
|
||||
names = append(names, fi.name)
|
||||
|
||||
switch {
|
||||
case fi.rel:
|
||||
mmi = fi.relModelInfo
|
||||
if fi.fieldType == RelManyToMany {
|
||||
mmi = fi.relThroughModelInfo
|
||||
}
|
||||
case fi.reverse:
|
||||
mmi = fi.reverseFieldInfo.mi
|
||||
}
|
||||
|
||||
if i < num {
|
||||
fiN, okN = mmi.fields.GetByAny(exprs[i+1])
|
||||
}
|
||||
|
||||
if isRel && (fi.mi.isThrough == false || num != i) {
|
||||
if fi.null || t.skipEnd {
|
||||
inner = false
|
||||
}
|
||||
|
||||
if t.skipEnd && okN || !t.skipEnd {
|
||||
if t.skipEnd && okN && fiN.pk {
|
||||
goto loopEnd
|
||||
}
|
||||
|
||||
jt, _ := t.add(names, mmi, fi, inner)
|
||||
jt.jtl = jtl
|
||||
jtl = jt
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if num != i {
|
||||
continue
|
||||
}
|
||||
|
||||
loopEnd:
|
||||
|
||||
if i == 0 || jtl == nil {
|
||||
index = "T0"
|
||||
} else {
|
||||
index = jtl.index
|
||||
}
|
||||
|
||||
info = fi
|
||||
|
||||
if jtl == nil {
|
||||
name = fi.name
|
||||
} else {
|
||||
name = jtl.name + ExprSep + fi.name
|
||||
}
|
||||
|
||||
switch {
|
||||
case fi.rel:
|
||||
|
||||
case fi.reverse:
|
||||
switch fi.reverseFieldInfo.fieldType {
|
||||
case RelOneToOne, RelForeignKey:
|
||||
index = jtl.index
|
||||
info = fi.reverseFieldInfo.mi.fields.pk
|
||||
name = info.name
|
||||
}
|
||||
}
|
||||
|
||||
break loopFor
|
||||
|
||||
} else {
|
||||
index = ""
|
||||
name = ""
|
||||
info = nil
|
||||
success = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
success = index != "" && info != nil
|
||||
return
|
||||
}
|
||||
|
||||
// generate condition sql.
|
||||
func (t *dbTables) getCondSQL(cond *Condition, sub bool, tz *time.Location) (where string, params []interface{}) {
|
||||
if cond == nil || cond.IsEmpty() {
|
||||
return
|
||||
}
|
||||
|
||||
Q := t.base.TableQuote()
|
||||
|
||||
mi := t.mi
|
||||
|
||||
for i, p := range cond.params {
|
||||
if i > 0 {
|
||||
if p.isOr {
|
||||
where += "OR "
|
||||
} else {
|
||||
where += "AND "
|
||||
}
|
||||
}
|
||||
if p.isNot {
|
||||
where += "NOT "
|
||||
}
|
||||
if p.isCond {
|
||||
w, ps := t.getCondSQL(p.cond, true, tz)
|
||||
if w != "" {
|
||||
w = fmt.Sprintf("( %s) ", w)
|
||||
}
|
||||
where += w
|
||||
params = append(params, ps...)
|
||||
} else {
|
||||
exprs := p.exprs
|
||||
|
||||
num := len(exprs) - 1
|
||||
operator := ""
|
||||
if operators[exprs[num]] {
|
||||
operator = exprs[num]
|
||||
exprs = exprs[:num]
|
||||
}
|
||||
|
||||
index, _, fi, suc := t.parseExprs(mi, exprs)
|
||||
if suc == false {
|
||||
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(p.exprs, ExprSep)))
|
||||
}
|
||||
|
||||
if operator == "" {
|
||||
operator = "exact"
|
||||
}
|
||||
|
||||
operSQL, args := t.base.GenerateOperatorSQL(mi, fi, operator, p.args, tz)
|
||||
|
||||
leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q)
|
||||
t.base.GenerateOperatorLeftCol(fi, operator, &leftCol)
|
||||
|
||||
where += fmt.Sprintf("%s %s ", leftCol, operSQL)
|
||||
params = append(params, args...)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if sub == false && where != "" {
|
||||
where = "WHERE " + where
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// generate group sql.
|
||||
func (t *dbTables) getGroupSQL(groups []string) (groupSQL string) {
|
||||
if len(groups) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
Q := t.base.TableQuote()
|
||||
|
||||
groupSqls := make([]string, 0, len(groups))
|
||||
for _, group := range groups {
|
||||
exprs := strings.Split(group, ExprSep)
|
||||
|
||||
index, _, fi, suc := t.parseExprs(t.mi, exprs)
|
||||
if suc == false {
|
||||
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
|
||||
}
|
||||
|
||||
groupSqls = append(groupSqls, fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q))
|
||||
}
|
||||
|
||||
groupSQL = fmt.Sprintf("GROUP BY %s ", strings.Join(groupSqls, ", "))
|
||||
return
|
||||
}
|
||||
|
||||
// generate order sql.
|
||||
func (t *dbTables) getOrderSQL(orders []string) (orderSQL string) {
|
||||
if len(orders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
Q := t.base.TableQuote()
|
||||
|
||||
orderSqls := make([]string, 0, len(orders))
|
||||
for _, order := range orders {
|
||||
asc := "ASC"
|
||||
if order[0] == '-' {
|
||||
asc = "DESC"
|
||||
order = order[1:]
|
||||
}
|
||||
exprs := strings.Split(order, ExprSep)
|
||||
|
||||
index, _, fi, suc := t.parseExprs(t.mi, exprs)
|
||||
if suc == false {
|
||||
panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
|
||||
}
|
||||
|
||||
orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, fi.column, Q, asc))
|
||||
}
|
||||
|
||||
orderSQL = fmt.Sprintf("ORDER BY %s ", strings.Join(orderSqls, ", "))
|
||||
return
|
||||
}
|
||||
|
||||
// generate limit sql.
|
||||
func (t *dbTables) getLimitSQL(mi *modelInfo, offset int64, limit int64) (limits string) {
|
||||
if limit == 0 {
|
||||
limit = int64(DefaultRowsLimit)
|
||||
}
|
||||
if limit < 0 {
|
||||
// no limit
|
||||
if offset > 0 {
|
||||
maxLimit := t.base.MaxLimit()
|
||||
if maxLimit == 0 {
|
||||
limits = fmt.Sprintf("OFFSET %d", offset)
|
||||
} else {
|
||||
limits = fmt.Sprintf("LIMIT %d OFFSET %d", maxLimit, offset)
|
||||
}
|
||||
}
|
||||
} else if offset <= 0 {
|
||||
limits = fmt.Sprintf("LIMIT %d", limit)
|
||||
} else {
|
||||
limits = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// crete new tables collection.
|
||||
func newDbTables(mi *modelInfo, base dbBaser) *dbTables {
|
||||
tables := &dbTables{}
|
||||
tables.tablesM = make(map[string]*dbTable)
|
||||
tables.mi = mi
|
||||
tables.base = base
|
||||
return tables
|
||||
}
|
||||
63
vendor/github.com/fatedier/beego/orm/db_tidb.go
generated
vendored
Normal file
63
vendor/github.com/fatedier/beego/orm/db_tidb.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2015 TiDB Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// mysql dbBaser implementation.
|
||||
type dbBaseTidb struct {
|
||||
dbBase
|
||||
}
|
||||
|
||||
var _ dbBaser = new(dbBaseTidb)
|
||||
|
||||
// get mysql operator.
|
||||
func (d *dbBaseTidb) OperatorSQL(operator string) string {
|
||||
return mysqlOperators[operator]
|
||||
}
|
||||
|
||||
// get mysql table field types.
|
||||
func (d *dbBaseTidb) DbTypes() map[string]string {
|
||||
return mysqlTypes
|
||||
}
|
||||
|
||||
// show table sql for mysql.
|
||||
func (d *dbBaseTidb) ShowTablesQuery() string {
|
||||
return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()"
|
||||
}
|
||||
|
||||
// show columns sql of table for mysql.
|
||||
func (d *dbBaseTidb) ShowColumnsQuery(table string) string {
|
||||
return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+
|
||||
"WHERE table_schema = DATABASE() AND table_name = '%s'", table)
|
||||
}
|
||||
|
||||
// execute sql to check index exist.
|
||||
func (d *dbBaseTidb) IndexExists(db dbQuerier, table string, name string) bool {
|
||||
row := db.QueryRow("SELECT count(*) FROM information_schema.statistics "+
|
||||
"WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, name)
|
||||
var cnt int
|
||||
row.Scan(&cnt)
|
||||
return cnt > 0
|
||||
}
|
||||
|
||||
// create new mysql dbBaser.
|
||||
func newdbBaseTidb() dbBaser {
|
||||
b := new(dbBaseTidb)
|
||||
b.ins = b
|
||||
return b
|
||||
}
|
||||
177
vendor/github.com/fatedier/beego/orm/db_utils.go
generated
vendored
Normal file
177
vendor/github.com/fatedier/beego/orm/db_utils.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// get table alias.
|
||||
func getDbAlias(name string) *alias {
|
||||
if al, ok := dataBaseCache.get(name); ok {
|
||||
return al
|
||||
}
|
||||
panic(fmt.Errorf("unknown DataBase alias name %s", name))
|
||||
}
|
||||
|
||||
// get pk column info.
|
||||
func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) {
|
||||
fi := mi.fields.pk
|
||||
|
||||
v := ind.FieldByIndex(fi.fieldIndex)
|
||||
if fi.fieldType&IsPositiveIntegerField > 0 {
|
||||
vu := v.Uint()
|
||||
exist = vu > 0
|
||||
value = vu
|
||||
} else if fi.fieldType&IsIntegerField > 0 {
|
||||
vu := v.Int()
|
||||
exist = true
|
||||
value = vu
|
||||
} else if fi.fieldType&IsRelField > 0 {
|
||||
_, value, exist = getExistPk(fi.relModelInfo, reflect.Indirect(v))
|
||||
} else {
|
||||
vu := v.String()
|
||||
exist = vu != ""
|
||||
value = vu
|
||||
}
|
||||
|
||||
column = fi.column
|
||||
return
|
||||
}
|
||||
|
||||
// get fields description as flatted string.
|
||||
func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) {
|
||||
|
||||
outFor:
|
||||
for _, arg := range args {
|
||||
val := reflect.ValueOf(arg)
|
||||
|
||||
if arg == nil {
|
||||
params = append(params, arg)
|
||||
continue
|
||||
}
|
||||
|
||||
kind := val.Kind()
|
||||
if kind == reflect.Ptr {
|
||||
val = val.Elem()
|
||||
kind = val.Kind()
|
||||
arg = val.Interface()
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.String:
|
||||
v := val.String()
|
||||
if fi != nil {
|
||||
if fi.fieldType == TypeTimeField || fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField {
|
||||
var t time.Time
|
||||
var err error
|
||||
if len(v) >= 19 {
|
||||
s := v[:19]
|
||||
t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc)
|
||||
} else if len(v) >= 10 {
|
||||
s := v
|
||||
if len(v) > 10 {
|
||||
s = v[:10]
|
||||
}
|
||||
t, err = time.ParseInLocation(formatDate, s, tz)
|
||||
} else {
|
||||
s := v
|
||||
if len(s) > 8 {
|
||||
s = v[:8]
|
||||
}
|
||||
t, err = time.ParseInLocation(formatTime, s, tz)
|
||||
}
|
||||
if err == nil {
|
||||
if fi.fieldType == TypeDateField {
|
||||
v = t.In(tz).Format(formatDate)
|
||||
} else if fi.fieldType == TypeDateTimeField {
|
||||
v = t.In(tz).Format(formatDateTime)
|
||||
} else {
|
||||
v = t.In(tz).Format(formatTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arg = v
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
arg = val.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
arg = val.Uint()
|
||||
case reflect.Float32:
|
||||
arg, _ = StrTo(ToStr(arg)).Float64()
|
||||
case reflect.Float64:
|
||||
arg = val.Float()
|
||||
case reflect.Bool:
|
||||
arg = val.Bool()
|
||||
case reflect.Slice, reflect.Array:
|
||||
if _, ok := arg.([]byte); ok {
|
||||
continue outFor
|
||||
}
|
||||
|
||||
var args []interface{}
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
v := val.Index(i)
|
||||
|
||||
var vu interface{}
|
||||
if v.CanInterface() {
|
||||
vu = v.Interface()
|
||||
}
|
||||
|
||||
if vu == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
args = append(args, vu)
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
p := getFlatParams(fi, args, tz)
|
||||
params = append(params, p...)
|
||||
}
|
||||
continue outFor
|
||||
case reflect.Struct:
|
||||
if v, ok := arg.(time.Time); ok {
|
||||
if fi != nil && fi.fieldType == TypeDateField {
|
||||
arg = v.In(tz).Format(formatDate)
|
||||
} else if fi != nil && fi.fieldType == TypeDateTimeField {
|
||||
arg = v.In(tz).Format(formatDateTime)
|
||||
} else if fi != nil && fi.fieldType == TypeTimeField {
|
||||
arg = v.In(tz).Format(formatTime)
|
||||
} else {
|
||||
arg = v.In(tz).Format(formatDateTime)
|
||||
}
|
||||
} else {
|
||||
typ := val.Type()
|
||||
name := getFullName(typ)
|
||||
var value interface{}
|
||||
if mmi, ok := modelCache.getByFullName(name); ok {
|
||||
if _, vu, exist := getExistPk(mmi, val); exist {
|
||||
value = vu
|
||||
}
|
||||
}
|
||||
arg = value
|
||||
|
||||
if arg == nil {
|
||||
panic(fmt.Errorf("need a valid args value, unknown table or value `%s`", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params = append(params, arg)
|
||||
}
|
||||
return
|
||||
}
|
||||
99
vendor/github.com/fatedier/beego/orm/models.go
generated
vendored
Normal file
99
vendor/github.com/fatedier/beego/orm/models.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
odCascade = "cascade"
|
||||
odSetNULL = "set_null"
|
||||
odSetDefault = "set_default"
|
||||
odDoNothing = "do_nothing"
|
||||
defaultStructTagName = "orm"
|
||||
defaultStructTagDelim = ";"
|
||||
)
|
||||
|
||||
var (
|
||||
modelCache = &_modelCache{
|
||||
cache: make(map[string]*modelInfo),
|
||||
cacheByFullName: make(map[string]*modelInfo),
|
||||
}
|
||||
)
|
||||
|
||||
// model info collection
|
||||
type _modelCache struct {
|
||||
sync.RWMutex // only used outsite for bootStrap
|
||||
orders []string
|
||||
cache map[string]*modelInfo
|
||||
cacheByFullName map[string]*modelInfo
|
||||
done bool
|
||||
}
|
||||
|
||||
// get all model info
|
||||
func (mc *_modelCache) all() map[string]*modelInfo {
|
||||
m := make(map[string]*modelInfo, len(mc.cache))
|
||||
for k, v := range mc.cache {
|
||||
m[k] = v
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// get orderd model info
|
||||
func (mc *_modelCache) allOrdered() []*modelInfo {
|
||||
m := make([]*modelInfo, 0, len(mc.orders))
|
||||
for _, table := range mc.orders {
|
||||
m = append(m, mc.cache[table])
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// get model info by table name
|
||||
func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
|
||||
mi, ok = mc.cache[table]
|
||||
return
|
||||
}
|
||||
|
||||
// get model info by full name
|
||||
func (mc *_modelCache) getByFullName(name string) (mi *modelInfo, ok bool) {
|
||||
mi, ok = mc.cacheByFullName[name]
|
||||
return
|
||||
}
|
||||
|
||||
// set model info to collection
|
||||
func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
|
||||
mii := mc.cache[table]
|
||||
mc.cache[table] = mi
|
||||
mc.cacheByFullName[mi.fullName] = mi
|
||||
if mii == nil {
|
||||
mc.orders = append(mc.orders, table)
|
||||
}
|
||||
return mii
|
||||
}
|
||||
|
||||
// clean all model info.
|
||||
func (mc *_modelCache) clean() {
|
||||
mc.orders = make([]string, 0)
|
||||
mc.cache = make(map[string]*modelInfo)
|
||||
mc.cacheByFullName = make(map[string]*modelInfo)
|
||||
mc.done = false
|
||||
}
|
||||
|
||||
// ResetModelCache Clean model cache. Then you can re-RegisterModel.
|
||||
// Common use this api for test case.
|
||||
func ResetModelCache() {
|
||||
modelCache.clean()
|
||||
}
|
||||
345
vendor/github.com/fatedier/beego/orm/models_boot.go
generated
vendored
Normal file
345
vendor/github.com/fatedier/beego/orm/models_boot.go
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// register models.
|
||||
// PrefixOrSuffix means table name prefix or suffix.
|
||||
// isPrefix whether the prefix is prefix or suffix
|
||||
func registerModel(PrefixOrSuffix string, model interface{}, isPrefix bool) {
|
||||
val := reflect.ValueOf(model)
|
||||
typ := reflect.Indirect(val).Type()
|
||||
|
||||
if val.Kind() != reflect.Ptr {
|
||||
panic(fmt.Errorf("<orm.RegisterModel> cannot use non-ptr model struct `%s`", getFullName(typ)))
|
||||
}
|
||||
// For this case:
|
||||
// u := &User{}
|
||||
// registerModel(&u)
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
panic(fmt.Errorf("<orm.RegisterModel> only allow ptr model struct, it looks you use two reference to the struct `%s`", typ))
|
||||
}
|
||||
|
||||
table := getTableName(val)
|
||||
|
||||
if PrefixOrSuffix != "" {
|
||||
if isPrefix {
|
||||
table = PrefixOrSuffix + table
|
||||
} else {
|
||||
table = table + PrefixOrSuffix
|
||||
}
|
||||
}
|
||||
// models's fullname is pkgpath + struct name
|
||||
name := getFullName(typ)
|
||||
if _, ok := modelCache.getByFullName(name); ok {
|
||||
fmt.Printf("<orm.RegisterModel> model `%s` repeat register, must be unique\n", name)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if _, ok := modelCache.get(table); ok {
|
||||
fmt.Printf("<orm.RegisterModel> table name `%s` repeat register, must be unique\n", table)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
mi := newModelInfo(val)
|
||||
if mi.fields.pk == nil {
|
||||
outFor:
|
||||
for _, fi := range mi.fields.fieldsDB {
|
||||
if strings.ToLower(fi.name) == "id" {
|
||||
switch fi.addrValue.Elem().Kind() {
|
||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||
fi.auto = true
|
||||
fi.pk = true
|
||||
mi.fields.pk = fi
|
||||
break outFor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mi.fields.pk == nil {
|
||||
fmt.Printf("<orm.RegisterModel> `%s` need a primary key field, default use 'id' if not set\n", name)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mi.table = table
|
||||
mi.pkg = typ.PkgPath()
|
||||
mi.model = model
|
||||
mi.manual = true
|
||||
|
||||
modelCache.set(table, mi)
|
||||
}
|
||||
|
||||
// boostrap models
|
||||
func bootStrap() {
|
||||
if modelCache.done {
|
||||
return
|
||||
}
|
||||
var (
|
||||
err error
|
||||
models map[string]*modelInfo
|
||||
)
|
||||
if dataBaseCache.getDefault() == nil {
|
||||
err = fmt.Errorf("must have one register DataBase alias named `default`")
|
||||
goto end
|
||||
}
|
||||
|
||||
// set rel and reverse model
|
||||
// RelManyToMany set the relTable
|
||||
models = modelCache.all()
|
||||
for _, mi := range models {
|
||||
for _, fi := range mi.fields.columns {
|
||||
if fi.rel || fi.reverse {
|
||||
elm := fi.addrValue.Type().Elem()
|
||||
if fi.fieldType == RelReverseMany || fi.fieldType == RelManyToMany {
|
||||
elm = elm.Elem()
|
||||
}
|
||||
// check the rel or reverse model already register
|
||||
name := getFullName(elm)
|
||||
mii, ok := modelCache.getByFullName(name)
|
||||
if !ok || mii.pkg != elm.PkgPath() {
|
||||
err = fmt.Errorf("can not find rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String())
|
||||
goto end
|
||||
}
|
||||
fi.relModelInfo = mii
|
||||
|
||||
switch fi.fieldType {
|
||||
case RelManyToMany:
|
||||
if fi.relThrough != "" {
|
||||
if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) {
|
||||
pn := fi.relThrough[:i]
|
||||
rmi, ok := modelCache.getByFullName(fi.relThrough)
|
||||
if ok == false || pn != rmi.pkg {
|
||||
err = fmt.Errorf("field `%s` wrong rel_through value `%s` cannot find table", fi.fullName, fi.relThrough)
|
||||
goto end
|
||||
}
|
||||
fi.relThroughModelInfo = rmi
|
||||
fi.relTable = rmi.table
|
||||
} else {
|
||||
err = fmt.Errorf("field `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough)
|
||||
goto end
|
||||
}
|
||||
} else {
|
||||
i := newM2MModelInfo(mi, mii)
|
||||
if fi.relTable != "" {
|
||||
i.table = fi.relTable
|
||||
}
|
||||
if v := modelCache.set(i.table, i); v != nil {
|
||||
err = fmt.Errorf("the rel table name `%s` already registered, cannot be use, please change one", fi.relTable)
|
||||
goto end
|
||||
}
|
||||
fi.relTable = i.table
|
||||
fi.relThroughModelInfo = i
|
||||
}
|
||||
|
||||
fi.relThroughModelInfo.isThrough = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check the rel filed while the relModelInfo also has filed point to current model
|
||||
// if not exist, add a new field to the relModelInfo
|
||||
models = modelCache.all()
|
||||
for _, mi := range models {
|
||||
for _, fi := range mi.fields.fieldsRel {
|
||||
switch fi.fieldType {
|
||||
case RelForeignKey, RelOneToOne, RelManyToMany:
|
||||
inModel := false
|
||||
for _, ffi := range fi.relModelInfo.fields.fieldsReverse {
|
||||
if ffi.relModelInfo == mi {
|
||||
inModel = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if inModel == false {
|
||||
rmi := fi.relModelInfo
|
||||
ffi := new(fieldInfo)
|
||||
ffi.name = mi.name
|
||||
ffi.column = ffi.name
|
||||
ffi.fullName = rmi.fullName + "." + ffi.name
|
||||
ffi.reverse = true
|
||||
ffi.relModelInfo = mi
|
||||
ffi.mi = rmi
|
||||
if fi.fieldType == RelOneToOne {
|
||||
ffi.fieldType = RelReverseOne
|
||||
} else {
|
||||
ffi.fieldType = RelReverseMany
|
||||
}
|
||||
if rmi.fields.Add(ffi) == false {
|
||||
added := false
|
||||
for cnt := 0; cnt < 5; cnt++ {
|
||||
ffi.name = fmt.Sprintf("%s%d", mi.name, cnt)
|
||||
ffi.column = ffi.name
|
||||
ffi.fullName = rmi.fullName + "." + ffi.name
|
||||
if added = rmi.fields.Add(ffi); added {
|
||||
break
|
||||
}
|
||||
}
|
||||
if added == false {
|
||||
panic(fmt.Errorf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
models = modelCache.all()
|
||||
for _, mi := range models {
|
||||
for _, fi := range mi.fields.fieldsRel {
|
||||
switch fi.fieldType {
|
||||
case RelManyToMany:
|
||||
for _, ffi := range fi.relThroughModelInfo.fields.fieldsRel {
|
||||
switch ffi.fieldType {
|
||||
case RelOneToOne, RelForeignKey:
|
||||
if ffi.relModelInfo == fi.relModelInfo {
|
||||
fi.reverseFieldInfoTwo = ffi
|
||||
}
|
||||
if ffi.relModelInfo == mi {
|
||||
fi.reverseField = ffi.name
|
||||
fi.reverseFieldInfo = ffi
|
||||
}
|
||||
}
|
||||
}
|
||||
if fi.reverseFieldInfoTwo == nil {
|
||||
err = fmt.Errorf("can not find m2m field for m2m model `%s`, ensure your m2m model defined correct",
|
||||
fi.relThroughModelInfo.fullName)
|
||||
goto end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
models = modelCache.all()
|
||||
for _, mi := range models {
|
||||
for _, fi := range mi.fields.fieldsReverse {
|
||||
switch fi.fieldType {
|
||||
case RelReverseOne:
|
||||
found := false
|
||||
mForA:
|
||||
for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelOneToOne] {
|
||||
if ffi.relModelInfo == mi {
|
||||
found = true
|
||||
fi.reverseField = ffi.name
|
||||
fi.reverseFieldInfo = ffi
|
||||
|
||||
ffi.reverseField = fi.name
|
||||
ffi.reverseFieldInfo = fi
|
||||
break mForA
|
||||
}
|
||||
}
|
||||
if found == false {
|
||||
err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
|
||||
goto end
|
||||
}
|
||||
case RelReverseMany:
|
||||
found := false
|
||||
mForB:
|
||||
for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelForeignKey] {
|
||||
if ffi.relModelInfo == mi {
|
||||
found = true
|
||||
fi.reverseField = ffi.name
|
||||
fi.reverseFieldInfo = ffi
|
||||
|
||||
ffi.reverseField = fi.name
|
||||
ffi.reverseFieldInfo = fi
|
||||
|
||||
break mForB
|
||||
}
|
||||
}
|
||||
if found == false {
|
||||
mForC:
|
||||
for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] {
|
||||
conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough ||
|
||||
fi.relTable != "" && fi.relTable == ffi.relTable ||
|
||||
fi.relThrough == "" && fi.relTable == ""
|
||||
if ffi.relModelInfo == mi && conditions {
|
||||
found = true
|
||||
|
||||
fi.reverseField = ffi.reverseFieldInfoTwo.name
|
||||
fi.reverseFieldInfo = ffi.reverseFieldInfoTwo
|
||||
fi.relThroughModelInfo = ffi.relThroughModelInfo
|
||||
fi.reverseFieldInfoTwo = ffi.reverseFieldInfo
|
||||
fi.reverseFieldInfoM2M = ffi
|
||||
ffi.reverseFieldInfoM2M = fi
|
||||
|
||||
break mForC
|
||||
}
|
||||
}
|
||||
}
|
||||
if found == false {
|
||||
err = fmt.Errorf("reverse field for `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName)
|
||||
goto end
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterModel register models
|
||||
func RegisterModel(models ...interface{}) {
|
||||
if modelCache.done {
|
||||
panic(fmt.Errorf("RegisterModel must be run before BootStrap"))
|
||||
}
|
||||
RegisterModelWithPrefix("", models...)
|
||||
}
|
||||
|
||||
// RegisterModelWithPrefix register models with a prefix
|
||||
func RegisterModelWithPrefix(prefix string, models ...interface{}) {
|
||||
if modelCache.done {
|
||||
panic(fmt.Errorf("RegisterModelWithPrefix must be run before BootStrap"))
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
registerModel(prefix, model, true)
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterModelWithSuffix register models with a suffix
|
||||
func RegisterModelWithSuffix(suffix string, models ...interface{}) {
|
||||
if modelCache.done {
|
||||
panic(fmt.Errorf("RegisterModelWithSuffix must be run before BootStrap"))
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
registerModel(suffix, model, false)
|
||||
}
|
||||
}
|
||||
|
||||
// BootStrap bootrap models.
|
||||
// make all model parsed and can not add more models
|
||||
func BootStrap() {
|
||||
if modelCache.done {
|
||||
return
|
||||
}
|
||||
modelCache.Lock()
|
||||
defer modelCache.Unlock()
|
||||
bootStrap()
|
||||
modelCache.done = true
|
||||
}
|
||||
775
vendor/github.com/fatedier/beego/orm/models_fields.go
generated
vendored
Normal file
775
vendor/github.com/fatedier/beego/orm/models_fields.go
generated
vendored
Normal file
@@ -0,0 +1,775 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package orm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Define the Type enum
|
||||
const (
|
||||
TypeBooleanField = 1 << iota
|
||||
TypeCharField
|
||||
TypeTextField
|
||||
TypeTimeField
|
||||
TypeDateField
|
||||
TypeDateTimeField
|
||||
TypeBitField
|
||||
TypeSmallIntegerField
|
||||
TypeIntegerField
|
||||
TypeBigIntegerField
|
||||
TypePositiveBitField
|
||||
TypePositiveSmallIntegerField
|
||||
TypePositiveIntegerField
|
||||
TypePositiveBigIntegerField
|
||||
TypeFloatField
|
||||
TypeDecimalField
|
||||
TypeJSONField
|
||||
TypeJsonbField
|
||||
RelForeignKey
|
||||
RelOneToOne
|
||||
RelManyToMany
|
||||
RelReverseOne
|
||||
RelReverseMany
|
||||
)
|
||||
|
||||
// Define some logic enum
|
||||
const (
|
||||
IsIntegerField = ^-TypePositiveBigIntegerField >> 5 << 6
|
||||
IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 9 << 10
|
||||
IsRelField = ^-RelReverseMany >> 17 << 18
|
||||
IsFieldType = ^-RelReverseMany<<1 + 1
|
||||
)
|
||||
|
||||
// BooleanField A true/false field.
|
||||
type BooleanField bool
|
||||
|
||||
// Value return the BooleanField
|
||||
func (e BooleanField) Value() bool {
|
||||
return bool(e)
|
||||
}
|
||||
|
||||
// Set will set the BooleanField
|
||||
func (e *BooleanField) Set(d bool) {
|
||||
*e = BooleanField(d)
|
||||
}
|
||||
|
||||
// String format the Bool to string
|
||||
func (e *BooleanField) String() string {
|
||||
return strconv.FormatBool(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return BooleanField the type
|
||||
func (e *BooleanField) FieldType() int {
|
||||
return TypeBooleanField
|
||||
}
|
||||
|
||||
// SetRaw set the interface to bool
|
||||
func (e *BooleanField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case bool:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Bool()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
return err
|
||||
default:
|
||||
return fmt.Errorf("<BooleanField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return the current value
|
||||
func (e *BooleanField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify the BooleanField implement the Fielder interface
|
||||
var _ Fielder = new(BooleanField)
|
||||
|
||||
// CharField A string field
|
||||
// required values tag: size
|
||||
// The size is enforced at the database level and in models’s validation.
|
||||
// eg: `orm:"size(120)"`
|
||||
type CharField string
|
||||
|
||||
// Value return the CharField's Value
|
||||
func (e CharField) Value() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// Set CharField value
|
||||
func (e *CharField) Set(d string) {
|
||||
*e = CharField(d)
|
||||
}
|
||||
|
||||
// String return the CharField
|
||||
func (e *CharField) String() string {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// FieldType return the enum type
|
||||
func (e *CharField) FieldType() int {
|
||||
return TypeCharField
|
||||
}
|
||||
|
||||
// SetRaw set the interface to string
|
||||
func (e *CharField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case string:
|
||||
e.Set(d)
|
||||
default:
|
||||
return fmt.Errorf("<CharField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return the CharField value
|
||||
func (e *CharField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify CharField implement Fielder
|
||||
var _ Fielder = new(CharField)
|
||||
|
||||
// TimeField A time, represented in go by a time.Time instance.
|
||||
// only time values like 10:00:00
|
||||
// Has a few extra, optional attr tag:
|
||||
//
|
||||
// auto_now:
|
||||
// Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps.
|
||||
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||
//
|
||||
// auto_now_add:
|
||||
// Automatically set the field to now when the object is first created. Useful for creation of timestamps.
|
||||
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||
//
|
||||
// eg: `orm:"auto_now"` or `orm:"auto_now_add"`
|
||||
type TimeField time.Time
|
||||
|
||||
// Value return the time.Time
|
||||
func (e TimeField) Value() time.Time {
|
||||
return time.Time(e)
|
||||
}
|
||||
|
||||
// Set set the TimeField's value
|
||||
func (e *TimeField) Set(d time.Time) {
|
||||
*e = TimeField(d)
|
||||
}
|
||||
|
||||
// String convert time to string
|
||||
func (e *TimeField) String() string {
|
||||
return e.Value().String()
|
||||
}
|
||||
|
||||
// FieldType return enum type Date
|
||||
func (e *TimeField) FieldType() int {
|
||||
return TypeDateField
|
||||
}
|
||||
|
||||
// SetRaw convert the interface to time.Time. Allow string and time.Time
|
||||
func (e *TimeField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case time.Time:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := timeParse(d, formatTime)
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
return err
|
||||
default:
|
||||
return fmt.Errorf("<TimeField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return time value
|
||||
func (e *TimeField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
var _ Fielder = new(TimeField)
|
||||
|
||||
// DateField A date, represented in go by a time.Time instance.
|
||||
// only date values like 2006-01-02
|
||||
// Has a few extra, optional attr tag:
|
||||
//
|
||||
// auto_now:
|
||||
// Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps.
|
||||
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||
//
|
||||
// auto_now_add:
|
||||
// Automatically set the field to now when the object is first created. Useful for creation of timestamps.
|
||||
// Note that the current date is always used; it’s not just a default value that you can override.
|
||||
//
|
||||
// eg: `orm:"auto_now"` or `orm:"auto_now_add"`
|
||||
type DateField time.Time
|
||||
|
||||
// Value return the time.Time
|
||||
func (e DateField) Value() time.Time {
|
||||
return time.Time(e)
|
||||
}
|
||||
|
||||
// Set set the DateField's value
|
||||
func (e *DateField) Set(d time.Time) {
|
||||
*e = DateField(d)
|
||||
}
|
||||
|
||||
// String convert datatime to string
|
||||
func (e *DateField) String() string {
|
||||
return e.Value().String()
|
||||
}
|
||||
|
||||
// FieldType return enum type Date
|
||||
func (e *DateField) FieldType() int {
|
||||
return TypeDateField
|
||||
}
|
||||
|
||||
// SetRaw convert the interface to time.Time. Allow string and time.Time
|
||||
func (e *DateField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case time.Time:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := timeParse(d, formatDate)
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
return err
|
||||
default:
|
||||
return fmt.Errorf("<DateField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return Date value
|
||||
func (e *DateField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify DateField implement fielder interface
|
||||
var _ Fielder = new(DateField)
|
||||
|
||||
// DateTimeField A date, represented in go by a time.Time instance.
|
||||
// datetime values like 2006-01-02 15:04:05
|
||||
// Takes the same extra arguments as DateField.
|
||||
type DateTimeField time.Time
|
||||
|
||||
// Value return the datatime value
|
||||
func (e DateTimeField) Value() time.Time {
|
||||
return time.Time(e)
|
||||
}
|
||||
|
||||
// Set set the time.Time to datatime
|
||||
func (e *DateTimeField) Set(d time.Time) {
|
||||
*e = DateTimeField(d)
|
||||
}
|
||||
|
||||
// String return the time's String
|
||||
func (e *DateTimeField) String() string {
|
||||
return e.Value().String()
|
||||
}
|
||||
|
||||
// FieldType return the enum TypeDateTimeField
|
||||
func (e *DateTimeField) FieldType() int {
|
||||
return TypeDateTimeField
|
||||
}
|
||||
|
||||
// SetRaw convert the string or time.Time to DateTimeField
|
||||
func (e *DateTimeField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case time.Time:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := timeParse(d, formatDateTime)
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
return err
|
||||
default:
|
||||
return fmt.Errorf("<DateTimeField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return the datatime value
|
||||
func (e *DateTimeField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify datatime implement fielder
|
||||
var _ Fielder = new(DateTimeField)
|
||||
|
||||
// FloatField A floating-point number represented in go by a float32 value.
|
||||
type FloatField float64
|
||||
|
||||
// Value return the FloatField value
|
||||
func (e FloatField) Value() float64 {
|
||||
return float64(e)
|
||||
}
|
||||
|
||||
// Set the Float64
|
||||
func (e *FloatField) Set(d float64) {
|
||||
*e = FloatField(d)
|
||||
}
|
||||
|
||||
// String return the string
|
||||
func (e *FloatField) String() string {
|
||||
return ToStr(e.Value(), -1, 32)
|
||||
}
|
||||
|
||||
// FieldType return the enum type
|
||||
func (e *FloatField) FieldType() int {
|
||||
return TypeFloatField
|
||||
}
|
||||
|
||||
// SetRaw converter interface Float64 float32 or string to FloatField
|
||||
func (e *FloatField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case float32:
|
||||
e.Set(float64(d))
|
||||
case float64:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Float64()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<FloatField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return the FloatField value
|
||||
func (e *FloatField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify FloatField implement Fielder
|
||||
var _ Fielder = new(FloatField)
|
||||
|
||||
// SmallIntegerField -32768 to 32767
|
||||
type SmallIntegerField int16
|
||||
|
||||
// Value return int16 value
|
||||
func (e SmallIntegerField) Value() int16 {
|
||||
return int16(e)
|
||||
}
|
||||
|
||||
// Set the SmallIntegerField value
|
||||
func (e *SmallIntegerField) Set(d int16) {
|
||||
*e = SmallIntegerField(d)
|
||||
}
|
||||
|
||||
// String convert smallint to string
|
||||
func (e *SmallIntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return enum type SmallIntegerField
|
||||
func (e *SmallIntegerField) FieldType() int {
|
||||
return TypeSmallIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert interface int16/string to int16
|
||||
func (e *SmallIntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case int16:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Int16()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<SmallIntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return smallint value
|
||||
func (e *SmallIntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify SmallIntegerField implement Fielder
|
||||
var _ Fielder = new(SmallIntegerField)
|
||||
|
||||
// IntegerField -2147483648 to 2147483647
|
||||
type IntegerField int32
|
||||
|
||||
// Value return the int32
|
||||
func (e IntegerField) Value() int32 {
|
||||
return int32(e)
|
||||
}
|
||||
|
||||
// Set IntegerField value
|
||||
func (e *IntegerField) Set(d int32) {
|
||||
*e = IntegerField(d)
|
||||
}
|
||||
|
||||
// String convert Int32 to string
|
||||
func (e *IntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return the enum type
|
||||
func (e *IntegerField) FieldType() int {
|
||||
return TypeIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert interface int32/string to int32
|
||||
func (e *IntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case int32:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Int32()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<IntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return IntegerField value
|
||||
func (e *IntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify IntegerField implement Fielder
|
||||
var _ Fielder = new(IntegerField)
|
||||
|
||||
// BigIntegerField -9223372036854775808 to 9223372036854775807.
|
||||
type BigIntegerField int64
|
||||
|
||||
// Value return int64
|
||||
func (e BigIntegerField) Value() int64 {
|
||||
return int64(e)
|
||||
}
|
||||
|
||||
// Set the BigIntegerField value
|
||||
func (e *BigIntegerField) Set(d int64) {
|
||||
*e = BigIntegerField(d)
|
||||
}
|
||||
|
||||
// String convert BigIntegerField to string
|
||||
func (e *BigIntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (e *BigIntegerField) FieldType() int {
|
||||
return TypeBigIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert interface int64/string to int64
|
||||
func (e *BigIntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case int64:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Int64()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<BigIntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return BigIntegerField value
|
||||
func (e *BigIntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify BigIntegerField implement Fielder
|
||||
var _ Fielder = new(BigIntegerField)
|
||||
|
||||
// PositiveSmallIntegerField 0 to 65535
|
||||
type PositiveSmallIntegerField uint16
|
||||
|
||||
// Value return uint16
|
||||
func (e PositiveSmallIntegerField) Value() uint16 {
|
||||
return uint16(e)
|
||||
}
|
||||
|
||||
// Set PositiveSmallIntegerField value
|
||||
func (e *PositiveSmallIntegerField) Set(d uint16) {
|
||||
*e = PositiveSmallIntegerField(d)
|
||||
}
|
||||
|
||||
// String convert uint16 to string
|
||||
func (e *PositiveSmallIntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (e *PositiveSmallIntegerField) FieldType() int {
|
||||
return TypePositiveSmallIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert Interface uint16/string to uint16
|
||||
func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case uint16:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Uint16()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<PositiveSmallIntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue returns PositiveSmallIntegerField value
|
||||
func (e *PositiveSmallIntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify PositiveSmallIntegerField implement Fielder
|
||||
var _ Fielder = new(PositiveSmallIntegerField)
|
||||
|
||||
// PositiveIntegerField 0 to 4294967295
|
||||
type PositiveIntegerField uint32
|
||||
|
||||
// Value return PositiveIntegerField value. Uint32
|
||||
func (e PositiveIntegerField) Value() uint32 {
|
||||
return uint32(e)
|
||||
}
|
||||
|
||||
// Set the PositiveIntegerField value
|
||||
func (e *PositiveIntegerField) Set(d uint32) {
|
||||
*e = PositiveIntegerField(d)
|
||||
}
|
||||
|
||||
// String convert PositiveIntegerField to string
|
||||
func (e *PositiveIntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (e *PositiveIntegerField) FieldType() int {
|
||||
return TypePositiveIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert interface uint32/string to Uint32
|
||||
func (e *PositiveIntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case uint32:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Uint32()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<PositiveIntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return the PositiveIntegerField Value
|
||||
func (e *PositiveIntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify PositiveIntegerField implement Fielder
|
||||
var _ Fielder = new(PositiveIntegerField)
|
||||
|
||||
// PositiveBigIntegerField 0 to 18446744073709551615
|
||||
type PositiveBigIntegerField uint64
|
||||
|
||||
// Value return uint64
|
||||
func (e PositiveBigIntegerField) Value() uint64 {
|
||||
return uint64(e)
|
||||
}
|
||||
|
||||
// Set PositiveBigIntegerField value
|
||||
func (e *PositiveBigIntegerField) Set(d uint64) {
|
||||
*e = PositiveBigIntegerField(d)
|
||||
}
|
||||
|
||||
// String convert PositiveBigIntegerField to string
|
||||
func (e *PositiveBigIntegerField) String() string {
|
||||
return ToStr(e.Value())
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (e *PositiveBigIntegerField) FieldType() int {
|
||||
return TypePositiveIntegerField
|
||||
}
|
||||
|
||||
// SetRaw convert interface uint64/string to Uint64
|
||||
func (e *PositiveBigIntegerField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case uint64:
|
||||
e.Set(d)
|
||||
case string:
|
||||
v, err := StrTo(d).Uint64()
|
||||
if err != nil {
|
||||
e.Set(v)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("<PositiveBigIntegerField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return PositiveBigIntegerField value
|
||||
func (e *PositiveBigIntegerField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify PositiveBigIntegerField implement Fielder
|
||||
var _ Fielder = new(PositiveBigIntegerField)
|
||||
|
||||
// TextField A large text field.
|
||||
type TextField string
|
||||
|
||||
// Value return TextField value
|
||||
func (e TextField) Value() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
// Set the TextField value
|
||||
func (e *TextField) Set(d string) {
|
||||
*e = TextField(d)
|
||||
}
|
||||
|
||||
// String convert TextField to string
|
||||
func (e *TextField) String() string {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (e *TextField) FieldType() int {
|
||||
return TypeTextField
|
||||
}
|
||||
|
||||
// SetRaw convert interface string to string
|
||||
func (e *TextField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case string:
|
||||
e.Set(d)
|
||||
default:
|
||||
return fmt.Errorf("<TextField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return TextField value
|
||||
func (e *TextField) RawValue() interface{} {
|
||||
return e.Value()
|
||||
}
|
||||
|
||||
// verify TextField implement Fielder
|
||||
var _ Fielder = new(TextField)
|
||||
|
||||
// JSONField postgres json field.
|
||||
type JSONField string
|
||||
|
||||
// Value return JSONField value
|
||||
func (j JSONField) Value() string {
|
||||
return string(j)
|
||||
}
|
||||
|
||||
// Set the JSONField value
|
||||
func (j *JSONField) Set(d string) {
|
||||
*j = JSONField(d)
|
||||
}
|
||||
|
||||
// String convert JSONField to string
|
||||
func (j *JSONField) String() string {
|
||||
return j.Value()
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (j *JSONField) FieldType() int {
|
||||
return TypeJSONField
|
||||
}
|
||||
|
||||
// SetRaw convert interface string to string
|
||||
func (j *JSONField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case string:
|
||||
j.Set(d)
|
||||
default:
|
||||
return fmt.Errorf("<JSONField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return JSONField value
|
||||
func (j *JSONField) RawValue() interface{} {
|
||||
return j.Value()
|
||||
}
|
||||
|
||||
// verify JSONField implement Fielder
|
||||
var _ Fielder = new(JSONField)
|
||||
|
||||
// JsonbField postgres json field.
|
||||
type JsonbField string
|
||||
|
||||
// Value return JsonbField value
|
||||
func (j JsonbField) Value() string {
|
||||
return string(j)
|
||||
}
|
||||
|
||||
// Set the JsonbField value
|
||||
func (j *JsonbField) Set(d string) {
|
||||
*j = JsonbField(d)
|
||||
}
|
||||
|
||||
// String convert JsonbField to string
|
||||
func (j *JsonbField) String() string {
|
||||
return j.Value()
|
||||
}
|
||||
|
||||
// FieldType return enum type
|
||||
func (j *JsonbField) FieldType() int {
|
||||
return TypeJsonbField
|
||||
}
|
||||
|
||||
// SetRaw convert interface string to string
|
||||
func (j *JsonbField) SetRaw(value interface{}) error {
|
||||
switch d := value.(type) {
|
||||
case string:
|
||||
j.Set(d)
|
||||
default:
|
||||
return fmt.Errorf("<JsonbField.SetRaw> unknown value `%s`", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawValue return JsonbField value
|
||||
func (j *JsonbField) RawValue() interface{} {
|
||||
return j.Value()
|
||||
}
|
||||
|
||||
// verify JsonbField implement Fielder
|
||||
var _ Fielder = new(JsonbField)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user