Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
c59a029c
B
beego
项目概览
二次元的罪恶王冠
/
beego
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
beego
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c59a029c
编写于
1月 27, 2016
作者:
Y
youngsterxyf
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop' into config-logic
上级
20efd523
4ce094a2
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
545 addition
and
277 deletion
+545
-277
.travis.yml
.travis.yml
+9
-2
cache/memcache/memcache_test.go
cache/memcache/memcache_test.go
+1
-1
config.go
config.go
+16
-12
config/config.go
config/config.go
+36
-0
config/fake.go
config/fake.go
+1
-1
config/ini.go
config/ini.go
+32
-10
config/ini_test.go
config/ini_test.go
+119
-39
config/json.go
config/json.go
+3
-5
config/json_test.go
config/json_test.go
+88
-65
config/xml/xml.go
config/xml/xml.go
+4
-1
config/yaml/yaml.go
config/yaml/yaml.go
+3
-3
hooks.go
hooks.go
+4
-6
logs/conn.go
logs/conn.go
+6
-2
logs/console.go
logs/console.go
+17
-15
logs/es/es.go
logs/es/es.go
+4
-4
logs/file.go
logs/file.go
+6
-45
logs/log.go
logs/log.go
+52
-6
logs/smtp.go
logs/smtp.go
+2
-2
orm/types.go
orm/types.go
+6
-0
parser.go
parser.go
+3
-3
plugins/cors/cors.go
plugins/cors/cors.go
+2
-0
tree.go
tree.go
+18
-6
tree_test.go
tree_test.go
+29
-42
utils/mail.go
utils/mail.go
+84
-7
未找到文件。
.travis.yml
浏览文件 @
c59a029c
language
:
go
go
:
-
1.5.1
-
1.5.3
-
1.4.3
-
1.3.3
services
:
-
redis-server
-
mysql
...
...
@@ -24,7 +25,13 @@ install:
-
go get github.com/couchbase/go-couchbase
-
go get github.com/siddontang/ledisdb/config
-
go get github.com/siddontang/ledisdb/ledis
-
go get golang.org/x/tools/cmd/vet
-
go get github.com/golang/lint/golint
before_script
:
-
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"
script
:
-
go vet -x ./...
-
$HOME/gopath/bin/golint ./...
-
go test -v ./...
cache/memcache/memcache_test.go
浏览文件 @
c59a029c
...
...
@@ -37,7 +37,7 @@ func TestMemcacheCache(t *testing.T) {
t
.
Error
(
"check err"
)
}
time
.
Sleep
(
1
0
*
time
.
Second
)
time
.
Sleep
(
1
1
*
time
.
Second
)
if
bm
.
IsExist
(
"astaxie"
)
{
t
.
Error
(
"check err"
)
...
...
config.go
浏览文件 @
c59a029c
...
...
@@ -105,18 +105,25 @@ var (
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
// AppConfigPath is the path to the config files
AppConfigPath
string
// AppConfigProvider is the provider for the config, default is ini
AppConfigProvider
=
"ini"
// TemplateCache stores template caching
TemplateCache
map
[
string
]
*
template
.
Template
// 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"
workPath
string
)
func
init
()
{
AppPath
,
_
=
filepath
.
Abs
(
filepath
.
Dir
(
os
.
Args
[
0
]))
workPath
,
_
=
os
.
Getwd
()
workPath
,
_
=
filepath
.
Abs
(
workPath
)
BConfig
=
&
Config
{
AppName
:
"beego"
,
RunMode
:
DEV
,
...
...
@@ -177,8 +184,7 @@ func init() {
},
}
AppConfigPath
=
getDefaultAppConfigPath
()
AppConfigPath
=
filepath
.
Join
(
AppPath
,
"conf"
,
"app.conf"
)
if
!
utils
.
FileExists
(
AppConfigPath
)
{
AppConfig
=
&
beegoAppConfig
{
config
.
NewFakeConfig
()}
return
...
...
@@ -187,14 +193,12 @@ func init() {
parseConfig
(
AppConfigPath
)
}
func
getDefaultAppConfigPath
()
string
{
// default config path
AppPath
,
_
:=
filepath
.
Abs
(
filepath
.
Dir
(
os
.
Args
[
0
]))
return
filepath
.
Join
(
AppPath
,
"conf"
,
"app.conf"
)
}
// now only support ini, next will support json.
func
parseConfig
(
appConfigPath
string
)
(
err
error
)
{
if
workPath
!=
AppPath
{
os
.
Chdir
(
AppPath
)
}
AppConfig
,
err
=
newAppConfig
(
AppConfigProvider
,
appConfigPath
)
if
err
!=
nil
{
return
err
...
...
config/config.go
浏览文件 @
c59a029c
...
...
@@ -106,3 +106,39 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) {
}
return
adapter
.
ParseData
(
data
)
}
// 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"
)
}
config/fake.go
浏览文件 @
c59a029c
...
...
@@ -82,7 +82,7 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
}
func
(
c
*
fakeConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
return
strconv
.
ParseBool
(
c
.
getData
(
key
))
return
ParseBool
(
c
.
getData
(
key
))
}
func
(
c
*
fakeConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
...
...
config/ini.go
浏览文件 @
c59a029c
...
...
@@ -27,7 +27,6 @@ import (
"strings"
"sync"
"time"
"unicode"
)
var
(
...
...
@@ -97,9 +96,11 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
}
if
bComment
!=
nil
{
line
=
bytes
.
TrimLeft
(
line
,
string
(
bComment
))
line
=
bytes
.
TrimLeftFunc
(
line
,
unicode
.
IsSpace
)
// Need append to a new line if multi-line comments.
if
comment
.
Len
()
>
0
{
comment
.
WriteByte
(
'\n'
)
}
comment
.
Write
(
line
)
comment
.
WriteByte
(
'\n'
)
continue
}
...
...
@@ -194,7 +195,7 @@ type IniConfigContainer struct {
// Bool returns the boolean value for a given key.
func
(
c
*
IniConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
return
strconv
.
ParseBool
(
c
.
getdata
(
key
))
return
ParseBool
(
c
.
getdata
(
key
))
}
// DefaultBool returns the boolean value for a given key.
...
...
@@ -299,14 +300,35 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
}
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
,
ok
:=
c
.
keyComment
[
key
];
ok
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
v
:=
getCommentStr
(
defaultSection
,
key
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
}
}
...
...
@@ -327,8 +349,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
for
section
,
dt
:=
range
c
.
data
{
if
section
!=
defaultSection
{
// Write section comments.
if
v
,
ok
:=
c
.
sectionComment
[
section
];
ok
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
v
:=
getCommentStr
(
section
,
""
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
}
}
...
...
@@ -341,8 +363,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
for
key
,
val
:=
range
dt
{
if
key
!=
" "
{
// Write key comments.
if
v
,
ok
:=
c
.
keyComment
[
key
];
ok
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
v
:=
getCommentStr
(
section
,
key
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
}
}
...
...
config/ini_test.go
浏览文件 @
c59a029c
...
...
@@ -15,11 +15,17 @@
package
config
import
(
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
)
var
inicontext
=
`
func
TestIni
(
t
*
testing
.
T
)
{
var
(
inicontext
=
`
;comment one
#comment two
appname = beeapi
...
...
@@ -29,6 +35,13 @@ PI = 3.1415976
runmode = "dev"
autorender = false
copyrequestbody = true
session= on
cookieon= off
newreg = OFF
needlogin = ON
enableSession = Y
enableCookie = N
flag = 1
[demo]
key1="asta"
key2 = "xie"
...
...
@@ -36,7 +49,31 @@ CaseInsensitive = true
peers = one;two;three
`
func
TestIni
(
t
*
testing
.
T
)
{
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
,
"demo::key1"
:
"asta"
,
"demo::key2"
:
"xie"
,
"demo::CaseInsensitive"
:
true
,
"demo::peers"
:
[]
string
{
"one"
,
"two"
,
"three"
},
"null"
:
""
,
"demo2::key1"
:
""
,
"error"
:
""
,
}
)
f
,
err
:=
os
.
Create
(
"testini.conf"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -52,31 +89,31 @@ func TestIni(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
iniconf
.
String
(
"appname"
)
!=
"beeapi"
{
t
.
Fatal
(
"appname not equal to beeapi"
)
}
if
port
,
err
:=
iniconf
.
Int
(
"httpport"
);
err
!=
nil
||
port
!=
8080
{
t
.
Error
(
port
)
t
.
Fatal
(
err
)
}
if
port
,
err
:=
iniconf
.
Int64
(
"mysqlport"
);
err
!=
nil
||
port
!=
3600
{
t
.
Error
(
port
)
t
.
Fatal
(
err
)
}
if
pi
,
err
:=
iniconf
.
Float
(
"PI"
);
err
!=
nil
||
pi
!=
3.1415976
{
t
.
Error
(
pi
)
t
.
Fatal
(
err
)
}
if
iniconf
.
String
(
"runmode"
)
!=
"dev"
{
t
.
Fatal
(
"runmode not equal to dev"
)
}
if
v
,
err
:=
iniconf
.
Bool
(
"autorender"
);
err
!=
nil
||
v
!=
false
{
t
.
Error
(
v
)
t
.
Fatal
(
err
)
}
if
v
,
err
:=
iniconf
.
Bool
(
"copyrequestbody"
);
err
!=
nil
||
v
!=
true
{
t
.
Error
(
v
)
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
)
...
...
@@ -84,20 +121,63 @@ func TestIni(t *testing.T) {
if
iniconf
.
String
(
"name"
)
!=
"astaxie"
{
t
.
Fatal
(
"get name error"
)
}
if
iniconf
.
String
(
"demo::key1"
)
!=
"asta"
{
t
.
Fatal
(
"get demo.key1 error"
)
}
if
iniconf
.
String
(
"demo::key2"
)
!=
"xie"
{
t
.
Fatal
(
"get demo.key2 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
)
}
if
v
,
err
:=
iniconf
.
Bool
(
"demo::caseinsensitive"
);
err
!=
nil
||
v
!=
true
{
t
.
Fatal
(
"get demo.caseinsensitive error"
)
name
:=
"newIniConfig.ini"
if
err
:=
cfg
.
SaveConfigFile
(
name
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
Remove
(
name
)
if
data
:=
iniconf
.
Strings
(
"demo::peers"
);
len
(
data
)
!=
3
{
t
.
Fatal
(
"get strings error"
,
data
)
}
else
if
data
[
0
]
!=
"one"
{
t
.
Fatal
(
"get first params error not equat to one"
)
}
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
)
}
}
}
}
config/json.go
浏览文件 @
c59a029c
...
...
@@ -17,6 +17,7 @@ package config
import
(
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
...
...
@@ -70,12 +71,9 @@ type JSONConfigContainer struct {
func
(
c
*
JSONConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
bool
);
ok
{
return
v
,
nil
}
return
false
,
errors
.
New
(
"not bool value"
)
return
ParseBool
(
val
)
}
return
false
,
errors
.
New
(
"not exist key:"
+
key
)
return
false
,
fmt
.
Errorf
(
"not exist key: %q"
,
key
)
}
// DefaultBool return the bool value if has no error
...
...
config/json_test.go
浏览文件 @
c59a029c
...
...
@@ -15,34 +15,14 @@
package
config
import
(
"fmt"
"os"
"testing"
)
var
jsoncontext
=
`{
"appname": "beeapi",
"testnames": "foo;bar",
"httpport": 8080,
"mysqlport": 3600,
"PI": 3.1415976,
"runmode": "dev",
"autorender": false,
"copyrequestbody": true,
"database": {
"host": "host",
"port": "port",
"database": "database",
"username": "username",
"password": "password",
"conns":{
"maxconnection":12,
"autoconnect":true,
"connectioninfo":"info"
}
}
}`
func
TestJsonStartsWithArray
(
t
*
testing
.
T
)
{
var
jsoncontextwitharray
=
`[
const
jsoncontextwitharray
=
`[
{
"url": "user",
"serviceAPI": "http://www.test.com/user"
...
...
@@ -52,8 +32,6 @@ var jsoncontextwitharray = `[
"serviceAPI": "http://www.test.com/employee"
}
]`
func
TestJsonStartsWithArray
(
t
*
testing
.
T
)
{
f
,
err
:=
os
.
Create
(
"testjsonWithArray.conf"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -90,6 +68,64 @@ func TestJsonStartsWithArray(t *testing.T) {
}
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,
"database": {
"host": "host",
"port": "port",
"database": "database",
"username": "username",
"password": "password",
"conns":{
"maxconnection":12,
"autoconnect":true,
"connectioninfo":"info"
}
}
}`
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
,
"database::host"
:
"host"
,
"database::port"
:
"port"
,
"database::database"
:
"database"
,
"database::password"
:
"password"
,
"database::conns::maxconnection"
:
12
,
"database::conns::autoconnect"
:
true
,
"database::conns::connectioninfo"
:
"info"
,
"unknown"
:
""
,
}
)
f
,
err
:=
os
.
Create
(
"testjson.conf"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -105,37 +141,32 @@ func TestJson(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
jsonconf
.
String
(
"appname"
)
!=
"beeapi"
{
t
.
Fatal
(
"appname not equal to beeapi"
)
}
if
port
,
err
:=
jsonconf
.
Int
(
"httpport"
);
err
!=
nil
||
port
!=
8080
{
t
.
Error
(
port
)
t
.
Fatal
(
err
)
}
if
port
,
err
:=
jsonconf
.
Int64
(
"mysqlport"
);
err
!=
nil
||
port
!=
3600
{
t
.
Error
(
port
)
t
.
Fatal
(
err
)
}
if
pi
,
err
:=
jsonconf
.
Float
(
"PI"
);
err
!=
nil
||
pi
!=
3.1415976
{
t
.
Error
(
pi
)
t
.
Fatal
(
err
)
}
if
jsonconf
.
String
(
"runmode"
)
!=
"dev"
{
t
.
Fatal
(
"runmode not equal to dev"
)
}
if
v
:=
jsonconf
.
Strings
(
"unknown"
);
len
(
v
)
>
0
{
t
.
Fatal
(
"unknown strings, the length should be 0"
)
}
if
v
:=
jsonconf
.
Strings
(
"testnames"
);
len
(
v
)
!=
2
{
t
.
Fatal
(
"testnames length should be 2"
)
}
if
v
,
err
:=
jsonconf
.
Bool
(
"autorender"
);
err
!=
nil
||
v
!=
false
{
t
.
Error
(
v
)
t
.
Fatal
(
err
)
}
if
v
,
err
:=
jsonconf
.
Bool
(
"copyrequestbody"
);
err
!=
nil
||
v
!=
true
{
t
.
Error
(
v
)
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
)
...
...
@@ -143,15 +174,7 @@ func TestJson(t *testing.T) {
if
jsonconf
.
String
(
"name"
)
!=
"astaxie"
{
t
.
Fatal
(
"get name error"
)
}
if
jsonconf
.
String
(
"database::host"
)
!=
"host"
{
t
.
Fatal
(
"get database::host error"
)
}
if
jsonconf
.
String
(
"database::conns::connectioninfo"
)
!=
"info"
{
t
.
Fatal
(
"get database::conns::connectioninfo error"
)
}
if
maxconnection
,
err
:=
jsonconf
.
Int
(
"database::conns::maxconnection"
);
err
!=
nil
||
maxconnection
!=
12
{
t
.
Fatal
(
"get database::conns::maxconnection error"
)
}
if
db
,
err
:=
jsonconf
.
DIY
(
"database"
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
else
if
m
,
ok
:=
db
.
(
map
[
string
]
interface
{});
!
ok
{
...
...
config/xml/xml.go
浏览文件 @
c59a029c
...
...
@@ -92,7 +92,10 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key.
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
return
strconv
.
ParseBool
(
c
.
data
[
key
]
.
(
string
))
if
v
,
ok
:=
c
.
data
[
key
];
ok
{
return
config
.
ParseBool
(
v
)
}
return
false
,
fmt
.
Errorf
(
"not exist key: %q"
,
key
)
}
// DefaultBool return the bool value if has no error
...
...
config/yaml/yaml.go
浏览文件 @
c59a029c
...
...
@@ -121,10 +121,10 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key.
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
bool
)
;
ok
{
return
v
,
nil
if
v
,
ok
:=
c
.
data
[
key
];
ok
{
return
config
.
ParseBool
(
v
)
}
return
false
,
errors
.
New
(
"not bool value"
)
return
false
,
fmt
.
Errorf
(
"not exist key: %q"
,
key
)
}
// DefaultBool return the bool value if has no error
...
...
hooks.go
浏览文件 @
c59a029c
...
...
@@ -68,13 +68,11 @@ func registerSession() error {
}
func
registerTemplate
()
error
{
if
BConfig
.
WebConfig
.
AutoRender
{
if
err
:=
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
if
BConfig
.
RunMode
==
DEV
{
Warn
(
err
)
}
return
err
if
err
:=
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
if
BConfig
.
RunMode
==
DEV
{
Warn
(
err
)
}
return
err
}
return
nil
}
...
...
logs/conn.go
浏览文件 @
c59a029c
...
...
@@ -19,6 +19,7 @@ import (
"io"
"log"
"net"
"time"
)
// connWriter implements LoggerInterface.
...
...
@@ -48,7 +49,7 @@ func (c *connWriter) Init(jsonconfig string) error {
// WriteMsg write message in connection.
// if connection is down, try to re-connect.
func
(
c
*
connWriter
)
WriteMsg
(
msg
string
,
level
int
)
error
{
func
(
c
*
connWriter
)
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
{
if
level
>
c
.
Level
{
return
nil
}
...
...
@@ -62,6 +63,9 @@ func (c *connWriter) WriteMsg(msg string, level int) error {
if
c
.
ReconnectOnMsg
{
defer
c
.
innerWriter
.
Close
()
}
msg
=
formatLogTime
(
when
)
+
msg
c
.
lg
.
Println
(
msg
)
return
nil
}
...
...
@@ -94,7 +98,7 @@ func (c *connWriter) connect() error {
}
c
.
innerWriter
=
conn
c
.
lg
=
log
.
New
(
conn
,
""
,
log
.
Ldate
|
log
.
Ltime
)
c
.
lg
=
log
.
New
(
conn
,
""
,
0
)
return
nil
}
...
...
logs/console.go
浏览文件 @
c59a029c
...
...
@@ -19,6 +19,7 @@ import (
"log"
"os"
"runtime"
"time"
)
// brush is a color join function
...
...
@@ -34,14 +35,14 @@ func newBrush(color string) brush {
}
var
colors
=
[]
brush
{
newBrush
(
"1;37"
),
// Emergency
white
newBrush
(
"1;36"
),
// Alert
cyan
newBrush
(
"1;35"
),
// Critical magenta
newBrush
(
"1;31"
),
// Error red
newBrush
(
"1;33"
),
// Warning yellow
newBrush
(
"1;32"
),
// Notice
green
newBrush
(
"1;34"
),
// Informational
blue
newBrush
(
"1;34"
),
// Debug blue
newBrush
(
"1;37"
),
// Emergency
white
newBrush
(
"1;36"
),
// Alert
cyan
newBrush
(
"1;35"
),
// Critical
magenta
newBrush
(
"1;31"
),
// Error
red
newBrush
(
"1;33"
),
// Warning
yellow
newBrush
(
"1;32"
),
// Notice
green
newBrush
(
"1;34"
),
// Informational
blue
newBrush
(
"1;34"
),
// Debug
blue
}
// consoleWriter implements LoggerInterface and writes messages to terminal.
...
...
@@ -53,27 +54,28 @@ type consoleWriter struct {
// NewConsole create ConsoleWriter returning as LoggerInterface.
func
NewConsole
()
Logger
{
cw
:=
&
consoleWriter
{
lg
:
log
.
New
(
os
.
Stdout
,
""
,
log
.
Ldate
|
log
.
Ltime
),
lg
:
log
.
New
(
os
.
Stdout
,
""
,
0
),
Level
:
LevelDebug
,
}
return
cw
}
// Init init console logger.
// json
c
onfig like '{"level":LevelTrace}'.
func
(
c
*
consoleWriter
)
Init
(
json
c
onfig
string
)
error
{
if
len
(
json
c
onfig
)
==
0
{
// json
C
onfig like '{"level":LevelTrace}'.
func
(
c
*
consoleWriter
)
Init
(
json
C
onfig
string
)
error
{
if
len
(
json
C
onfig
)
==
0
{
return
nil
}
return
json
.
Unmarshal
([]
byte
(
json
c
onfig
),
c
)
return
json
.
Unmarshal
([]
byte
(
json
C
onfig
),
c
)
}
// WriteMsg write message in console.
func
(
c
*
consoleWriter
)
WriteMsg
(
msg
string
,
level
int
)
error
{
func
(
c
*
consoleWriter
)
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
{
if
level
>
c
.
Level
{
return
nil
}
if
goos
:=
runtime
.
GOOS
;
goos
==
"windows"
{
msg
=
formatLogTime
(
when
)
+
msg
if
runtime
.
GOOS
==
"windows"
{
c
.
lg
.
Println
(
msg
)
return
nil
}
...
...
logs/es/es.go
浏览文件 @
c59a029c
...
...
@@ -48,16 +48,16 @@ func (el *esLogger) Init(jsonconfig string) error {
}
// WriteMsg will write the msg and level into es
func
(
el
*
esLogger
)
WriteMsg
(
msg
string
,
level
int
)
error
{
func
(
el
*
esLogger
)
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
{
if
level
>
el
.
Level
{
return
nil
}
t
:=
time
.
Now
()
vals
:=
make
(
map
[
string
]
interface
{})
vals
[
"@timestamp"
]
=
t
.
Format
(
time
.
RFC3339
)
vals
[
"@timestamp"
]
=
when
.
Format
(
time
.
RFC3339
)
vals
[
"@msg"
]
=
msg
d
:=
goes
.
Document
{
Index
:
fmt
.
Sprintf
(
"%04d.%02d.%02d"
,
t
.
Year
(),
t
.
Month
(),
t
.
Day
()),
Index
:
fmt
.
Sprintf
(
"%04d.%02d.%02d"
,
when
.
Year
(),
when
.
Month
(),
when
.
Day
()),
Type
:
"logs"
,
Fields
:
vals
,
}
...
...
logs/file.go
浏览文件 @
c59a029c
...
...
@@ -114,59 +114,20 @@ func (w *fileLogWriter) needRotate(size int, day int) bool {
}
// WriteMsg write logger message into file.
func
(
w
*
fileLogWriter
)
WriteMsg
(
msg
string
,
level
int
)
error
{
func
(
w
*
fileLogWriter
)
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
{
if
level
>
w
.
Level
{
return
nil
}
//2016/01/12 21:34:33
now
:=
time
.
Now
()
y
,
mo
,
d
:=
now
.
Date
()
h
,
mi
,
s
:=
now
.
Clock
()
//len(2006/01/02 15:03:04)==19
var
buf
[
20
]
byte
t
:=
3
for
y
>=
10
{
p
:=
y
/
10
buf
[
t
]
=
byte
(
'0'
+
y
-
p
*
10
)
y
=
p
t
--
}
buf
[
0
]
=
byte
(
'0'
+
y
)
buf
[
4
]
=
'/'
if
mo
>
9
{
buf
[
5
]
=
'1'
buf
[
6
]
=
byte
(
'0'
+
mo
-
9
)
}
else
{
buf
[
5
]
=
'0'
buf
[
6
]
=
byte
(
'0'
+
mo
)
}
buf
[
7
]
=
'/'
t
=
d
/
10
buf
[
8
]
=
byte
(
'0'
+
t
)
buf
[
9
]
=
byte
(
'0'
+
d
-
t
*
10
)
buf
[
10
]
=
' '
t
=
h
/
10
buf
[
11
]
=
byte
(
'0'
+
t
)
buf
[
12
]
=
byte
(
'0'
+
h
-
t
*
10
)
buf
[
13
]
=
':'
t
=
mi
/
10
buf
[
14
]
=
byte
(
'0'
+
t
)
buf
[
15
]
=
byte
(
'0'
+
mi
-
t
*
10
)
buf
[
16
]
=
':'
t
=
s
/
10
buf
[
17
]
=
byte
(
'0'
+
t
)
buf
[
18
]
=
byte
(
'0'
+
s
-
t
*
10
)
buf
[
19
]
=
' '
msg
=
string
(
buf
[
0
:
])
+
msg
+
"
\n
"
msg
=
formatLogTime
(
when
)
+
msg
+
"
\n
"
if
w
.
Rotate
{
d
:=
when
.
Day
()
if
w
.
needRotate
(
len
(
msg
),
d
)
{
w
.
Lock
()
if
w
.
needRotate
(
len
(
msg
),
d
)
{
if
err
:=
w
.
doRotate
();
err
!=
nil
{
if
err
:=
w
.
doRotate
(
when
);
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"FileLogWriter(%q): %s
\n
"
,
w
.
Filename
,
err
)
}
}
w
.
Unlock
()
}
...
...
@@ -236,7 +197,7 @@ func (w *fileLogWriter) lines() (int, error) {
// DoRotate means it need to write file in new file.
// new file name like xx.2013-01-01.2.log
func
(
w
*
fileLogWriter
)
doRotate
()
error
{
func
(
w
*
fileLogWriter
)
doRotate
(
logTime
time
.
Time
)
error
{
_
,
err
:=
os
.
Lstat
(
w
.
Filename
)
if
err
!=
nil
{
return
err
...
...
@@ -251,7 +212,7 @@ func (w *fileLogWriter) doRotate() error {
suffix
=
".log"
}
for
;
err
==
nil
&&
num
<=
999
;
num
++
{
fName
=
filenameOnly
+
fmt
.
Sprintf
(
".%s.%03d%s"
,
time
.
Now
()
.
Format
(
"2006-01-02"
),
num
,
suffix
)
fName
=
filenameOnly
+
fmt
.
Sprintf
(
".%s.%03d%s"
,
logTime
.
Format
(
"2006-01-02"
),
num
,
suffix
)
_
,
err
=
os
.
Lstat
(
fName
)
}
// return error if the last file checked still existed
...
...
logs/log.go
浏览文件 @
c59a029c
...
...
@@ -40,6 +40,7 @@ import (
"runtime"
"strconv"
"sync"
"time"
)
// RFC5424 log message levels.
...
...
@@ -68,7 +69,7 @@ type loggerType func() Logger
// Logger defines the behavior of a log provider.
type
Logger
interface
{
Init
(
config
string
)
error
WriteMsg
(
msg
string
,
level
int
)
error
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
Destroy
()
Flush
()
}
...
...
@@ -108,6 +109,7 @@ type nameLogger struct {
type
logMsg
struct
{
level
int
msg
string
when
time
.
Time
}
var
logMsgPool
*
sync
.
Pool
...
...
@@ -173,9 +175,9 @@ func (bl *BeeLogger) DelLogger(adapterName string) error {
return
nil
}
func
(
bl
*
BeeLogger
)
writeToLoggers
(
msg
string
,
level
int
)
{
func
(
bl
*
BeeLogger
)
writeToLoggers
(
when
time
.
Time
,
msg
string
,
level
int
)
{
for
_
,
l
:=
range
bl
.
outputs
{
err
:=
l
.
WriteMsg
(
msg
,
level
)
err
:=
l
.
WriteMsg
(
when
,
msg
,
level
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"unable to WriteMsg to adapter:%v,error:%v
\n
"
,
l
.
name
,
err
)
}
...
...
@@ -183,6 +185,7 @@ func (bl *BeeLogger) writeToLoggers(msg string, level int) {
}
func
(
bl
*
BeeLogger
)
writeMsg
(
logLevel
int
,
msg
string
)
error
{
when
:=
time
.
Now
()
if
bl
.
enableFuncCallDepth
{
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
bl
.
loggerFuncCallDepth
)
if
!
ok
{
...
...
@@ -196,9 +199,10 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error {
lm
:=
logMsgPool
.
Get
()
.
(
*
logMsg
)
lm
.
level
=
logLevel
lm
.
msg
=
msg
lm
.
when
=
when
bl
.
msgChan
<-
lm
}
else
{
bl
.
writeToLoggers
(
msg
,
logLevel
)
bl
.
writeToLoggers
(
when
,
msg
,
logLevel
)
}
return
nil
}
...
...
@@ -231,7 +235,7 @@ func (bl *BeeLogger) startLogger() {
for
{
select
{
case
bm
:=
<-
bl
.
msgChan
:
bl
.
writeToLoggers
(
bm
.
msg
,
bm
.
level
)
bl
.
writeToLoggers
(
bm
.
when
,
bm
.
msg
,
bm
.
level
)
logMsgPool
.
Put
(
bm
)
}
}
...
...
@@ -351,7 +355,7 @@ func (bl *BeeLogger) Close() {
for
{
if
len
(
bl
.
msgChan
)
>
0
{
bm
:=
<-
bl
.
msgChan
bl
.
writeToLoggers
(
bm
.
msg
,
bm
.
level
)
bl
.
writeToLoggers
(
bm
.
when
,
bm
.
msg
,
bm
.
level
)
logMsgPool
.
Put
(
bm
)
continue
}
...
...
@@ -363,3 +367,45 @@ func (bl *BeeLogger) Close() {
}
bl
.
outputs
=
nil
}
func
formatLogTime
(
when
time
.
Time
)
string
{
y
,
mo
,
d
:=
when
.
Date
()
h
,
mi
,
s
:=
when
.
Clock
()
//len(2006/01/02 15:03:04)==19
var
buf
[
20
]
byte
t
:=
3
for
y
>=
10
{
p
:=
y
/
10
buf
[
t
]
=
byte
(
'0'
+
y
-
p
*
10
)
y
=
p
t
--
}
buf
[
0
]
=
byte
(
'0'
+
y
)
buf
[
4
]
=
'/'
if
mo
>
9
{
buf
[
5
]
=
'1'
buf
[
6
]
=
byte
(
'0'
+
mo
-
9
)
}
else
{
buf
[
5
]
=
'0'
buf
[
6
]
=
byte
(
'0'
+
mo
)
}
buf
[
7
]
=
'/'
t
=
d
/
10
buf
[
8
]
=
byte
(
'0'
+
t
)
buf
[
9
]
=
byte
(
'0'
+
d
-
t
*
10
)
buf
[
10
]
=
' '
t
=
h
/
10
buf
[
11
]
=
byte
(
'0'
+
t
)
buf
[
12
]
=
byte
(
'0'
+
h
-
t
*
10
)
buf
[
13
]
=
':'
t
=
mi
/
10
buf
[
14
]
=
byte
(
'0'
+
t
)
buf
[
15
]
=
byte
(
'0'
+
mi
-
t
*
10
)
buf
[
16
]
=
':'
t
=
s
/
10
buf
[
17
]
=
byte
(
'0'
+
t
)
buf
[
18
]
=
byte
(
'0'
+
s
-
t
*
10
)
buf
[
19
]
=
' '
return
string
(
buf
[
0
:
])
}
logs/smtp.go
浏览文件 @
c59a029c
...
...
@@ -126,7 +126,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
// WriteMsg write message in smtp writer.
// it will send an email with subject and only this message.
func
(
s
*
SMTPWriter
)
WriteMsg
(
msg
string
,
level
int
)
error
{
func
(
s
*
SMTPWriter
)
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
{
if
level
>
s
.
Level
{
return
nil
}
...
...
@@ -140,7 +140,7 @@ func (s *SMTPWriter) WriteMsg(msg string, level int) error {
// and send the email all in one step.
contentType
:=
"Content-Type: text/plain"
+
"; charset=UTF-8"
mailmsg
:=
[]
byte
(
"To: "
+
strings
.
Join
(
s
.
RecipientAddresses
,
";"
)
+
"
\r\n
From: "
+
s
.
FromAddress
+
"<"
+
s
.
FromAddress
+
">
\r\n
Subject: "
+
s
.
Subject
+
"
\r\n
"
+
contentType
+
"
\r\n\r\n
"
+
fmt
.
Sprintf
(
".%s"
,
time
.
Now
()
.
Format
(
"2006-01-02 15:04:05"
))
+
msg
)
">
\r\n
Subject: "
+
s
.
Subject
+
"
\r\n
"
+
contentType
+
"
\r\n\r\n
"
+
fmt
.
Sprintf
(
".%s"
,
when
.
Format
(
"2006-01-02 15:04:05"
))
+
msg
)
return
s
.
sendMail
(
s
.
Host
,
auth
,
s
.
FromAddress
,
s
.
RecipientAddresses
,
mailmsg
)
}
...
...
orm/types.go
浏览文件 @
c59a029c
...
...
@@ -162,6 +162,12 @@ type QuerySeter interface {
// qs.RelatedSel("profile").One(&user)
// user.Profile.Age = 32
RelatedSel
(
params
...
interface
{})
QuerySeter
// Set Distinct
// for example:
// o.QueryTable("policy").Filter("Groups__Group__Users__User", user).
// Distinct().
// All(&permissions)
Distinct
()
QuerySeter
// return QuerySeter execution result number
// for example:
// num, err = qs.Filter("profile__age__gt", 28).Count()
...
...
parser.go
浏览文件 @
c59a029c
...
...
@@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
}
func
genRouterCode
()
{
os
.
Mkdir
(
"routers"
,
0755
)
os
.
Mkdir
(
path
.
Join
(
AppPath
,
"routers"
)
,
0755
)
Info
(
"generate router from comments"
)
var
(
globalinfo
string
...
...
@@ -172,7 +172,7 @@ func genRouterCode() {
}
}
if
globalinfo
!=
""
{
f
,
err
:=
os
.
Create
(
path
.
Join
(
"routers"
,
commentFilename
))
f
,
err
:=
os
.
Create
(
path
.
Join
(
AppPath
,
"routers"
,
commentFilename
))
if
err
!=
nil
{
panic
(
err
)
}
...
...
@@ -182,7 +182,7 @@ func genRouterCode() {
}
func
compareFile
(
pkgRealpath
string
)
bool
{
if
!
utils
.
FileExists
(
path
.
Join
(
"routers"
,
commentFilename
))
{
if
!
utils
.
FileExists
(
path
.
Join
(
AppPath
,
"routers"
,
commentFilename
))
{
return
true
}
if
utils
.
FileExists
(
lastupdateFilename
)
{
...
...
plugins/cors/cors.go
浏览文件 @
c59a029c
...
...
@@ -36,6 +36,7 @@
package
cors
import
(
"net/http"
"regexp"
"strconv"
"strings"
...
...
@@ -215,6 +216,7 @@ func Allow(opts *Options) beego.FilterFunc {
for
key
,
value
:=
range
headers
{
ctx
.
Output
.
Header
(
key
,
value
)
}
ctx
.
ResponseWriter
.
WriteHeader
(
http
.
StatusOK
)
return
}
headers
=
opts
.
Header
(
origin
)
...
...
tree.go
浏览文件 @
c59a029c
...
...
@@ -141,7 +141,7 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st
regexpStr
=
"([^.]+).(.+)"
params
=
params
[
1
:
]
}
else
{
for
range
params
{
for
_
=
range
params
{
regexpStr
=
"([^/]+)/"
+
regexpStr
}
}
...
...
@@ -254,7 +254,7 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
regexpStr
=
"/([^.]+).(.+)"
params
=
params
[
1
:
]
}
else
{
for
range
params
{
for
_
=
range
params
{
regexpStr
=
"/([^/]+)"
+
regexpStr
}
}
...
...
@@ -420,7 +420,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
if
len
(
strs
)
==
2
{
ctx
.
Input
.
SetParam
(
":ext"
,
strs
[
1
])
}
ctx
.
Input
.
SetParam
(
":path"
,
path
.
Join
(
path
.
Join
(
wildcardValues
[
index
:
len
(
wildcardValues
)
-
1
]
...
),
strs
[
0
]))
if
index
>
(
len
(
wildcardValues
)
-
1
)
{
ctx
.
Input
.
SetParam
(
":path"
,
""
)
}
else
{
ctx
.
Input
.
SetParam
(
":path"
,
path
.
Join
(
path
.
Join
(
wildcardValues
[
index
:
len
(
wildcardValues
)
-
1
]
...
),
strs
[
0
]))
}
return
true
}
// match :id
...
...
@@ -438,7 +442,9 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
}
matches
:=
leaf
.
regexps
.
FindStringSubmatch
(
path
.
Join
(
wildcardValues
...
))
for
i
,
match
:=
range
matches
[
1
:
]
{
ctx
.
Input
.
SetParam
(
leaf
.
wildcards
[
i
],
match
)
if
i
<
len
(
leaf
.
wildcards
)
{
ctx
.
Input
.
SetParam
(
leaf
.
wildcards
[
i
],
match
)
}
}
return
true
}
...
...
@@ -536,13 +542,19 @@ func splitSegment(key string) (bool, []string, string) {
continue
}
}
if
v
==
':'
{
// Escape Sequence '\'
if
i
>
0
&&
key
[
i
-
1
]
==
'\\'
{
out
=
append
(
out
,
v
)
}
else
if
v
==
':'
{
param
=
make
([]
rune
,
0
)
start
=
true
}
else
if
v
==
'('
{
startexp
=
true
start
=
false
params
=
append
(
params
,
":"
+
string
(
param
))
if
len
(
param
)
>
0
{
params
=
append
(
params
,
":"
+
string
(
param
))
param
=
make
([]
rune
,
0
)
}
paramsNum
++
expt
=
make
([]
rune
,
0
)
expt
=
append
(
expt
,
'('
)
...
...
tree_test.go
浏览文件 @
c59a029c
...
...
@@ -15,6 +15,7 @@
package
beego
import
(
"strings"
"testing"
"github.com/astaxie/beego/context"
...
...
@@ -57,6 +58,9 @@ func init() {
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg"
,
map
[
string
]
string
{
":width"
:
"48"
,
":height"
:
"48"
,
":ext"
:
"jpg"
,
":path"
:
"05ac66d9bda00a3acf948c43e306fc9a"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id:int"
,
"/v1/shop/123"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id
\\
((a|b|c)
\\
)"
,
"/v1/shop/123(a)"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id
\\
((a|b|c)
\\
)"
,
"/v1/shop/123(b)"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id
\\
((a|b|c)
\\
)"
,
"/v1/shop/123(c)"
,
map
[
string
]
string
{
":id"
:
"123"
}})
routers
=
append
(
routers
,
testinfo
{
"/:year:int/:month:int/:id/:endid"
,
"/1111/111/aaa/aaa"
,
map
[
string
]
string
{
":year"
:
"1111"
,
":month"
:
"111"
,
":id"
:
"aaa"
,
":endid"
:
"aaa"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id/:name"
,
"/v1/shop/123/nike"
,
map
[
string
]
string
{
":id"
:
"123"
,
":name"
:
"nike"
}})
routers
=
append
(
routers
,
testinfo
{
"/v1/shop/:id/account"
,
"/v1/shop/123/account"
,
map
[
string
]
string
{
":id"
:
"123"
}})
...
...
@@ -245,48 +249,31 @@ func TestSplitPath(t *testing.T) {
}
func
TestSplitSegment
(
t
*
testing
.
T
)
{
b
,
w
,
r
:=
splitSegment
(
"admin"
)
if
b
||
len
(
w
)
!=
0
||
r
!=
""
{
t
.
Fatal
(
"admin should return false, nil, ''"
)
}
b
,
w
,
r
=
splitSegment
(
"*"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":splat"
||
r
!=
""
{
t
.
Fatal
(
"* should return true, [:splat], ''"
)
}
b
,
w
,
r
=
splitSegment
(
"*.*"
)
if
!
b
||
len
(
w
)
!=
3
||
w
[
1
]
!=
":path"
||
w
[
2
]
!=
":ext"
||
w
[
0
]
!=
"."
||
r
!=
""
{
t
.
Fatal
(
"admin should return true,[. :path :ext], ''"
)
}
b
,
w
,
r
=
splitSegment
(
":id"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":id"
||
r
!=
""
{
t
.
Fatal
(
":id should return true, [:id], ''"
)
}
b
,
w
,
r
=
splitSegment
(
"?:id"
)
if
!
b
||
len
(
w
)
!=
2
||
w
[
0
]
!=
":"
||
w
[
1
]
!=
":id"
||
r
!=
""
{
t
.
Fatal
(
"?:id should return true, [: :id], ''"
)
}
b
,
w
,
r
=
splitSegment
(
":id:int"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":id"
||
r
!=
"([0-9]+)"
{
t
.
Fatal
(
":id:int should return true, [:id], '([0-9]+)'"
)
}
b
,
w
,
r
=
splitSegment
(
":name:string"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":name"
||
r
!=
`([\w]+)`
{
t
.
Fatal
(
`:name:string should return true, [:name], '([\w]+)'`
)
}
b
,
w
,
r
=
splitSegment
(
":id([0-9]+)"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":id"
||
r
!=
`([0-9]+)`
{
t
.
Fatal
(
`:id([0-9]+) should return true, [:id], '([0-9]+)'`
)
}
b
,
w
,
r
=
splitSegment
(
":id([0-9]+)_:name"
)
if
!
b
||
len
(
w
)
!=
2
||
w
[
0
]
!=
":id"
||
w
[
1
]
!=
":name"
||
r
!=
`([0-9]+)_(.+)`
{
t
.
Fatal
(
`:id([0-9]+)_:name should return true, [:id :name], '([0-9]+)_(.+)'`
)
}
b
,
w
,
r
=
splitSegment
(
":id(.+)_cms.html"
)
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":id"
||
r
!=
`(.+)_cms.html`
{
t
.
Fatal
(
":id_cms.html should return true, [:id], '(.+)_cms.html'"
)
items
:=
map
[
string
]
struct
{
isReg
bool
params
[]
string
regStr
string
}{
"admin"
:
{
false
,
nil
,
""
},
"*"
:
{
true
,
[]
string
{
":splat"
},
""
},
"*.*"
:
{
true
,
[]
string
{
"."
,
":path"
,
":ext"
},
""
},
":id"
:
{
true
,
[]
string
{
":id"
},
""
},
"?:id"
:
{
true
,
[]
string
{
":"
,
":id"
},
""
},
":id:int"
:
{
true
,
[]
string
{
":id"
},
"([0-9]+)"
},
":name:string"
:
{
true
,
[]
string
{
":name"
},
`([\w]+)`
},
":id([0-9]+)"
:
{
true
,
[]
string
{
":id"
},
`([0-9]+)`
},
":id([0-9]+)_:name"
:
{
true
,
[]
string
{
":id"
,
":name"
},
`([0-9]+)_(.+)`
},
":id(.+)_cms.html"
:
{
true
,
[]
string
{
":id"
},
`(.+)_cms.html`
},
"cms_:id(.+)_:page(.+).html"
:
{
true
,
[]
string
{
":id"
,
":page"
},
`cms_(.+)_(.+).html`
},
`:app(a|b|c)`
:
{
true
,
[]
string
{
":app"
},
`(a|b|c)`
},
`:app\((a|b|c)\)`
:
{
true
,
[]
string
{
":app"
},
`(.+)\((a|b|c)\)`
},
}
b
,
w
,
r
=
splitSegment
(
"cms_:id(.+)_:page(.+).html"
)
if
!
b
||
len
(
w
)
!=
2
||
w
[
0
]
!=
":id"
||
w
[
1
]
!=
":page"
||
r
!=
`cms_(.+)_(.+).html`
{
t
.
Fatal
(
":id_cms.html should return true, [:id :page], cms_(.+)_(.+).html"
)
for
pattern
,
v
:=
range
items
{
b
,
w
,
r
:=
splitSegment
(
pattern
)
if
b
!=
v
.
isReg
||
r
!=
v
.
regStr
||
strings
.
Join
(
w
,
","
)
!=
strings
.
Join
(
v
.
params
,
","
)
{
t
.
Fatalf
(
"%s should return %t,%s,%q, got %t,%s,%q"
,
pattern
,
v
.
isReg
,
v
.
params
,
v
.
regStr
,
b
,
w
,
r
)
}
}
}
utils/mail.go
浏览文件 @
c59a029c
...
...
@@ -31,10 +31,13 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
)
const
(
maxLineLength
=
76
upperhex
=
"0123456789ABCDEF"
)
// Email is the type used for email messages
...
...
@@ -74,9 +77,6 @@ func NewEMail(config string) *Email {
if
err
!=
nil
{
return
nil
}
if
e
.
From
==
""
{
e
.
From
=
e
.
Username
}
return
e
}
...
...
@@ -228,14 +228,21 @@ func (e *Email) Send() error {
to
:=
make
([]
string
,
0
,
len
(
e
.
To
)
+
len
(
e
.
Cc
)
+
len
(
e
.
Bcc
))
to
=
append
(
append
(
append
(
to
,
e
.
To
...
),
e
.
Cc
...
),
e
.
Bcc
...
)
// Check to make sure there is at least one recipient and one "From" address
if
e
.
From
==
""
||
len
(
to
)
==
0
{
return
errors
.
New
(
"Must specify at least one
From address and one
To address"
)
if
len
(
to
)
==
0
{
return
errors
.
New
(
"Must specify at least one To address"
)
}
from
,
err
:=
mail
.
ParseAddress
(
e
.
From
)
from
,
err
:=
mail
.
ParseAddress
(
e
.
Username
)
if
err
!=
nil
{
return
err
}
e
.
From
=
from
.
String
()
if
len
(
e
.
From
)
==
0
{
e
.
From
=
e
.
Username
}
// use mail's RFC 2047 to encode any string
e
.
Subject
=
qEncode
(
"utf-8"
,
e
.
Subject
)
raw
,
err
:=
e
.
Bytes
()
if
err
!=
nil
{
return
err
...
...
@@ -342,3 +349,73 @@ func base64Wrap(w io.Writer, b []byte) {
w
.
Write
(
out
)
}
}
// Encode returns the encoded-word form of s. If s is ASCII without special
// characters, it is returned unchanged. The provided charset is the IANA
// charset name of s. It is case insensitive.
// RFC 2047 encoded-word
func
qEncode
(
charset
,
s
string
)
string
{
if
!
needsEncoding
(
s
)
{
return
s
}
return
encodeWord
(
charset
,
s
)
}
func
needsEncoding
(
s
string
)
bool
{
for
_
,
b
:=
range
s
{
if
(
b
<
' '
||
b
>
'~'
)
&&
b
!=
'\t'
{
return
true
}
}
return
false
}
// encodeWord encodes a string into an encoded-word.
func
encodeWord
(
charset
,
s
string
)
string
{
buf
:=
getBuffer
()
buf
.
WriteString
(
"=?"
)
buf
.
WriteString
(
charset
)
buf
.
WriteByte
(
'?'
)
buf
.
WriteByte
(
'q'
)
buf
.
WriteByte
(
'?'
)
enc
:=
make
([]
byte
,
3
)
for
i
:=
0
;
i
<
len
(
s
);
i
++
{
b
:=
s
[
i
]
switch
{
case
b
==
' '
:
buf
.
WriteByte
(
'_'
)
case
b
<=
'~'
&&
b
>=
'!'
&&
b
!=
'='
&&
b
!=
'?'
&&
b
!=
'_'
:
buf
.
WriteByte
(
b
)
default
:
enc
[
0
]
=
'='
enc
[
1
]
=
upperhex
[
b
>>
4
]
enc
[
2
]
=
upperhex
[
b
&
0x0f
]
buf
.
Write
(
enc
)
}
}
buf
.
WriteString
(
"?="
)
es
:=
buf
.
String
()
putBuffer
(
buf
)
return
es
}
var
bufPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
new
(
bytes
.
Buffer
)
},
}
func
getBuffer
()
*
bytes
.
Buffer
{
return
bufPool
.
Get
()
.
(
*
bytes
.
Buffer
)
}
func
putBuffer
(
buf
*
bytes
.
Buffer
)
{
if
buf
.
Len
()
>
1024
{
return
}
buf
.
Reset
()
bufPool
.
Put
(
buf
)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录