Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
c59a029c
Commit
c59a029c
authored
Jan 27, 2016
by
youngsterxyf
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into config-logic
parents
20efd523
4ce094a2
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
523 additions
and
255 deletions
+523
-255
.travis.yml
.travis.yml
+9
-2
memcache_test.go
cache/memcache/memcache_test.go
+1
-1
config.go
config.go
+16
-12
config.go
config/config.go
+36
-0
fake.go
config/fake.go
+1
-1
ini.go
config/ini.go
+32
-10
ini_test.go
config/ini_test.go
+115
-35
json.go
config/json.go
+3
-5
json_test.go
config/json_test.go
+86
-63
xml.go
config/xml/xml.go
+4
-1
yaml.go
config/yaml/yaml.go
+3
-3
hooks.go
hooks.go
+0
-2
conn.go
logs/conn.go
+6
-2
console.go
logs/console.go
+9
-7
es.go
logs/es/es.go
+4
-4
file.go
logs/file.go
+6
-45
log.go
logs/log.go
+52
-6
smtp.go
logs/smtp.go
+2
-2
types.go
orm/types.go
+6
-0
parser.go
parser.go
+3
-3
cors.go
plugins/cors/cors.go
+2
-0
tree.go
tree.go
+15
-3
tree_test.go
tree_test.go
+28
-41
mail.go
utils/mail.go
+84
-7
No files found.
.travis.yml
View file @
c59a029c
language
:
go
language
:
go
go
:
go
:
-
1.5.1
-
1.5.3
-
1.4.3
-
1.3.3
services
:
services
:
-
redis-server
-
redis-server
-
mysql
-
mysql
...
@@ -24,7 +25,13 @@ install:
...
@@ -24,7 +25,13 @@ install:
-
go get github.com/couchbase/go-couchbase
-
go get github.com/couchbase/go-couchbase
-
go get github.com/siddontang/ledisdb/config
-
go get github.com/siddontang/ledisdb/config
-
go get github.com/siddontang/ledisdb/ledis
-
go get github.com/siddontang/ledisdb/ledis
-
go get golang.org/x/tools/cmd/vet
-
go get github.com/golang/lint/golint
before_script
:
before_script
:
-
sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi"
-
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' = '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 [ '$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
View file @
c59a029c
...
@@ -37,7 +37,7 @@ func TestMemcacheCache(t *testing.T) {
...
@@ -37,7 +37,7 @@ func TestMemcacheCache(t *testing.T) {
t
.
Error
(
"check err"
)
t
.
Error
(
"check err"
)
}
}
time
.
Sleep
(
1
0
*
time
.
Second
)
time
.
Sleep
(
1
1
*
time
.
Second
)
if
bm
.
IsExist
(
"astaxie"
)
{
if
bm
.
IsExist
(
"astaxie"
)
{
t
.
Error
(
"check err"
)
t
.
Error
(
"check err"
)
...
...
config.go
View file @
c59a029c
...
@@ -105,18 +105,25 @@ var (
...
@@ -105,18 +105,25 @@ var (
BConfig
*
Config
BConfig
*
Config
// AppConfig is the instance of Config, store the config information from file
// AppConfig is the instance of Config, store the config information from file
AppConfig
*
beegoAppConfig
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 stores template caching
TemplateCache
map
[
string
]
*
template
.
Template
TemplateCache
map
[
string
]
*
template
.
Template
// GlobalSessions is the instance for the session manager
// GlobalSessions is the instance for the session manager
GlobalSessions
*
session
.
Manager
GlobalSessions
*
session
.
Manager
// AppConfigPath is the path to the config files
workPath
string
AppConfigPath
string
// AppConfigProvider is the provider for the config, default is ini
AppConfigProvider
=
"ini"
)
)
func
init
()
{
func
init
()
{
AppPath
,
_
=
filepath
.
Abs
(
filepath
.
Dir
(
os
.
Args
[
0
]))
workPath
,
_
=
os
.
Getwd
()
workPath
,
_
=
filepath
.
Abs
(
workPath
)
BConfig
=
&
Config
{
BConfig
=
&
Config
{
AppName
:
"beego"
,
AppName
:
"beego"
,
RunMode
:
DEV
,
RunMode
:
DEV
,
...
@@ -177,8 +184,7 @@ func init() {
...
@@ -177,8 +184,7 @@ func init() {
},
},
}
}
AppConfigPath
=
getDefaultAppConfigPath
()
AppConfigPath
=
filepath
.
Join
(
AppPath
,
"conf"
,
"app.conf"
)
if
!
utils
.
FileExists
(
AppConfigPath
)
{
if
!
utils
.
FileExists
(
AppConfigPath
)
{
AppConfig
=
&
beegoAppConfig
{
config
.
NewFakeConfig
()}
AppConfig
=
&
beegoAppConfig
{
config
.
NewFakeConfig
()}
return
return
...
@@ -187,14 +193,12 @@ func init() {
...
@@ -187,14 +193,12 @@ func init() {
parseConfig
(
AppConfigPath
)
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.
// now only support ini, next will support json.
func
parseConfig
(
appConfigPath
string
)
(
err
error
)
{
func
parseConfig
(
appConfigPath
string
)
(
err
error
)
{
if
workPath
!=
AppPath
{
os
.
Chdir
(
AppPath
)
}
AppConfig
,
err
=
newAppConfig
(
AppConfigProvider
,
appConfigPath
)
AppConfig
,
err
=
newAppConfig
(
AppConfigProvider
,
appConfigPath
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
...
config/config.go
View file @
c59a029c
...
@@ -106,3 +106,39 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) {
...
@@ -106,3 +106,39 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) {
}
}
return
adapter
.
ParseData
(
data
)
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
View file @
c59a029c
...
@@ -82,7 +82,7 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
...
@@ -82,7 +82,7 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
}
}
func
(
c
*
fakeConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
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
{
func
(
c
*
fakeConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
...
...
config/ini.go
View file @
c59a029c
...
@@ -27,7 +27,6 @@ import (
...
@@ -27,7 +27,6 @@ import (
"strings"
"strings"
"sync"
"sync"
"time"
"time"
"unicode"
)
)
var
(
var
(
...
@@ -97,9 +96,11 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
...
@@ -97,9 +96,11 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
}
}
if
bComment
!=
nil
{
if
bComment
!=
nil
{
line
=
bytes
.
TrimLeft
(
line
,
string
(
bComment
))
line
=
bytes
.
TrimLeft
(
line
,
string
(
bComment
))
line
=
bytes
.
TrimLeftFunc
(
line
,
unicode
.
IsSpace
)
// Need append to a new line if multi-line comments.
comment
.
Write
(
line
)
if
comment
.
Len
()
>
0
{
comment
.
WriteByte
(
'\n'
)
comment
.
WriteByte
(
'\n'
)
}
comment
.
Write
(
line
)
continue
continue
}
}
...
@@ -194,7 +195,7 @@ type IniConfigContainer struct {
...
@@ -194,7 +195,7 @@ type IniConfigContainer struct {
// Bool returns the boolean value for a given key.
// Bool returns the boolean value for a given key.
func
(
c
*
IniConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
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.
// DefaultBool returns the boolean value for a given key.
...
@@ -299,14 +300,35 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
...
@@ -299,14 +300,35 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
}
}
defer
f
.
Close
()
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
)
buf
:=
bytes
.
NewBuffer
(
nil
)
// Save default section at first place
// Save default section at first place
if
dt
,
ok
:=
c
.
data
[
defaultSection
];
ok
{
if
dt
,
ok
:=
c
.
data
[
defaultSection
];
ok
{
for
key
,
val
:=
range
dt
{
for
key
,
val
:=
range
dt
{
if
key
!=
" "
{
if
key
!=
" "
{
// Write key comments.
// Write key comments.
if
v
,
ok
:=
c
.
keyComment
[
key
];
ok
{
if
v
:=
getCommentStr
(
defaultSection
,
key
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
return
err
}
}
}
}
...
@@ -327,8 +349,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
...
@@ -327,8 +349,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
for
section
,
dt
:=
range
c
.
data
{
for
section
,
dt
:=
range
c
.
data
{
if
section
!=
defaultSection
{
if
section
!=
defaultSection
{
// Write section comments.
// Write section comments.
if
v
,
ok
:=
c
.
sectionComment
[
section
];
ok
{
if
v
:=
getCommentStr
(
section
,
""
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
return
err
}
}
}
}
...
@@ -341,8 +363,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
...
@@ -341,8 +363,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
for
key
,
val
:=
range
dt
{
for
key
,
val
:=
range
dt
{
if
key
!=
" "
{
if
key
!=
" "
{
// Write key comments.
// Write key comments.
if
v
,
ok
:=
c
.
keyComment
[
key
];
ok
{
if
v
:=
getCommentStr
(
section
,
key
);
len
(
v
)
>
0
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
if
_
,
err
=
buf
.
WriteString
(
v
+
lineBreak
);
err
!=
nil
{
return
err
return
err
}
}
}
}
...
...
config/ini_test.go
View file @
c59a029c
...
@@ -15,11 +15,17 @@
...
@@ -15,11 +15,17 @@
package
config
package
config
import
(
import
(
"fmt"
"io/ioutil"
"os"
"os"
"strings"
"testing"
"testing"
)
)
var
inicontext
=
`
func
TestIni
(
t
*
testing
.
T
)
{
var
(
inicontext
=
`
;comment one
;comment one
#comment two
#comment two
appname = beeapi
appname = beeapi
...
@@ -29,6 +35,13 @@ PI = 3.1415976
...
@@ -29,6 +35,13 @@ PI = 3.1415976
runmode = "dev"
runmode = "dev"
autorender = false
autorender = false
copyrequestbody = true
copyrequestbody = true
session= on
cookieon= off
newreg = OFF
needlogin = ON
enableSession = Y
enableCookie = N
flag = 1
[demo]
[demo]
key1="asta"
key1="asta"
key2 = "xie"
key2 = "xie"
...
@@ -36,7 +49,31 @@ CaseInsensitive = true
...
@@ -36,7 +49,31 @@ CaseInsensitive = true
peers = one;two;three
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"
)
f
,
err
:=
os
.
Create
(
"testini.conf"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -52,52 +89,95 @@ func TestIni(t *testing.T) {
...
@@ -52,52 +89,95 @@ func TestIni(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
iniconf
.
String
(
"appname"
)
!=
"beeapi"
{
for
k
,
v
:=
range
keyValue
{
t
.
Fatal
(
"appname not equal to beeapi"
)
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
port
,
err
:=
iniconf
.
Int
(
"httpport"
);
err
!=
nil
||
port
!=
8080
{
if
err
!=
nil
{
t
.
Error
(
port
)
t
.
Fatalf
(
"get key %q value fail,err %s"
,
k
,
err
)
t
.
Fatal
(
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
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
{
if
err
=
iniconf
.
Set
(
"name"
,
"astaxie"
);
err
!=
nil
{
t
.
Error
(
pi
)
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
iniconf
.
String
(
"
runmode"
)
!=
"dev
"
{
if
iniconf
.
String
(
"
name"
)
!=
"astaxie
"
{
t
.
Fatal
(
"
runmode not equal to dev
"
)
t
.
Fatal
(
"
get name error
"
)
}
}
if
v
,
err
:=
iniconf
.
Bool
(
"autorender"
);
err
!=
nil
||
v
!=
false
{
t
.
Error
(
v
)
}
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
)
t
.
Fatal
(
err
)
}
}
if
v
,
err
:=
iniconf
.
Bool
(
"copyrequestbody"
);
err
!=
nil
||
v
!=
true
{
name
:=
"newIniConfig.ini"
t
.
Error
(
v
)
if
err
:=
cfg
.
SaveConfigFile
(
name
);
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
err
=
iniconf
.
Set
(
"name"
,
"astaxie"
);
err
!=
nil
{
defer
os
.
Remove
(
name
)
if
data
,
err
:=
ioutil
.
ReadFile
(
name
);
err
!=
nil
{
t
.
Fatal
(
err
)
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
)
}
}
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"
)
}
if
v
,
err
:=
iniconf
.
Bool
(
"demo::caseinsensitive"
);
err
!=
nil
||
v
!=
true
{
t
.
Fatal
(
"get demo.caseinsensitive error"
)
}
}
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"
)
}
}
}
}
config/json.go
View file @
c59a029c
...
@@ -17,6 +17,7 @@ package config
...
@@ -17,6 +17,7 @@ package config
import
(
import
(
"encoding/json"
"encoding/json"
"errors"
"errors"
"fmt"
"io/ioutil"
"io/ioutil"
"os"
"os"
"strings"
"strings"
...
@@ -70,12 +71,9 @@ type JSONConfigContainer struct {
...
@@ -70,12 +71,9 @@ type JSONConfigContainer struct {
func
(
c
*
JSONConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
func
(
c
*
JSONConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
val
:=
c
.
getData
(
key
)
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
bool
);
ok
{
return
ParseBool
(
val
)
return
v
,
nil
}
return
false
,
errors
.
New
(
"not bool value"
)
}
}
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
// DefaultBool return the bool value if has no error
...
...
config/json_test.go
View file @
c59a029c
...
@@ -15,34 +15,14 @@
...
@@ -15,34 +15,14 @@
package
config
package
config
import
(
import
(
"fmt"
"os"
"os"
"testing"
"testing"
)
)
var
jsoncontext
=
`{
func
TestJsonStartsWithArray
(
t
*
testing
.
T
)
{
"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"
}
}
}`
var
jsoncontextwitharray
=
`[
const
jsoncontextwitharray
=
`[
{
{
"url": "user",
"url": "user",
"serviceAPI": "http://www.test.com/user"
"serviceAPI": "http://www.test.com/user"
...
@@ -52,8 +32,6 @@ var jsoncontextwitharray = `[
...
@@ -52,8 +32,6 @@ var jsoncontextwitharray = `[
"serviceAPI": "http://www.test.com/employee"
"serviceAPI": "http://www.test.com/employee"
}
}
]`
]`
func
TestJsonStartsWithArray
(
t
*
testing
.
T
)
{
f
,
err
:=
os
.
Create
(
"testjsonWithArray.conf"
)
f
,
err
:=
os
.
Create
(
"testjsonWithArray.conf"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -90,6 +68,64 @@ func TestJsonStartsWithArray(t *testing.T) {
...
@@ -90,6 +68,64 @@ func TestJsonStartsWithArray(t *testing.T) {
}
}
func
TestJson
(
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"
)
f
,
err
:=
os
.
Create
(
"testjson.conf"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -105,37 +141,32 @@ func TestJson(t *testing.T) {
...
@@ -105,37 +141,32 @@ func TestJson(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
jsonconf
.
String
(
"appname"
)
!=
"beeapi"
{
t
.
Fatal
(
"appname not equal to beeapi"
)
for
k
,
v
:=
range
keyValue
{
}
var
err
error
if
port
,
err
:=
jsonconf
.
Int
(
"httpport"
);
err
!=
nil
||
port
!=
8080
{
var
value
interface
{}
t
.
Error
(
port
)
switch
v
.
(
type
)
{
t
.
Fatal
(
err
)
case
int
:
}
value
,
err
=
jsonconf
.
Int
(
k
)
if
port
,
err
:=
jsonconf
.
Int64
(
"mysqlport"
);
err
!=
nil
||
port
!=
3600
{
case
int64
:
t
.
Error
(
port
)
value
,
err
=
jsonconf
.
Int64
(
k
)
t
.
Fatal
(
err
)
case
float64
:
}
value
,
err
=
jsonconf
.
Float
(
k
)
if
pi
,
err
:=
jsonconf
.
Float
(
"PI"
);
err
!=
nil
||
pi
!=
3.1415976
{
case
bool
:
t
.
Error
(
pi
)
value
,
err
=
jsonconf
.
Bool
(
k
)
t
.
Fatal
(
err
)
case
[]
string
:
}
value
=
jsonconf
.
Strings
(
k
)
if
jsonconf
.
String
(
"runmode"
)
!=
"dev"
{
case
string
:
t
.
Fatal
(
"runmode not equal to dev"
)
value
=
jsonconf
.
String
(
k
)
}
default
:
if
v
:=
jsonconf
.
Strings
(
"unknown"
);
len
(
v
)
>
0
{
value
,
err
=
jsonconf
.
DIY
(
k
)
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
{
if
err
!=
nil
{
t
.
Error
(
v
)
t
.
Fatalf
(
"get key %q value fatal,%v err %s"
,
k
,
v
,
err
)
t
.
Fatal
(
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
v
,
err
:=
jsonconf
.
Bool
(
"copyrequestbody"
);
err
!=
nil
||
v
!=
true
{
t
.
Error
(
v
)
t
.
Fatal
(
err
)
}
}
if
err
=
jsonconf
.
Set
(
"name"
,
"astaxie"
);
err
!=
nil
{
if
err
=
jsonconf
.
Set
(
"name"
,
"astaxie"
);
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -143,15 +174,7 @@ func TestJson(t *testing.T) {
...
@@ -143,15 +174,7 @@ func TestJson(t *testing.T) {
if
jsonconf
.
String
(
"name"
)
!=
"astaxie"
{
if
jsonconf
.
String
(
"name"
)
!=
"astaxie"
{
t
.
Fatal
(
"get name error"
)
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
{
if
db
,
err
:=
jsonconf
.
DIY
(
"database"
);
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
else
if
m
,
ok
:=
db
.
(
map
[
string
]
interface
{});
!
ok
{
}
else
if
m
,
ok
:=
db
.
(
map
[
string
]
interface
{});
!
ok
{
...
...
config/xml/xml.go
View file @
c59a029c
...
@@ -92,7 +92,10 @@ type ConfigContainer struct {
...
@@ -92,7 +92,10 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key.
// Bool returns the boolean value for a given key.
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
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
// DefaultBool return the bool value if has no error
...
...
config/yaml/yaml.go
View file @
c59a029c
...
@@ -121,10 +121,10 @@ type ConfigContainer struct {
...
@@ -121,10 +121,10 @@ type ConfigContainer struct {
// Bool returns the boolean value for a given key.
// Bool returns the boolean value for a given key.
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
bool
)
;
ok
{
if
v
,
ok
:=
c
.
data
[
key
];
ok
{
return
v
,
nil
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
// DefaultBool return the bool value if has no error
...
...
hooks.go
View file @
c59a029c
...
@@ -68,14 +68,12 @@ func registerSession() error {
...
@@ -68,14 +68,12 @@ func registerSession() error {
}
}
func
registerTemplate
()
error
{
func
registerTemplate
()
error
{
if
BConfig
.
WebConfig
.
AutoRender
{
if
err
:=
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
if
err
:=
BuildTemplate
(
BConfig
.
WebConfig
.
ViewsPath
);
err
!=
nil
{
if
BConfig
.
RunMode
==
DEV
{
if
BConfig
.
RunMode
==
DEV
{
Warn
(
err
)
Warn
(
err
)
}
}
return
err
return
err
}
}
}
return
nil
return
nil
}
}
...
...
logs/conn.go
View file @
c59a029c
...
@@ -19,6 +19,7 @@ import (
...
@@ -19,6 +19,7 @@ import (
"io"
"io"
"log"
"log"
"net"
"net"
"time"
)
)
// connWriter implements LoggerInterface.
// connWriter implements LoggerInterface.
...
@@ -48,7 +49,7 @@ func (c *connWriter) Init(jsonconfig string) error {
...
@@ -48,7 +49,7 @@ func (c *connWriter) Init(jsonconfig string) error {
// WriteMsg write message in connection.
// WriteMsg write message in connection.
// if connection is down, try to re-connect.
// 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
{
if
level
>
c
.
Level
{
return
nil
return
nil
}
}
...
@@ -62,6 +63,9 @@ func (c *connWriter) WriteMsg(msg string, level int) error {
...
@@ -62,6 +63,9 @@ func (c *connWriter) WriteMsg(msg string, level int) error {
if
c
.
ReconnectOnMsg
{
if
c
.
ReconnectOnMsg
{
defer
c
.
innerWriter
.
Close
()
defer
c
.
innerWriter
.
Close
()
}
}
msg
=
formatLogTime
(
when
)
+
msg
c
.
lg
.
Println
(
msg
)
c
.
lg
.
Println
(
msg
)
return
nil
return
nil
}
}
...
@@ -94,7 +98,7 @@ func (c *connWriter) connect() error {
...
@@ -94,7 +98,7 @@ func (c *connWriter) connect() error {
}
}
c
.
innerWriter
=
conn
c
.
innerWriter
=
conn
c
.
lg
=
log
.
New
(
conn
,
""
,
log
.
Ldate
|
log
.
Ltime
)
c
.
lg
=
log
.
New
(
conn
,
""
,
0
)
return
nil
return
nil
}
}
...
...
logs/console.go
View file @
c59a029c
...
@@ -19,6 +19,7 @@ import (
...
@@ -19,6 +19,7 @@ import (
"log"
"log"
"os"
"os"
"runtime"
"runtime"
"time"
)
)
// brush is a color join function
// brush is a color join function
...
@@ -53,27 +54,28 @@ type consoleWriter struct {
...
@@ -53,27 +54,28 @@ type consoleWriter struct {
// NewConsole create ConsoleWriter returning as LoggerInterface.
// NewConsole create ConsoleWriter returning as LoggerInterface.
func
NewConsole
()
Logger
{
func
NewConsole
()
Logger
{
cw
:=
&
consoleWriter
{
cw
:=
&
consoleWriter
{
lg
:
log
.
New
(
os
.
Stdout
,
""
,
log
.
Ldate
|
log
.
Ltime
),
lg
:
log
.
New
(
os
.
Stdout
,
""
,
0
),
Level
:
LevelDebug
,
Level
:
LevelDebug
,
}
}
return
cw
return
cw
}
}
// Init init console logger.
// Init init console logger.
// json
c
onfig like '{"level":LevelTrace}'.
// json
C
onfig like '{"level":LevelTrace}'.
func
(
c
*
consoleWriter
)
Init
(
json
c
onfig
string
)
error
{
func
(
c
*
consoleWriter
)
Init
(
json
C
onfig
string
)
error
{
if
len
(
json
c
onfig
)
==
0
{
if
len
(
json
C
onfig
)
==
0
{
return
nil
return
nil
}
}
return
json
.
Unmarshal
([]
byte
(
json
c
onfig
),
c
)
return
json
.
Unmarshal
([]
byte
(
json
C
onfig
),
c
)
}
}
// WriteMsg write message in console.
// 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
{
if
level
>
c
.
Level
{
return
nil
return
nil
}
}
if
goos
:=
runtime
.
GOOS
;
goos
==
"windows"
{
msg
=
formatLogTime
(
when
)
+
msg
if
runtime
.
GOOS
==
"windows"
{
c
.
lg
.
Println
(
msg
)
c
.
lg
.
Println
(
msg
)
return
nil
return
nil
}
}
...
...
logs/es/es.go
View file @
c59a029c
...
@@ -48,16 +48,16 @@ func (el *esLogger) Init(jsonconfig string) error {
...
@@ -48,16 +48,16 @@ func (el *esLogger) Init(jsonconfig string) error {
}
}
// WriteMsg will write the msg and level into es
// 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
{
if
level
>
el
.
Level
{
return
nil
return
nil
}
}
t
:=
time
.
Now
()
vals
:=
make
(
map
[
string
]
interface
{})
vals
:=
make
(
map
[
string
]
interface
{})
vals
[
"@timestamp"
]
=
t
.
Format
(
time
.
RFC3339
)
vals
[
"@timestamp"
]
=
when
.
Format
(
time
.
RFC3339
)
vals
[
"@msg"
]
=
msg
vals
[
"@msg"
]
=
msg
d
:=
goes
.
Document
{
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"
,
Type
:
"logs"
,
Fields
:
vals
,
Fields
:
vals
,
}
}
...
...
logs/file.go
View file @
c59a029c
...
@@ -114,59 +114,20 @@ func (w *fileLogWriter) needRotate(size int, day int) bool {
...
@@ -114,59 +114,20 @@ func (w *fileLogWriter) needRotate(size int, day int) bool {
}
}
// WriteMsg write logger message into file.
// 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
{
if
level
>
w
.
Level
{
return
nil
return
nil
}
}
//2016/01/12 21:34:33
msg
=
formatLogTime
(
when
)
+
msg
+
"
\n
"
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
"
if
w
.
Rotate
{
if
w
.
Rotate
{
d
:=
when
.
Day
()
if
w
.
needRotate
(
len
(
msg
),
d
)
{
if
w
.
needRotate
(
len
(
msg
),
d
)
{
w
.
Lock
()
w
.
Lock
()
if
w
.
needRotate
(
len
(
msg
),
d
)
{
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
)
fmt
.
Fprintf
(
os
.
Stderr
,
"FileLogWriter(%q): %s
\n
"
,
w
.
Filename
,
err
)
}
}
}
}
w
.
Unlock
()
w
.
Unlock
()
}
}
...
@@ -236,7 +197,7 @@ func (w *fileLogWriter) lines() (int, error) {
...
@@ -236,7 +197,7 @@ func (w *fileLogWriter) lines() (int, error) {
// DoRotate means it need to write file in new file.
// DoRotate means it need to write file in new file.
// new file name like xx.2013-01-01.2.log
// 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
)
_
,
err
:=
os
.
Lstat
(
w
.
Filename
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -251,7 +212,7 @@ func (w *fileLogWriter) doRotate() error {
...
@@ -251,7 +212,7 @@ func (w *fileLogWriter) doRotate() error {
suffix
=
".log"
suffix
=
".log"
}
}
for
;
err
==
nil
&&
num
<=
999
;
num
++
{
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
)
_
,
err
=
os
.
Lstat
(
fName
)
}
}
// return error if the last file checked still existed
// return error if the last file checked still existed
...
...
logs/log.go
View file @
c59a029c
...
@@ -40,6 +40,7 @@ import (
...
@@ -40,6 +40,7 @@ import (
"runtime"
"runtime"
"strconv"
"strconv"
"sync"
"sync"
"time"
)
)
// RFC5424 log message levels.
// RFC5424 log message levels.
...
@@ -68,7 +69,7 @@ type loggerType func() Logger
...
@@ -68,7 +69,7 @@ type loggerType func() Logger
// Logger defines the behavior of a log provider.
// Logger defines the behavior of a log provider.
type
Logger
interface
{
type
Logger
interface
{
Init
(
config
string
)
error
Init
(
config
string
)
error
WriteMsg
(
msg
string
,
level
int
)
error
WriteMsg
(
when
time
.
Time
,
msg
string
,
level
int
)
error
Destroy
()
Destroy
()
Flush
()
Flush
()
}
}
...
@@ -108,6 +109,7 @@ type nameLogger struct {
...
@@ -108,6 +109,7 @@ type nameLogger struct {
type
logMsg
struct
{
type
logMsg
struct
{
level
int
level
int
msg
string
msg
string
when
time
.
Time
}
}
var
logMsgPool
*
sync
.
Pool
var
logMsgPool
*
sync
.
Pool
...
@@ -173,9 +175,9 @@ func (bl *BeeLogger) DelLogger(adapterName string) error {
...
@@ -173,9 +175,9 @@ func (bl *BeeLogger) DelLogger(adapterName string) error {
return
nil
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
{
for
_
,
l
:=
range
bl
.
outputs
{
err
:=
l
.
WriteMsg
(
msg
,
level
)
err
:=
l
.
WriteMsg
(
when
,
msg
,
level
)
if
err
!=
nil
{
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"unable to WriteMsg to adapter:%v,error:%v
\n
"
,
l
.
name
,
err
)
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) {
...
@@ -183,6 +185,7 @@ func (bl *BeeLogger) writeToLoggers(msg string, level int) {
}
}
func
(
bl
*
BeeLogger
)
writeMsg
(
logLevel
int
,
msg
string
)
error
{
func
(
bl
*
BeeLogger
)
writeMsg
(
logLevel
int
,
msg
string
)
error
{
when
:=
time
.
Now
()
if
bl
.
enableFuncCallDepth
{
if
bl
.
enableFuncCallDepth
{
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
bl
.
loggerFuncCallDepth
)
_
,
file
,
line
,
ok
:=
runtime
.
Caller
(
bl
.
loggerFuncCallDepth
)
if
!
ok
{
if
!
ok
{
...
@@ -196,9 +199,10 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error {
...
@@ -196,9 +199,10 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error {
lm
:=
logMsgPool
.
Get
()
.
(
*
logMsg
)
lm
:=
logMsgPool
.
Get
()
.
(
*
logMsg
)
lm
.
level
=
logLevel
lm
.
level
=
logLevel
lm
.
msg
=
msg
lm
.
msg
=
msg
lm
.
when
=
when
bl
.
msgChan
<-
lm
bl
.
msgChan
<-
lm
}
else
{
}
else
{
bl
.
writeToLoggers
(
msg
,
logLevel
)
bl
.
writeToLoggers
(
when
,
msg
,
logLevel
)
}
}
return
nil
return
nil
}
}
...
@@ -231,7 +235,7 @@ func (bl *BeeLogger) startLogger() {
...
@@ -231,7 +235,7 @@ func (bl *BeeLogger) startLogger() {
for
{
for
{
select
{
select
{
case
bm
:=
<-
bl
.
msgChan
:
case
bm
:=
<-
bl
.
msgChan
:
bl
.
writeToLoggers
(
bm
.
msg
,
bm
.
level
)
bl
.
writeToLoggers
(
bm
.
when
,
bm
.
msg
,
bm
.
level
)
logMsgPool
.
Put
(
bm
)
logMsgPool
.
Put
(
bm
)
}
}
}
}
...
@@ -351,7 +355,7 @@ func (bl *BeeLogger) Close() {
...
@@ -351,7 +355,7 @@ func (bl *BeeLogger) Close() {
for
{
for
{
if
len
(
bl
.
msgChan
)
>
0
{
if
len
(
bl
.
msgChan
)
>
0
{
bm
:=
<-
bl
.
msgChan
bm
:=
<-
bl
.
msgChan
bl
.
writeToLoggers
(
bm
.
msg
,
bm
.
level
)
bl
.
writeToLoggers
(
bm
.
when
,
bm
.
msg
,
bm
.
level
)
logMsgPool
.
Put
(
bm
)
logMsgPool
.
Put
(
bm
)
continue
continue
}
}
...
@@ -363,3 +367,45 @@ func (bl *BeeLogger) Close() {
...
@@ -363,3 +367,45 @@ func (bl *BeeLogger) Close() {
}
}
bl
.
outputs
=
nil
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
View file @
c59a029c
...
@@ -126,7 +126,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
...
@@ -126,7 +126,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd
// WriteMsg write message in smtp writer.
// WriteMsg write message in smtp writer.
// it will send an email with subject and only this message.
// 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
{
if
level
>
s
.
Level
{
return
nil
return
nil
}
}
...
@@ -140,7 +140,7 @@ func (s *SMTPWriter) WriteMsg(msg string, level int) error {
...
@@ -140,7 +140,7 @@ func (s *SMTPWriter) WriteMsg(msg string, level int) error {
// and send the email all in one step.
// and send the email all in one step.
contentType
:=
"Content-Type: text/plain"
+
"; charset=UTF-8"
contentType
:=
"Content-Type: text/plain"
+
"; charset=UTF-8"
mailmsg
:=
[]
byte
(
"To: "
+
strings
.
Join
(
s
.
RecipientAddresses
,
";"
)
+
"
\r\n
From: "
+
s
.
FromAddress
+
"<"
+
s
.
FromAddress
+
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
)
return
s
.
sendMail
(
s
.
Host
,
auth
,
s
.
FromAddress
,
s
.
RecipientAddresses
,
mailmsg
)
}
}
...
...
orm/types.go
View file @
c59a029c
...
@@ -162,6 +162,12 @@ type QuerySeter interface {
...
@@ -162,6 +162,12 @@ type QuerySeter interface {
// qs.RelatedSel("profile").One(&user)
// qs.RelatedSel("profile").One(&user)
// user.Profile.Age = 32
// user.Profile.Age = 32
RelatedSel
(
params
...
interface
{})
QuerySeter
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
// return QuerySeter execution result number
// for example:
// for example:
// num, err = qs.Filter("profile__age__gt", 28).Count()
// num, err = qs.Filter("profile__age__gt", 28).Count()
...
...
parser.go
View file @
c59a029c
...
@@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
...
@@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat
}
}
func
genRouterCode
()
{
func
genRouterCode
()
{
os
.
Mkdir
(
"routers"
,
0755
)
os
.
Mkdir
(
path
.
Join
(
AppPath
,
"routers"
)
,
0755
)
Info
(
"generate router from comments"
)
Info
(
"generate router from comments"
)
var
(
var
(
globalinfo
string
globalinfo
string
...
@@ -172,7 +172,7 @@ func genRouterCode() {
...
@@ -172,7 +172,7 @@ func genRouterCode() {
}
}
}
}
if
globalinfo
!=
""
{
if
globalinfo
!=
""
{
f
,
err
:=
os
.
Create
(
path
.
Join
(
"routers"
,
commentFilename
))
f
,
err
:=
os
.
Create
(
path
.
Join
(
AppPath
,
"routers"
,
commentFilename
))
if
err
!=
nil
{
if
err
!=
nil
{
panic
(
err
)
panic
(
err
)
}
}
...
@@ -182,7 +182,7 @@ func genRouterCode() {
...
@@ -182,7 +182,7 @@ func genRouterCode() {
}
}
func
compareFile
(
pkgRealpath
string
)
bool
{
func
compareFile
(
pkgRealpath
string
)
bool
{
if
!
utils
.
FileExists
(
path
.
Join
(
"routers"
,
commentFilename
))
{
if
!
utils
.
FileExists
(
path
.
Join
(
AppPath
,
"routers"
,
commentFilename
))
{
return
true
return
true
}
}
if
utils
.
FileExists
(
lastupdateFilename
)
{
if
utils
.
FileExists
(
lastupdateFilename
)
{
...
...
plugins/cors/cors.go
View file @
c59a029c
...
@@ -36,6 +36,7 @@
...
@@ -36,6 +36,7 @@
package
cors
package
cors
import
(
import
(
"net/http"
"regexp"
"regexp"
"strconv"
"strconv"
"strings"
"strings"
...
@@ -215,6 +216,7 @@ func Allow(opts *Options) beego.FilterFunc {
...
@@ -215,6 +216,7 @@ func Allow(opts *Options) beego.FilterFunc {
for
key
,
value
:=
range
headers
{
for
key
,
value
:=
range
headers
{
ctx
.
Output
.
Header
(
key
,
value
)
ctx
.
Output
.
Header
(
key
,
value
)
}
}
ctx
.
ResponseWriter
.
WriteHeader
(
http
.
StatusOK
)
return
return
}
}
headers
=
opts
.
Header
(
origin
)
headers
=
opts
.
Header
(
origin
)
...
...
tree.go
View file @
c59a029c
...
@@ -141,7 +141,7 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st
...
@@ -141,7 +141,7 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st
regexpStr
=
"([^.]+).(.+)"
regexpStr
=
"([^.]+).(.+)"
params
=
params
[
1
:
]
params
=
params
[
1
:
]
}
else
{
}
else
{
for
range
params
{
for
_
=
range
params
{
regexpStr
=
"([^/]+)/"
+
regexpStr
regexpStr
=
"([^/]+)/"
+
regexpStr
}
}
}
}
...
@@ -254,7 +254,7 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
...
@@ -254,7 +254,7 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
regexpStr
=
"/([^.]+).(.+)"
regexpStr
=
"/([^.]+).(.+)"
params
=
params
[
1
:
]
params
=
params
[
1
:
]
}
else
{
}
else
{
for
range
params
{
for
_
=
range
params
{
regexpStr
=
"/([^/]+)"
+
regexpStr
regexpStr
=
"/([^/]+)"
+
regexpStr
}
}
}
}
...
@@ -420,7 +420,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
...
@@ -420,7 +420,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
if
len
(
strs
)
==
2
{
if
len
(
strs
)
==
2
{
ctx
.
Input
.
SetParam
(
":ext"
,
strs
[
1
])
ctx
.
Input
.
SetParam
(
":ext"
,
strs
[
1
])
}
}
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
]))
ctx
.
Input
.
SetParam
(
":path"
,
path
.
Join
(
path
.
Join
(
wildcardValues
[
index
:
len
(
wildcardValues
)
-
1
]
...
),
strs
[
0
]))
}
return
true
return
true
}
}
// match :id
// match :id
...
@@ -438,8 +442,10 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
...
@@ -438,8 +442,10 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b
}
}
matches
:=
leaf
.
regexps
.
FindStringSubmatch
(
path
.
Join
(
wildcardValues
...
))
matches
:=
leaf
.
regexps
.
FindStringSubmatch
(
path
.
Join
(
wildcardValues
...
))
for
i
,
match
:=
range
matches
[
1
:
]
{
for
i
,
match
:=
range
matches
[
1
:
]
{
if
i
<
len
(
leaf
.
wildcards
)
{
ctx
.
Input
.
SetParam
(
leaf
.
wildcards
[
i
],
match
)
ctx
.
Input
.
SetParam
(
leaf
.
wildcards
[
i
],
match
)
}
}
}
return
true
return
true
}
}
...
@@ -536,13 +542,19 @@ func splitSegment(key string) (bool, []string, string) {
...
@@ -536,13 +542,19 @@ func splitSegment(key string) (bool, []string, string) {
continue
continue
}
}
}
}
if
v
==
':'
{
// Escape Sequence '\'
if
i
>
0
&&
key
[
i
-
1
]
==
'\\'
{
out
=
append
(
out
,
v
)
}
else
if
v
==
':'
{
param
=
make
([]
rune
,
0
)
param
=
make
([]
rune
,
0
)
start
=
true
start
=
true
}
else
if
v
==
'('
{
}
else
if
v
==
'('
{
startexp
=
true
startexp
=
true
start
=
false
start
=
false
if
len
(
param
)
>
0
{
params
=
append
(
params
,
":"
+
string
(
param
))
params
=
append
(
params
,
":"
+
string
(
param
))
param
=
make
([]
rune
,
0
)
}
paramsNum
++
paramsNum
++
expt
=
make
([]
rune
,
0
)
expt
=
make
([]
rune
,
0
)
expt
=
append
(
expt
,
'('
)
expt
=
append
(
expt
,
'('
)
...
...
tree_test.go
View file @
c59a029c
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
package
beego
package
beego
import
(
import
(
"strings"
"testing"
"testing"
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/context"
...
@@ -57,6 +58,9 @@ func init() {
...
@@ -57,6 +58,9 @@ func init() {
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg"
,
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg"
,
map
[
string
]
string
{
":width"
:
"48"
,
":height"
:
"48"
,
":ext"
:
"jpg"
,
":path"
:
"05ac66d9bda00a3acf948c43e306fc9a"
}})
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: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
{
"/: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/: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"
}})
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) {
...
@@ -245,48 +249,31 @@ func TestSplitPath(t *testing.T) {
}
}
func
TestSplitSegment
(
t
*
testing
.
T
)
{
func
TestSplitSegment
(
t
*
testing
.
T
)
{
b
,
w
,
r
:=
splitSegment
(
"admin"
)
if
b
||
len
(
w
)
!=
0
||
r
!=
""
{
items
:=
map
[
string
]
struct
{
t
.
Fatal
(
"admin should return false, nil, ''"
)
isReg
bool
}
params
[]
string
b
,
w
,
r
=
splitSegment
(
"*"
)
regStr
string
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":splat"
||
r
!=
""
{
}{
t
.
Fatal
(
"* should return true, [:splat], ''"
)
"admin"
:
{
false
,
nil
,
""
},
}
"*"
:
{
true
,
[]
string
{
":splat"
},
""
},
b
,
w
,
r
=
splitSegment
(
"*.*"
)
"*.*"
:
{
true
,
[]
string
{
"."
,
":path"
,
":ext"
},
""
},
if
!
b
||
len
(
w
)
!=
3
||
w
[
1
]
!=
":path"
||
w
[
2
]
!=
":ext"
||
w
[
0
]
!=
"."
||
r
!=
""
{
":id"
:
{
true
,
[]
string
{
":id"
},
""
},
t
.
Fatal
(
"admin should return true,[. :path :ext], ''"
)
"?:id"
:
{
true
,
[]
string
{
":"
,
":id"
},
""
},
}
":id:int"
:
{
true
,
[]
string
{
":id"
},
"([0-9]+)"
},
b
,
w
,
r
=
splitSegment
(
":id"
)
":name:string"
:
{
true
,
[]
string
{
":name"
},
`([\w]+)`
},
if
!
b
||
len
(
w
)
!=
1
||
w
[
0
]
!=
":id"
||
r
!=
""
{
":id([0-9]+)"
:
{
true
,
[]
string
{
":id"
},
`([0-9]+)`
},
t
.
Fatal
(
":id should return true, [:id], ''"
)
":id([0-9]+)_:name"
:
{
true
,
[]
string
{
":id"
,
":name"
},
`([0-9]+)_(.+)`
},
}
":id(.+)_cms.html"
:
{
true
,
[]
string
{
":id"
},
`(.+)_cms.html`
},
b
,
w
,
r
=
splitSegment
(
"?:id"
)
"cms_:id(.+)_:page(.+).html"
:
{
true
,
[]
string
{
":id"
,
":page"
},
`cms_(.+)_(.+).html`
},
if
!
b
||
len
(
w
)
!=
2
||
w
[
0
]
!=
":"
||
w
[
1
]
!=
":id"
||
r
!=
""
{
`:app(a|b|c)`
:
{
true
,
[]
string
{
":app"
},
`(a|b|c)`
},
t
.
Fatal
(
"?:id should return true, [: :id], ''"
)
`:app\((a|b|c)\)`
:
{
true
,
[]
string
{
":app"
},
`(.+)\((a|b|c)\)`
},
}
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`
{
for
pattern
,
v
:=
range
items
{
t
.
Fatal
(
":id_cms.html should return true, [:id], '(.+)_cms.html'"
)
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
)
}
}
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"
)
}
}
}
}
utils/mail.go
View file @
c59a029c
...
@@ -31,10 +31,13 @@ import (
...
@@ -31,10 +31,13 @@ import (
"path/filepath"
"path/filepath"
"strconv"
"strconv"
"strings"
"strings"
"sync"
)
)
const
(
const
(
maxLineLength
=
76
maxLineLength
=
76
upperhex
=
"0123456789ABCDEF"
)
)
// Email is the type used for email messages
// Email is the type used for email messages
...
@@ -74,9 +77,6 @@ func NewEMail(config string) *Email {
...
@@ -74,9 +77,6 @@ func NewEMail(config string) *Email {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
return
nil
}
}
if
e
.
From
==
""
{
e
.
From
=
e
.
Username
}
return
e
return
e
}
}
...
@@ -228,14 +228,21 @@ func (e *Email) Send() error {
...
@@ -228,14 +228,21 @@ func (e *Email) Send() error {
to
:=
make
([]
string
,
0
,
len
(
e
.
To
)
+
len
(
e
.
Cc
)
+
len
(
e
.
Bcc
))
to
:=
make
([]
string
,
0
,
len
(
e
.
To
)
+
len
(
e
.
Cc
)
+
len
(
e
.
Bcc
))
to
=
append
(
append
(
append
(
to
,
e
.
To
...
),
e
.
Cc
...
),
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
// Check to make sure there is at least one recipient and one "From" address
if
e
.
From
==
""
||
len
(
to
)
==
0
{
if
len
(
to
)
==
0
{
return
errors
.
New
(
"Must specify at least one
From address and one
To address"
)
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
{
if
err
!=
nil
{
return
err
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
()
raw
,
err
:=
e
.
Bytes
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
@@ -342,3 +349,73 @@ func base64Wrap(w io.Writer, b []byte) {
...
@@ -342,3 +349,73 @@ func base64Wrap(w io.Writer, b []byte) {
w
.
Write
(
out
)
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
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment