mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 03:11:30 +00:00
Merge branch 'develop'
This commit is contained in:
commit
020bfbcc9c
6
admin.go
6
admin.go
@ -397,7 +397,7 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
|
data["Message"] = []string{"error", fmt.Sprintf("%s", err)}
|
||||||
}
|
}
|
||||||
data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is %s", taskname, t.GetStatus())}
|
data["Message"] = []string{"success", fmt.Sprintf("%s run success,Now the Status is <br>%s", taskname, t.GetStatus())}
|
||||||
} else {
|
} else {
|
||||||
data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)}
|
data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)}
|
||||||
}
|
}
|
||||||
@ -410,12 +410,14 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
|||||||
var fields = []string{
|
var fields = []string{
|
||||||
fmt.Sprintf("Task Name"),
|
fmt.Sprintf("Task Name"),
|
||||||
fmt.Sprintf("Task Spec"),
|
fmt.Sprintf("Task Spec"),
|
||||||
fmt.Sprintf("Task Function"),
|
fmt.Sprintf("Task Status"),
|
||||||
|
fmt.Sprintf("Last Time"),
|
||||||
fmt.Sprintf(""),
|
fmt.Sprintf(""),
|
||||||
}
|
}
|
||||||
for tname, tk := range toolbox.AdminTaskList {
|
for tname, tk := range toolbox.AdminTaskList {
|
||||||
result = []string{
|
result = []string{
|
||||||
fmt.Sprintf("%s", tname),
|
fmt.Sprintf("%s", tname),
|
||||||
|
fmt.Sprintf("%s", tk.GetSpec()),
|
||||||
fmt.Sprintf("%s", tk.GetStatus()),
|
fmt.Sprintf("%s", tk.GetStatus()),
|
||||||
fmt.Sprintf("%s", tk.GetPrev().String()),
|
fmt.Sprintf("%s", tk.GetPrev().String()),
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ bg-warning
|
|||||||
</td>
|
</td>
|
||||||
{{end}}
|
{{end}}
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-primary btn-sm" href="/task?taskname={{index $slice 1}}">Run</a>
|
<a class="btn btn-primary btn-sm" href="/task?taskname={{index $slice 0}}">Run</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
7
app.go
7
app.go
@ -19,7 +19,10 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/fcgi"
|
"net/http/fcgi"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// App defines beego application with a new PatternServeMux.
|
// App defines beego application with a new PatternServeMux.
|
||||||
@ -59,6 +62,10 @@ func (app *App) Run() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if HttpPort == 0 {
|
if HttpPort == 0 {
|
||||||
|
// remove the Socket file before start
|
||||||
|
if utils.FileExists(addr) {
|
||||||
|
os.Remove(addr)
|
||||||
|
}
|
||||||
l, err = net.Listen("unix", addr)
|
l, err = net.Listen("unix", addr)
|
||||||
} else {
|
} else {
|
||||||
l, err = net.Listen("tcp", addr)
|
l, err = net.Listen("tcp", addr)
|
||||||
|
83
beego.go
83
beego.go
@ -33,83 +33,15 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/astaxie/beego/middleware"
|
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// beego web framework version.
|
// beego web framework version.
|
||||||
const VERSION = "1.4.2"
|
const VERSION = "1.4.3"
|
||||||
|
|
||||||
type hookfunc func() error //hook function to run
|
type hookfunc func() error //hook function to run
|
||||||
var hooks []hookfunc //hook function slice to store the hookfunc
|
var hooks []hookfunc //hook function slice to store the hookfunc
|
||||||
|
|
||||||
type groupRouter struct {
|
|
||||||
pattern string
|
|
||||||
controller ControllerInterface
|
|
||||||
mappingMethods string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RouterGroups which will store routers
|
|
||||||
type GroupRouters []groupRouter
|
|
||||||
|
|
||||||
// Get a new GroupRouters
|
|
||||||
func NewGroupRouters() GroupRouters {
|
|
||||||
return make(GroupRouters, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Router in the GroupRouters
|
|
||||||
// it is for plugin or module to register router
|
|
||||||
func (gr *GroupRouters) AddRouter(pattern string, c ControllerInterface, mappingMethod ...string) {
|
|
||||||
var newRG groupRouter
|
|
||||||
if len(mappingMethod) > 0 {
|
|
||||||
newRG = groupRouter{
|
|
||||||
pattern,
|
|
||||||
c,
|
|
||||||
mappingMethod[0],
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newRG = groupRouter{
|
|
||||||
pattern,
|
|
||||||
c,
|
|
||||||
"",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*gr = append(*gr, newRG)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gr *GroupRouters) AddAuto(c ControllerInterface) {
|
|
||||||
newRG := groupRouter{
|
|
||||||
"",
|
|
||||||
c,
|
|
||||||
"",
|
|
||||||
}
|
|
||||||
*gr = append(*gr, newRG)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddGroupRouter with the prefix
|
|
||||||
// it will register the router in BeeApp
|
|
||||||
// the follow code is write in modules:
|
|
||||||
// GR:=NewGroupRouters()
|
|
||||||
// GR.AddRouter("/login",&UserController,"get:Login")
|
|
||||||
// GR.AddRouter("/logout",&UserController,"get:Logout")
|
|
||||||
// GR.AddRouter("/register",&UserController,"get:Reg")
|
|
||||||
// the follow code is write in app:
|
|
||||||
// import "github.com/beego/modules/auth"
|
|
||||||
// AddRouterGroup("/admin", auth.GR)
|
|
||||||
func AddGroupRouter(prefix string, groups GroupRouters) *App {
|
|
||||||
for _, v := range groups {
|
|
||||||
if v.pattern == "" {
|
|
||||||
BeeApp.Handlers.AddAutoPrefix(prefix, v.controller)
|
|
||||||
} else if v.mappingMethods != "" {
|
|
||||||
BeeApp.Handlers.Add(prefix+v.pattern, v.controller, v.mappingMethods)
|
|
||||||
} else {
|
|
||||||
BeeApp.Handlers.Add(prefix+v.pattern, v.controller)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Router adds a patterned controller handler to BeeApp.
|
// Router adds a patterned controller handler to BeeApp.
|
||||||
// it's an alias method of App.Router.
|
// it's an alias method of App.Router.
|
||||||
// usage:
|
// usage:
|
||||||
@ -280,15 +212,6 @@ func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
|
|||||||
return BeeApp
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorHandler registers http.HandlerFunc to each http err code string.
|
|
||||||
// usage:
|
|
||||||
// beego.ErrorHandler("404",NotFound)
|
|
||||||
// beego.ErrorHandler("500",InternalServerError)
|
|
||||||
func Errorhandler(err string, h http.HandlerFunc) *App {
|
|
||||||
middleware.Errorhandler(err, h)
|
|
||||||
return BeeApp
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetViewsPath sets view directory path in beego application.
|
// SetViewsPath sets view directory path in beego application.
|
||||||
func SetViewsPath(path string) *App {
|
func SetViewsPath(path string) *App {
|
||||||
ViewsPath = path
|
ViewsPath = path
|
||||||
@ -402,9 +325,7 @@ func initBeforeHttpRun() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
middleware.VERSION = VERSION
|
registerDefaultErrorHandler()
|
||||||
middleware.AppName = AppName
|
|
||||||
middleware.RegisterErrorHandler()
|
|
||||||
|
|
||||||
if EnableDocs {
|
if EnableDocs {
|
||||||
Get("/docs", serverDocs)
|
Get("/docs", serverDocs)
|
||||||
|
4
cache/cache_test.go
vendored
4
cache/cache_test.go
vendored
@ -15,6 +15,7 @@
|
|||||||
package cache
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -67,7 +68,7 @@ func TestCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFileCache(t *testing.T) {
|
func TestFileCache(t *testing.T) {
|
||||||
bm, err := NewCache("file", `{"CachePath":"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}`)
|
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("init err")
|
t.Error("init err")
|
||||||
}
|
}
|
||||||
@ -112,4 +113,5 @@ func TestFileCache(t *testing.T) {
|
|||||||
if v := bm.Get("astaxie"); v.(string) != "author" {
|
if v := bm.Get("astaxie"); v.(string) != "author" {
|
||||||
t.Error("get err")
|
t.Error("get err")
|
||||||
}
|
}
|
||||||
|
os.RemoveAll("cache")
|
||||||
}
|
}
|
||||||
|
2
cache/file.go
vendored
2
cache/file.go
vendored
@ -92,8 +92,6 @@ func (fc *FileCache) StartAndGC(config string) error {
|
|||||||
|
|
||||||
// Init will make new dir for file cache if not exist.
|
// Init will make new dir for file cache if not exist.
|
||||||
func (fc *FileCache) Init() {
|
func (fc *FileCache) Init() {
|
||||||
app := filepath.Dir(os.Args[0])
|
|
||||||
fc.CachePath = filepath.Join(app, fc.CachePath)
|
|
||||||
if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
|
if ok, _ := exists(fc.CachePath); !ok { // todo : error handle
|
||||||
_ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
|
_ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle
|
||||||
}
|
}
|
||||||
|
14
cache/redis/redis.go
vendored
14
cache/redis/redis.go
vendored
@ -32,6 +32,7 @@ package redis
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/garyburd/redigo/redis"
|
"github.com/garyburd/redigo/redis"
|
||||||
@ -48,6 +49,7 @@ var (
|
|||||||
type RedisCache struct {
|
type RedisCache struct {
|
||||||
p *redis.Pool // redis connection pool
|
p *redis.Pool // redis connection pool
|
||||||
conninfo string
|
conninfo string
|
||||||
|
dbNum int
|
||||||
key string
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +139,7 @@ func (rc *RedisCache) ClearAll() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start redis cache adapter.
|
// start redis cache adapter.
|
||||||
// config is like {"key":"collection key","conn":"connection info"}
|
// config is like {"key":"collection key","conn":"connection info","dbNum":"0"}
|
||||||
// the cache item in redis are stored forever,
|
// the cache item in redis are stored forever,
|
||||||
// so no gc operation.
|
// so no gc operation.
|
||||||
func (rc *RedisCache) StartAndGC(config string) error {
|
func (rc *RedisCache) StartAndGC(config string) error {
|
||||||
@ -151,9 +153,12 @@ func (rc *RedisCache) StartAndGC(config string) error {
|
|||||||
if _, ok := cf["conn"]; !ok {
|
if _, ok := cf["conn"]; !ok {
|
||||||
return errors.New("config has no conn key")
|
return errors.New("config has no conn key")
|
||||||
}
|
}
|
||||||
|
if _, ok := cf["dbNum"]; !ok {
|
||||||
|
cf["dbNum"] = "0"
|
||||||
|
}
|
||||||
rc.key = cf["key"]
|
rc.key = cf["key"]
|
||||||
rc.conninfo = cf["conn"]
|
rc.conninfo = cf["conn"]
|
||||||
|
rc.dbNum, _ = strconv.Atoi(cf["dbNum"])
|
||||||
rc.connectInit()
|
rc.connectInit()
|
||||||
|
|
||||||
c := rc.p.Get()
|
c := rc.p.Get()
|
||||||
@ -166,6 +171,11 @@ func (rc *RedisCache) StartAndGC(config string) error {
|
|||||||
func (rc *RedisCache) connectInit() {
|
func (rc *RedisCache) connectInit() {
|
||||||
dialFunc := func() (c redis.Conn, err error) {
|
dialFunc := func() (c redis.Conn, err error) {
|
||||||
c, err = redis.Dial("tcp", rc.conninfo)
|
c, err = redis.Dial("tcp", rc.conninfo)
|
||||||
|
_, selecterr := c.Do("SELECT", rc.dbNum)
|
||||||
|
if selecterr != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, selecterr
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// initialize a new pool
|
// initialize a new pool
|
||||||
|
@ -81,6 +81,7 @@ var (
|
|||||||
AppConfigProvider string // config provider
|
AppConfigProvider string // config provider
|
||||||
EnableDocs bool // enable generate docs & server docs API Swagger
|
EnableDocs bool // enable generate docs & server docs API Swagger
|
||||||
RouterCaseSensitive bool // router case sensitive default is true
|
RouterCaseSensitive bool // router case sensitive default is true
|
||||||
|
AccessLogs bool // print access logs, default is false
|
||||||
)
|
)
|
||||||
|
|
||||||
type beegoAppConfig struct {
|
type beegoAppConfig struct {
|
||||||
@ -110,7 +111,7 @@ func (b *beegoAppConfig) String(key string) string {
|
|||||||
|
|
||||||
func (b *beegoAppConfig) Strings(key string) []string {
|
func (b *beegoAppConfig) Strings(key string) []string {
|
||||||
v := b.innerConfig.Strings(RunMode + "::" + key)
|
v := b.innerConfig.Strings(RunMode + "::" + key)
|
||||||
if len(v) == 0 {
|
if v[0] == "" {
|
||||||
return b.innerConfig.Strings(key)
|
return b.innerConfig.Strings(key)
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
|
@ -17,13 +17,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// JsonConfig is a json config parser and implements Config interface.
|
// JsonConfig is a json config parser and implements Config interface.
|
||||||
@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return js.ParseData(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseData returns a ConfigContainer with json string
|
||||||
|
func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) {
|
||||||
x := &JsonConfigContainer{
|
x := &JsonConfigContainer{
|
||||||
data: make(map[string]interface{}),
|
data: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(content, &x.data)
|
err := json.Unmarshal(data, &x.data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var wrappingArray []interface{}
|
var wrappingArray []interface{}
|
||||||
err2 := json.Unmarshal(content, &wrappingArray)
|
err2 := json.Unmarshal(data, &wrappingArray)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) {
|
|
||||||
// Save memory data to temporary file
|
|
||||||
tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond()))
|
|
||||||
os.MkdirAll(path.Dir(tmpName), os.ModePerm)
|
|
||||||
if err := ioutil.WriteFile(tmpName, data, 0655); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return js.Parse(tmpName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Config represents the json configuration.
|
// A Config represents the json configuration.
|
||||||
// Only when get value, support key as section:name type.
|
// Only when get value, support key as section:name type.
|
||||||
type JsonConfigContainer struct {
|
type JsonConfigContainer struct {
|
||||||
@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) {
|
|||||||
// DefaultBool return the bool value if has no error
|
// DefaultBool return the bool value if has no error
|
||||||
// otherwise return the defaultval
|
// otherwise return the defaultval
|
||||||
func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||||
if v, err := c.Bool(key); err != nil {
|
if v, err := c.Bool(key); err == nil {
|
||||||
return defaultval
|
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int returns the integer value for a given key.
|
// Int returns the integer value for a given key.
|
||||||
@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) {
|
|||||||
// DefaultInt returns the integer value for a given key.
|
// DefaultInt returns the integer value for a given key.
|
||||||
// if err != nil return defaltval
|
// if err != nil return defaltval
|
||||||
func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int {
|
func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||||
if v, err := c.Int(key); err != nil {
|
if v, err := c.Int(key); err == nil {
|
||||||
return defaultval
|
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int64 returns the int64 value for a given key.
|
// Int64 returns the int64 value for a given key.
|
||||||
@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) {
|
|||||||
// DefaultInt64 returns the int64 value for a given key.
|
// DefaultInt64 returns the int64 value for a given key.
|
||||||
// if err != nil return defaltval
|
// if err != nil return defaltval
|
||||||
func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||||
if v, err := c.Int64(key); err != nil {
|
if v, err := c.Int64(key); err == nil {
|
||||||
return defaultval
|
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float returns the float value for a given key.
|
// Float returns the float value for a given key.
|
||||||
@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) {
|
|||||||
// DefaultFloat returns the float64 value for a given key.
|
// DefaultFloat returns the float64 value for a given key.
|
||||||
// if err != nil return defaltval
|
// if err != nil return defaltval
|
||||||
func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||||
if v, err := c.Float(key); err != nil {
|
if v, err := c.Float(key); err == nil {
|
||||||
return defaultval
|
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string value for a given key.
|
// String returns the string value for a given key.
|
||||||
@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string {
|
|||||||
// DefaultString returns the string value for a given key.
|
// DefaultString returns the string value for a given key.
|
||||||
// if err != nil return defaltval
|
// if err != nil return defaltval
|
||||||
func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string {
|
func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string {
|
||||||
if v := c.String(key); v == "" {
|
// TODO FIXME should not use "" to replace non existance
|
||||||
return defaultval
|
if v := c.String(key); v != "" {
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strings returns the []string value for a given key.
|
// Strings returns the []string value for a given key.
|
||||||
func (c *JsonConfigContainer) Strings(key string) []string {
|
func (c *JsonConfigContainer) Strings(key string) []string {
|
||||||
|
stringVal := c.String(key)
|
||||||
|
if stringVal == "" {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
return strings.Split(c.String(key), ";")
|
return strings.Split(c.String(key), ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultStrings returns the []string value for a given key.
|
// DefaultStrings returns the []string value for a given key.
|
||||||
// if err != nil return defaltval
|
// if err != nil return defaltval
|
||||||
func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||||
if v := c.Strings(key); len(v) == 0 {
|
if v := c.Strings(key); len(v) > 0 {
|
||||||
return defaultval
|
|
||||||
} else {
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
return defaultval
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSection returns map for the given section
|
// GetSection returns map for the given section
|
||||||
func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) {
|
func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||||
if v, ok := c.data[section]; ok {
|
if v, ok := c.data[section]; ok {
|
||||||
return v.(map[string]string), nil
|
return v.(map[string]string), nil
|
||||||
} else {
|
|
||||||
return nil, errors.New("not exist setction")
|
|
||||||
}
|
}
|
||||||
|
return nil, errors.New("nonexist section " + section)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveConfigFile save the config into file
|
// SaveConfigFile save the config into file
|
||||||
@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteValue writes a new value for key.
|
// Set writes a new value for key.
|
||||||
func (c *JsonConfigContainer) Set(key, val string) error {
|
func (c *JsonConfigContainer) Set(key, val string) error {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
|
|||||||
|
|
||||||
// section.key or key
|
// section.key or key
|
||||||
func (c *JsonConfigContainer) getData(key string) interface{} {
|
func (c *JsonConfigContainer) getData(key string) interface{} {
|
||||||
c.RLock()
|
|
||||||
defer c.RUnlock()
|
|
||||||
if len(key) == 0 {
|
if len(key) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
sectionKey := strings.Split(key, "::")
|
|
||||||
if len(sectionKey) >= 2 {
|
c.RLock()
|
||||||
curValue, ok := c.data[sectionKey[0]]
|
defer c.RUnlock()
|
||||||
|
|
||||||
|
sectionKeys := strings.Split(key, "::")
|
||||||
|
if len(sectionKeys) >= 2 {
|
||||||
|
curValue, ok := c.data[sectionKeys[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, key := range sectionKey[1:] {
|
for _, key := range sectionKeys[1:] {
|
||||||
if v, ok := curValue.(map[string]interface{}); ok {
|
if v, ok := curValue.(map[string]interface{}); ok {
|
||||||
if curValue, ok = v[key]; !ok {
|
if curValue, ok = v[key]; !ok {
|
||||||
return nil
|
return nil
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
var jsoncontext = `{
|
var jsoncontext = `{
|
||||||
"appname": "beeapi",
|
"appname": "beeapi",
|
||||||
|
"testnames": "foo;bar",
|
||||||
"httpport": 8080,
|
"httpport": 8080,
|
||||||
"mysqlport": 3600,
|
"mysqlport": 3600,
|
||||||
"PI": 3.1415976,
|
"PI": 3.1415976,
|
||||||
@ -28,8 +29,8 @@ var jsoncontext = `{
|
|||||||
"autorender": false,
|
"autorender": false,
|
||||||
"copyrequestbody": true,
|
"copyrequestbody": true,
|
||||||
"database": {
|
"database": {
|
||||||
"host": "host",
|
"host": "host",
|
||||||
"port": "port",
|
"port": "port",
|
||||||
"database": "database",
|
"database": "database",
|
||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
@ -122,6 +123,12 @@ func TestJson(t *testing.T) {
|
|||||||
if jsonconf.String("runmode") != "dev" {
|
if jsonconf.String("runmode") != "dev" {
|
||||||
t.Fatal("runmode not equal to 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 {
|
if v, err := jsonconf.Bool("autorender"); err != nil || v != false {
|
||||||
t.Error(v)
|
t.Error(v)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -179,4 +186,8 @@ func TestJson(t *testing.T) {
|
|||||||
if _, err := jsonconf.Bool("unknown"); err == nil {
|
if _, err := jsonconf.Bool("unknown"); err == nil {
|
||||||
t.Error("unknown keys should return an error when expecting a Bool")
|
t.Error("unknown keys should return an error when expecting a Bool")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !jsonconf.DefaultBool("unknow", true) {
|
||||||
|
t.Error("unknown keys with default value wrong")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/middleware"
|
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,24 +52,10 @@ func (ctx *Context) Redirect(status int, localurl string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Abort stops this request.
|
// Abort stops this request.
|
||||||
// if middleware.ErrorMaps exists, panic body.
|
// if beego.ErrorMaps exists, panic body.
|
||||||
// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string.
|
|
||||||
func (ctx *Context) Abort(status int, body string) {
|
func (ctx *Context) Abort(status int, body string) {
|
||||||
ctx.ResponseWriter.WriteHeader(status)
|
ctx.ResponseWriter.WriteHeader(status)
|
||||||
// first panic from ErrorMaps, is is user defined error functions.
|
panic(body)
|
||||||
if _, ok := middleware.ErrorMaps[body]; ok {
|
|
||||||
panic(body)
|
|
||||||
}
|
|
||||||
// second panic from HTTPExceptionMaps, it is system defined functions.
|
|
||||||
if e, ok := middleware.HTTPExceptionMaps[status]; ok {
|
|
||||||
if len(body) >= 1 {
|
|
||||||
e.Description = body
|
|
||||||
}
|
|
||||||
panic(e)
|
|
||||||
}
|
|
||||||
// last panic user string
|
|
||||||
ctx.ResponseWriter.Write([]byte(body))
|
|
||||||
panic("User stop run")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write string to response body.
|
// Write string to response body.
|
||||||
@ -155,8 +140,11 @@ func (ctx *Context) CheckXsrfCookie() bool {
|
|||||||
}
|
}
|
||||||
if token == "" {
|
if token == "" {
|
||||||
ctx.Abort(403, "'_xsrf' argument missing from POST")
|
ctx.Abort(403, "'_xsrf' argument missing from POST")
|
||||||
} else if ctx._xsrf_token != token {
|
return false
|
||||||
|
}
|
||||||
|
if ctx._xsrf_token != token {
|
||||||
ctx.Abort(403, "XSRF cookie does not match POST argument")
|
ctx.Abort(403, "XSRF cookie does not match POST argument")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeegoInput operates the http request header ,data ,cookie and body.
|
// BeegoInput operates the http request header, data, cookie and body.
|
||||||
// it also contains router params and current session.
|
// it also contains router params and current session.
|
||||||
type BeegoInput struct {
|
type BeegoInput struct {
|
||||||
CruSession session.SessionStore
|
CruSession session.SessionStore
|
||||||
@ -72,11 +72,11 @@ func (input *BeegoInput) Site() string {
|
|||||||
func (input *BeegoInput) Scheme() string {
|
func (input *BeegoInput) Scheme() string {
|
||||||
if input.Request.URL.Scheme != "" {
|
if input.Request.URL.Scheme != "" {
|
||||||
return input.Request.URL.Scheme
|
return input.Request.URL.Scheme
|
||||||
} else if input.Request.TLS == nil {
|
|
||||||
return "http"
|
|
||||||
} else {
|
|
||||||
return "https"
|
|
||||||
}
|
}
|
||||||
|
if input.Request.TLS == nil {
|
||||||
|
return "http"
|
||||||
|
}
|
||||||
|
return "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain returns host name.
|
// Domain returns host name.
|
||||||
@ -153,12 +153,12 @@ func (input *BeegoInput) IsSecure() bool {
|
|||||||
return input.Scheme() == "https"
|
return input.Scheme() == "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSecure returns boolean of this request is in webSocket.
|
// IsWebsocket returns boolean of this request is in webSocket.
|
||||||
func (input *BeegoInput) IsWebsocket() bool {
|
func (input *BeegoInput) IsWebsocket() bool {
|
||||||
return input.Header("Upgrade") == "websocket"
|
return input.Header("Upgrade") == "websocket"
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSecure returns boolean of whether file uploads in this request or not..
|
// IsUpload returns boolean of whether file uploads in this request or not..
|
||||||
func (input *BeegoInput) IsUpload() bool {
|
func (input *BeegoInput) IsUpload() bool {
|
||||||
return strings.Contains(input.Header("Content-Type"), "multipart/form-data")
|
return strings.Contains(input.Header("Content-Type"), "multipart/form-data")
|
||||||
}
|
}
|
||||||
@ -189,16 +189,24 @@ func (input *BeegoInput) Proxy() []string {
|
|||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Referer returns http referer header.
|
||||||
|
func (input *BeegoInput) Referer() string {
|
||||||
|
return input.Header("Referer")
|
||||||
|
}
|
||||||
|
|
||||||
// Refer returns http referer header.
|
// Refer returns http referer header.
|
||||||
func (input *BeegoInput) Refer() string {
|
func (input *BeegoInput) Refer() string {
|
||||||
return input.Header("Referer")
|
return input.Referer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubDomains returns sub domain string.
|
// SubDomains returns sub domain string.
|
||||||
// if aa.bb.domain.com, returns aa.bb .
|
// if aa.bb.domain.com, returns aa.bb .
|
||||||
func (input *BeegoInput) SubDomains() string {
|
func (input *BeegoInput) SubDomains() string {
|
||||||
parts := strings.Split(input.Host(), ".")
|
parts := strings.Split(input.Host(), ".")
|
||||||
return strings.Join(parts[len(parts)-2:], ".")
|
if len(parts) >= 3 {
|
||||||
|
return strings.Join(parts[:len(parts)-2], ".")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Port returns request client port.
|
// Port returns request client port.
|
||||||
@ -237,6 +245,7 @@ func (input *BeegoInput) Query(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Header returns request header item string by a given string.
|
// Header returns request header item string by a given string.
|
||||||
|
// if non-existed, return empty string.
|
||||||
func (input *BeegoInput) Header(key string) string {
|
func (input *BeegoInput) Header(key string) string {
|
||||||
return input.Request.Header.Get(key)
|
return input.Request.Header.Get(key)
|
||||||
}
|
}
|
||||||
@ -252,11 +261,12 @@ func (input *BeegoInput) Cookie(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Session returns current session item value by a given key.
|
// Session returns current session item value by a given key.
|
||||||
|
// if non-existed, return empty string.
|
||||||
func (input *BeegoInput) Session(key interface{}) interface{} {
|
func (input *BeegoInput) Session(key interface{}) interface{} {
|
||||||
return input.CruSession.Get(key)
|
return input.CruSession.Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body returns the raw request body data as bytes.
|
// CopyBody returns the raw request body data as bytes.
|
||||||
func (input *BeegoInput) CopyBody() []byte {
|
func (input *BeegoInput) CopyBody() []byte {
|
||||||
requestbody, _ := ioutil.ReadAll(input.Request.Body)
|
requestbody, _ := ioutil.ReadAll(input.Request.Body)
|
||||||
input.Request.Body.Close()
|
input.Request.Body.Close()
|
||||||
|
@ -70,3 +70,45 @@ func TestParse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fmt.Println(user)
|
fmt.Println(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSubDomain(t *testing.T) {
|
||||||
|
r, _ := http.NewRequest("GET", "http://www.example.com/?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie", nil)
|
||||||
|
beegoInput := NewInput(r)
|
||||||
|
|
||||||
|
subdomain := beegoInput.SubDomains()
|
||||||
|
if subdomain != "www" {
|
||||||
|
t.Fatal("Subdomain parse error, got" + subdomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _ = http.NewRequest("GET", "http://localhost/", nil)
|
||||||
|
beegoInput.Request = r
|
||||||
|
if beegoInput.SubDomains() != "" {
|
||||||
|
t.Fatal("Subdomain parse error, should be empty, got " + beegoInput.SubDomains())
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _ = http.NewRequest("GET", "http://aa.bb.example.com/", nil)
|
||||||
|
beegoInput.Request = r
|
||||||
|
if beegoInput.SubDomains() != "aa.bb" {
|
||||||
|
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Fix this
|
||||||
|
r, _ = http.NewRequest("GET", "http://127.0.0.1/", nil)
|
||||||
|
beegoInput.Request = r
|
||||||
|
if beegoInput.SubDomains() != "" {
|
||||||
|
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
r, _ = http.NewRequest("GET", "http://example.com/", nil)
|
||||||
|
beegoInput.Request = r
|
||||||
|
if beegoInput.SubDomains() != "" {
|
||||||
|
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||||
|
}
|
||||||
|
|
||||||
|
r, _ = http.NewRequest("GET", "http://aa.bb.cc.dd.example.com/", nil)
|
||||||
|
beegoInput.Request = r
|
||||||
|
if beegoInput.SubDomains() != "aa.bb.cc.dd" {
|
||||||
|
t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -188,7 +188,7 @@ func sanitizeValue(v string) string {
|
|||||||
// Json writes json to response body.
|
// Json writes json to response body.
|
||||||
// if coding is true, it converts utf-8 to \u0000 type.
|
// if coding is true, it converts utf-8 to \u0000 type.
|
||||||
func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) error {
|
func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) error {
|
||||||
output.Header("Content-Type", "application/json;charset=UTF-8")
|
output.Header("Content-Type", "application/json; charset=utf-8")
|
||||||
var content []byte
|
var content []byte
|
||||||
var err error
|
var err error
|
||||||
if hasIndent {
|
if hasIndent {
|
||||||
@ -209,7 +209,7 @@ func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) e
|
|||||||
|
|
||||||
// Jsonp writes jsonp to response body.
|
// Jsonp writes jsonp to response body.
|
||||||
func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error {
|
func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error {
|
||||||
output.Header("Content-Type", "application/javascript;charset=UTF-8")
|
output.Header("Content-Type", "application/javascript; charset=utf-8")
|
||||||
var content []byte
|
var content []byte
|
||||||
var err error
|
var err error
|
||||||
if hasIndent {
|
if hasIndent {
|
||||||
@ -235,7 +235,7 @@ func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error {
|
|||||||
|
|
||||||
// Xml writes xml string to response body.
|
// Xml writes xml string to response body.
|
||||||
func (output *BeegoOutput) Xml(data interface{}, hasIndent bool) error {
|
func (output *BeegoOutput) Xml(data interface{}, hasIndent bool) error {
|
||||||
output.Header("Content-Type", "application/xml;charset=UTF-8")
|
output.Header("Content-Type", "application/xml; charset=utf-8")
|
||||||
var content []byte
|
var content []byte
|
||||||
var err error
|
var err error
|
||||||
if hasIndent {
|
if hasIndent {
|
||||||
|
163
controller.go
163
controller.go
@ -270,16 +270,22 @@ func (c *Controller) Redirect(url string, code int) {
|
|||||||
// Aborts stops controller handler and show the error data if code is defined in ErrorMap or code string.
|
// Aborts stops controller handler and show the error data if code is defined in ErrorMap or code string.
|
||||||
func (c *Controller) Abort(code string) {
|
func (c *Controller) Abort(code string) {
|
||||||
status, err := strconv.Atoi(code)
|
status, err := strconv.Atoi(code)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
c.Ctx.Abort(status, code)
|
status = 200
|
||||||
} else {
|
|
||||||
c.Ctx.Abort(200, code)
|
|
||||||
}
|
}
|
||||||
|
c.CustomAbort(status, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
|
// CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body.
|
||||||
func (c *Controller) CustomAbort(status int, body string) {
|
func (c *Controller) CustomAbort(status int, body string) {
|
||||||
c.Ctx.Abort(status, body)
|
c.Ctx.ResponseWriter.WriteHeader(status)
|
||||||
|
// first panic from ErrorMaps, is is user defined error functions.
|
||||||
|
if _, ok := ErrorMaps[body]; ok {
|
||||||
|
panic(body)
|
||||||
|
}
|
||||||
|
// last panic user string
|
||||||
|
c.Ctx.ResponseWriter.Write([]byte(body))
|
||||||
|
panic(USERSTOPRUN)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
|
// StopRun makes panic of USERSTOPRUN error and go to recover function if defined.
|
||||||
@ -289,7 +295,7 @@ func (c *Controller) StopRun() {
|
|||||||
|
|
||||||
// UrlFor does another controller handler in this request function.
|
// UrlFor does another controller handler in this request function.
|
||||||
// it goes to this controller method if endpoint is not clear.
|
// it goes to this controller method if endpoint is not clear.
|
||||||
func (c *Controller) UrlFor(endpoint string, values ...string) string {
|
func (c *Controller) UrlFor(endpoint string, values ...interface{}) string {
|
||||||
if len(endpoint) <= 0 {
|
if len(endpoint) <= 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -363,67 +369,144 @@ func (c *Controller) ParseForm(obj interface{}) error {
|
|||||||
return ParseForm(c.Input(), obj)
|
return ParseForm(c.Input(), obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetString returns the input value by key string.
|
// GetString returns the input value by key string or the default value while it's present and input is blank
|
||||||
func (c *Controller) GetString(key string) string {
|
func (c *Controller) GetString(key string, def ...string) string {
|
||||||
return c.Ctx.Input.Query(key)
|
var defv string
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if v := c.Ctx.Input.Query(key); v != "" {
|
||||||
|
return v
|
||||||
|
} else {
|
||||||
|
return defv
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStrings returns the input string slice by key string.
|
// GetStrings returns the input string slice by key string or the default value while it's present and input is blank
|
||||||
// it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection.
|
// it's designed for multi-value input field such as checkbox(input[type=checkbox]), multi-selection.
|
||||||
func (c *Controller) GetStrings(key string) []string {
|
func (c *Controller) GetStrings(key string, def ...[]string) []string {
|
||||||
|
var defv []string
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
f := c.Input()
|
f := c.Input()
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return []string{}
|
return defv
|
||||||
}
|
}
|
||||||
|
|
||||||
vs := f[key]
|
vs := f[key]
|
||||||
if len(vs) > 0 {
|
if len(vs) > 0 {
|
||||||
return vs
|
return vs
|
||||||
|
} else {
|
||||||
|
return defv
|
||||||
}
|
}
|
||||||
return []string{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt returns input as an int
|
// GetInt returns input as an int or the default value while it's present and input is blank
|
||||||
func (c *Controller) GetInt(key string) (int, error) {
|
func (c *Controller) GetInt(key string, def ...int) (int, error) {
|
||||||
return strconv.Atoi(c.Ctx.Input.Query(key))
|
var defv int
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
return strconv.Atoi(strv)
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt8 return input as an int8
|
// GetInt8 return input as an int8 or the default value while it's present and input is blank
|
||||||
func (c *Controller) GetInt8(key string) (int8, error) {
|
func (c *Controller) GetInt8(key string, def ...int8) (int8, error) {
|
||||||
i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 8)
|
var defv int8
|
||||||
i8 := int8(i64)
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
return i8, err
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
i64, err := strconv.ParseInt(strv, 10, 8)
|
||||||
|
i8 := int8(i64)
|
||||||
|
return i8, err
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt16 returns input as an int16
|
// GetInt16 returns input as an int16 or the default value while it's present and input is blank
|
||||||
func (c *Controller) GetInt16(key string) (int16, error) {
|
func (c *Controller) GetInt16(key string, def ...int16) (int16, error) {
|
||||||
i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 16)
|
var defv int16
|
||||||
i16 := int16(i64)
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
return i16, err
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
i64, err := strconv.ParseInt(strv, 10, 16)
|
||||||
|
i16 := int16(i64)
|
||||||
|
|
||||||
|
return i16, err
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt32 returns input as an int32
|
// GetInt32 returns input as an int32 or the default value while it's present and input is blank
|
||||||
func (c *Controller) GetInt32(key string) (int32, error) {
|
func (c *Controller) GetInt32(key string, def ...int32) (int32, error) {
|
||||||
i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 32)
|
var defv int32
|
||||||
i32 := int32(i64)
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
return i32, err
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 32)
|
||||||
|
i32 := int32(i64)
|
||||||
|
return i32, err
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetInt64 returns input value as int64.
|
// GetInt64 returns input value as int64 or the default value while it's present and input is blank.
|
||||||
func (c *Controller) GetInt64(key string) (int64, error) {
|
func (c *Controller) GetInt64(key string, def ...int64) (int64, error) {
|
||||||
return strconv.ParseInt(c.Ctx.Input.Query(key), 10, 64)
|
var defv int64
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
return strconv.ParseInt(strv, 10, 64)
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBool returns input value as bool.
|
// GetBool returns input value as bool or the default value while it's present and input is blank.
|
||||||
func (c *Controller) GetBool(key string) (bool, error) {
|
func (c *Controller) GetBool(key string, def ...bool) (bool, error) {
|
||||||
return strconv.ParseBool(c.Ctx.Input.Query(key))
|
var defv bool
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
return strconv.ParseBool(strv)
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFloat returns input value as float64.
|
// GetFloat returns input value as float64 or the default value while it's present and input is blank.
|
||||||
func (c *Controller) GetFloat(key string) (float64, error) {
|
func (c *Controller) GetFloat(key string, def ...float64) (float64, error) {
|
||||||
return strconv.ParseFloat(c.Ctx.Input.Query(key), 64)
|
var defv float64
|
||||||
|
if len(def) > 0 {
|
||||||
|
defv = def[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strv := c.Ctx.Input.Query(key); strv != "" {
|
||||||
|
return strconv.ParseFloat(c.Ctx.Input.Query(key), 64)
|
||||||
|
} else {
|
||||||
|
return defv, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFile returns the file data in file upload field named as key.
|
// GetFile returns the file data in file upload field named as key.
|
||||||
|
@ -12,20 +12,26 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package middleware
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
const (
|
||||||
AppName string
|
errorTypeHandler = iota
|
||||||
VERSION string
|
errorTypeController
|
||||||
)
|
)
|
||||||
|
|
||||||
var tpl = `
|
var tpl = `
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@ -76,18 +82,18 @@ var tpl = `
|
|||||||
`
|
`
|
||||||
|
|
||||||
// render default application error page with error and stack string.
|
// render default application error page with error and stack string.
|
||||||
func ShowErr(err interface{}, rw http.ResponseWriter, r *http.Request, Stack string) {
|
func showErr(err interface{}, ctx *context.Context, Stack string) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(tpl)
|
t, _ := template.New("beegoerrortemp").Parse(tpl)
|
||||||
data := make(map[string]string)
|
data := make(map[string]string)
|
||||||
data["AppError"] = AppName + ":" + fmt.Sprint(err)
|
data["AppError"] = AppName + ":" + fmt.Sprint(err)
|
||||||
data["RequestMethod"] = r.Method
|
data["RequestMethod"] = ctx.Input.Method()
|
||||||
data["RequestURL"] = r.RequestURI
|
data["RequestURL"] = ctx.Input.Uri()
|
||||||
data["RemoteAddr"] = r.RemoteAddr
|
data["RemoteAddr"] = ctx.Input.IP()
|
||||||
data["Stack"] = Stack
|
data["Stack"] = Stack
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
data["GoVersion"] = runtime.Version()
|
data["GoVersion"] = runtime.Version()
|
||||||
rw.WriteHeader(500)
|
ctx.Output.SetStatus(500)
|
||||||
t.Execute(rw, data)
|
t.Execute(ctx.ResponseWriter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errtpl = `
|
var errtpl = `
|
||||||
@ -190,15 +196,68 @@ var errtpl = `
|
|||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
type errorInfo struct {
|
||||||
|
controllerType reflect.Type
|
||||||
|
handler http.HandlerFunc
|
||||||
|
method string
|
||||||
|
errorType int
|
||||||
|
}
|
||||||
|
|
||||||
// map of http handlers for each error string.
|
// map of http handlers for each error string.
|
||||||
var ErrorMaps map[string]http.HandlerFunc
|
var ErrorMaps map[string]*errorInfo
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ErrorMaps = make(map[string]http.HandlerFunc)
|
ErrorMaps = make(map[string]*errorInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show 401 unauthorized error.
|
||||||
|
func unauthorized(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Unauthorized"
|
||||||
|
data["Content"] = template.HTML("<br>The page you have requested can't be authorized." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>The credentials you supplied are incorrect" +
|
||||||
|
"<br>There are errors in the website address" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show 402 Payment Required
|
||||||
|
func paymentRequired(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Payment Required"
|
||||||
|
data["Content"] = template.HTML("<br>The page you have requested Payment Required." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>The credentials you supplied are incorrect" +
|
||||||
|
"<br>There are errors in the website address" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show 403 forbidden error.
|
||||||
|
func forbidden(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Forbidden"
|
||||||
|
data["Content"] = template.HTML("<br>The page you have requested is forbidden." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>Your address may be blocked" +
|
||||||
|
"<br>The site may be disabled" +
|
||||||
|
"<br>You need to log in" +
|
||||||
|
"</ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 404 notfound error.
|
// show 404 notfound error.
|
||||||
func NotFound(rw http.ResponseWriter, r *http.Request) {
|
func notFound(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["Title"] = "Page Not Found"
|
data["Title"] = "Page Not Found"
|
||||||
@ -211,45 +270,66 @@ func NotFound(rw http.ResponseWriter, r *http.Request) {
|
|||||||
"<br>You like 404 pages" +
|
"<br>You like 404 pages" +
|
||||||
"</ul>")
|
"</ul>")
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
//rw.WriteHeader(http.StatusNotFound)
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 401 unauthorized error.
|
// show 405 Method Not Allowed
|
||||||
func Unauthorized(rw http.ResponseWriter, r *http.Request) {
|
func methodNotAllowed(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["Title"] = "Unauthorized"
|
data["Title"] = "Method Not Allowed"
|
||||||
data["Content"] = template.HTML("<br>The page you have requested can't be authorized." +
|
data["Content"] = template.HTML("<br>The method you have requested Not Allowed." +
|
||||||
"<br>Perhaps you are here because:" +
|
"<br>Perhaps you are here because:" +
|
||||||
"<br><br><ul>" +
|
"<br><br><ul>" +
|
||||||
"<br>The credentials you supplied are incorrect" +
|
"<br>The method specified in the Request-Line is not allowed for the resource identified by the Request-URI" +
|
||||||
"<br>There are errors in the website address" +
|
"<br>The response MUST include an Allow header containing a list of valid methods for the requested resource." +
|
||||||
"</ul>")
|
"</ul>")
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
//rw.WriteHeader(http.StatusUnauthorized)
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 403 forbidden error.
|
// show 500 internal server error.
|
||||||
func Forbidden(rw http.ResponseWriter, r *http.Request) {
|
func internalServerError(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["Title"] = "Forbidden"
|
data["Title"] = "Internal Server Error"
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is forbidden." +
|
data["Content"] = template.HTML("<br>The page you have requested is down right now." +
|
||||||
"<br>Perhaps you are here because:" +
|
|
||||||
"<br><br><ul>" +
|
"<br><br><ul>" +
|
||||||
"<br>Your address may be blocked" +
|
"<br>Please try again later and report the error to the website administrator" +
|
||||||
"<br>The site may be disabled" +
|
"<br></ul>")
|
||||||
"<br>You need to log in" +
|
data["BeegoVersion"] = VERSION
|
||||||
"</ul>")
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show 501 Not Implemented.
|
||||||
|
func notImplemented(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Not Implemented"
|
||||||
|
data["Content"] = template.HTML("<br>The page you have requested is Not Implemented." +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>Please try again later and report the error to the website administrator" +
|
||||||
|
"<br></ul>")
|
||||||
|
data["BeegoVersion"] = VERSION
|
||||||
|
t.Execute(rw, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// show 502 Bad Gateway.
|
||||||
|
func badGateway(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["Title"] = "Bad Gateway"
|
||||||
|
data["Content"] = template.HTML("<br>The page you have requested is down right now." +
|
||||||
|
"<br><br><ul>" +
|
||||||
|
"<br>The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request." +
|
||||||
|
"<br>Please try again later and report the error to the website administrator" +
|
||||||
|
"<br></ul>")
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
//rw.WriteHeader(http.StatusForbidden)
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 503 service unavailable error.
|
// show 503 service unavailable error.
|
||||||
func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
func serviceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["Title"] = "Service Unavailable"
|
data["Title"] = "Service Unavailable"
|
||||||
@ -260,80 +340,151 @@ func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) {
|
|||||||
"<br>Please try again later." +
|
"<br>Please try again later." +
|
||||||
"</ul>")
|
"</ul>")
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
//rw.WriteHeader(http.StatusServiceUnavailable)
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 500 internal server error.
|
// show 504 Gateway Timeout.
|
||||||
func InternalServerError(rw http.ResponseWriter, r *http.Request) {
|
func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["Title"] = "Internal Server Error"
|
data["Title"] = "Gateway Timeout"
|
||||||
data["Content"] = template.HTML("<br>The page you have requested is down right now." +
|
data["Content"] = template.HTML("<br>The page you have requested is unavailable." +
|
||||||
|
"<br>Perhaps you are here because:" +
|
||||||
"<br><br><ul>" +
|
"<br><br><ul>" +
|
||||||
"<br>Please try again later and report the error to the website administrator" +
|
"<br><br>The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI." +
|
||||||
"<br></ul>")
|
"<br>Please try again later." +
|
||||||
|
"</ul>")
|
||||||
data["BeegoVersion"] = VERSION
|
data["BeegoVersion"] = VERSION
|
||||||
//rw.WriteHeader(http.StatusInternalServerError)
|
|
||||||
t.Execute(rw, data)
|
t.Execute(rw, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 500 internal error with simple text string.
|
|
||||||
func SimpleServerError(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add http handler for given error string.
|
|
||||||
func Errorhandler(err string, h http.HandlerFunc) {
|
|
||||||
ErrorMaps[err] = h
|
|
||||||
}
|
|
||||||
|
|
||||||
// register default error http handlers, 404,401,403,500 and 503.
|
// register default error http handlers, 404,401,403,500 and 503.
|
||||||
func RegisterErrorHandler() {
|
func registerDefaultErrorHandler() {
|
||||||
if _, ok := ErrorMaps["404"]; !ok {
|
if _, ok := ErrorMaps["401"]; !ok {
|
||||||
ErrorMaps["404"] = NotFound
|
Errorhandler("401", unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := ErrorMaps["401"]; !ok {
|
if _, ok := ErrorMaps["402"]; !ok {
|
||||||
ErrorMaps["401"] = Unauthorized
|
Errorhandler("402", paymentRequired)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := ErrorMaps["403"]; !ok {
|
if _, ok := ErrorMaps["403"]; !ok {
|
||||||
ErrorMaps["403"] = Forbidden
|
Errorhandler("403", forbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := ErrorMaps["503"]; !ok {
|
if _, ok := ErrorMaps["404"]; !ok {
|
||||||
ErrorMaps["503"] = ServiceUnavailable
|
Errorhandler("404", notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["405"]; !ok {
|
||||||
|
Errorhandler("405", methodNotAllowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := ErrorMaps["500"]; !ok {
|
if _, ok := ErrorMaps["500"]; !ok {
|
||||||
ErrorMaps["500"] = InternalServerError
|
Errorhandler("500", internalServerError)
|
||||||
}
|
}
|
||||||
|
if _, ok := ErrorMaps["501"]; !ok {
|
||||||
|
Errorhandler("501", notImplemented)
|
||||||
|
}
|
||||||
|
if _, ok := ErrorMaps["502"]; !ok {
|
||||||
|
Errorhandler("502", badGateway)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["503"]; !ok {
|
||||||
|
Errorhandler("503", serviceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := ErrorMaps["504"]; !ok {
|
||||||
|
Errorhandler("504", gatewayTimeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorHandler registers http.HandlerFunc to each http err code string.
|
||||||
|
// usage:
|
||||||
|
// beego.ErrorHandler("404",NotFound)
|
||||||
|
// beego.ErrorHandler("500",InternalServerError)
|
||||||
|
func Errorhandler(code string, h http.HandlerFunc) *App {
|
||||||
|
errinfo := &errorInfo{}
|
||||||
|
errinfo.errorType = errorTypeHandler
|
||||||
|
errinfo.handler = h
|
||||||
|
errinfo.method = code
|
||||||
|
ErrorMaps[code] = errinfo
|
||||||
|
return BeeApp
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorController registers ControllerInterface to each http err code string.
|
||||||
|
// usage:
|
||||||
|
// beego.ErrorHandler(&controllers.ErrorController{})
|
||||||
|
func ErrorController(c ControllerInterface) *App {
|
||||||
|
reflectVal := reflect.ValueOf(c)
|
||||||
|
rt := reflectVal.Type()
|
||||||
|
ct := reflect.Indirect(reflectVal).Type()
|
||||||
|
for i := 0; i < rt.NumMethod(); i++ {
|
||||||
|
if !utils.InSlice(rt.Method(i).Name, exceptMethod) && strings.HasPrefix(rt.Method(i).Name, "Error") {
|
||||||
|
errinfo := &errorInfo{}
|
||||||
|
errinfo.errorType = errorTypeController
|
||||||
|
errinfo.controllerType = ct
|
||||||
|
errinfo.method = rt.Method(i).Name
|
||||||
|
errname := strings.TrimPrefix(rt.Method(i).Name, "Error")
|
||||||
|
ErrorMaps[errname] = errinfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BeeApp
|
||||||
}
|
}
|
||||||
|
|
||||||
// show error string as simple text message.
|
// show error string as simple text message.
|
||||||
// if error string is empty, show 500 error as default.
|
// if error string is empty, show 500 error as default.
|
||||||
func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg string) {
|
func exception(errcode string, ctx *context.Context) {
|
||||||
|
code, err := strconv.Atoi(errcode)
|
||||||
|
if err != nil {
|
||||||
|
code = 503
|
||||||
|
}
|
||||||
|
ctx.ResponseWriter.WriteHeader(code)
|
||||||
if h, ok := ErrorMaps[errcode]; ok {
|
if h, ok := ErrorMaps[errcode]; ok {
|
||||||
isint, err := strconv.Atoi(errcode)
|
executeError(h, ctx)
|
||||||
if err != nil {
|
return
|
||||||
isint = 500
|
} else if h, ok := ErrorMaps["503"]; ok {
|
||||||
}
|
executeError(h, ctx)
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
w.WriteHeader(isint)
|
|
||||||
h(w, r)
|
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
isint, err := strconv.Atoi(errcode)
|
ctx.WriteString(errcode)
|
||||||
if err != nil {
|
}
|
||||||
isint = 500
|
}
|
||||||
}
|
|
||||||
if isint == 400 {
|
func executeError(err *errorInfo, ctx *context.Context) {
|
||||||
msg = "404 page not found"
|
if err.errorType == errorTypeHandler {
|
||||||
}
|
err.handler(ctx.ResponseWriter, ctx.Request)
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
return
|
||||||
w.WriteHeader(isint)
|
}
|
||||||
fmt.Fprintln(w, msg)
|
if err.errorType == errorTypeController {
|
||||||
return
|
//Invoke the request handler
|
||||||
|
vc := reflect.New(err.controllerType)
|
||||||
|
execController, ok := vc.Interface().(ControllerInterface)
|
||||||
|
if !ok {
|
||||||
|
panic("controller is not ControllerInterface")
|
||||||
|
}
|
||||||
|
//call the controller init function
|
||||||
|
execController.Init(ctx, err.controllerType.Name(), err.method, vc.Interface())
|
||||||
|
|
||||||
|
//call prepare function
|
||||||
|
execController.Prepare()
|
||||||
|
|
||||||
|
execController.URLMapping()
|
||||||
|
|
||||||
|
in := make([]reflect.Value, 0)
|
||||||
|
method := vc.MethodByName(err.method)
|
||||||
|
method.Call(in)
|
||||||
|
|
||||||
|
//render template
|
||||||
|
if ctx.Output.Status == 0 {
|
||||||
|
if AutoRender {
|
||||||
|
if err := execController.Render(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish all runrouter. release resource
|
||||||
|
execController.Finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -253,30 +253,20 @@ func (b *BeegoHttpRequest) Body(data interface{}) *BeegoHttpRequest {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
func (b *BeegoHttpRequest) buildUrl(paramBody string) {
|
||||||
if b.resp.StatusCode != 0 {
|
// build GET url with query string
|
||||||
return b.resp, nil
|
|
||||||
}
|
|
||||||
var paramBody string
|
|
||||||
if len(b.params) > 0 {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for k, v := range b.params {
|
|
||||||
buf.WriteString(url.QueryEscape(k))
|
|
||||||
buf.WriteByte('=')
|
|
||||||
buf.WriteString(url.QueryEscape(v))
|
|
||||||
buf.WriteByte('&')
|
|
||||||
}
|
|
||||||
paramBody = buf.String()
|
|
||||||
paramBody = paramBody[0 : len(paramBody)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.req.Method == "GET" && len(paramBody) > 0 {
|
if b.req.Method == "GET" && len(paramBody) > 0 {
|
||||||
if strings.Index(b.url, "?") != -1 {
|
if strings.Index(b.url, "?") != -1 {
|
||||||
b.url += "&" + paramBody
|
b.url += "&" + paramBody
|
||||||
} else {
|
} else {
|
||||||
b.url = b.url + "?" + paramBody
|
b.url = b.url + "?" + paramBody
|
||||||
}
|
}
|
||||||
} else if b.req.Method == "POST" && b.req.Body == nil {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// build POST url and body
|
||||||
|
if b.req.Method == "POST" && b.req.Body == nil {
|
||||||
|
// with files
|
||||||
if len(b.files) > 0 {
|
if len(b.files) > 0 {
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
bodyWriter := multipart.NewWriter(pw)
|
bodyWriter := multipart.NewWriter(pw)
|
||||||
@ -305,12 +295,35 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
|||||||
}()
|
}()
|
||||||
b.Header("Content-Type", bodyWriter.FormDataContentType())
|
b.Header("Content-Type", bodyWriter.FormDataContentType())
|
||||||
b.req.Body = ioutil.NopCloser(pr)
|
b.req.Body = ioutil.NopCloser(pr)
|
||||||
} else if len(paramBody) > 0 {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// with params
|
||||||
|
if len(paramBody) > 0 {
|
||||||
b.Header("Content-Type", "application/x-www-form-urlencoded")
|
b.Header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
b.Body(paramBody)
|
b.Body(paramBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
||||||
|
if b.resp.StatusCode != 0 {
|
||||||
|
return b.resp, nil
|
||||||
|
}
|
||||||
|
var paramBody string
|
||||||
|
if len(b.params) > 0 {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for k, v := range b.params {
|
||||||
|
buf.WriteString(url.QueryEscape(k))
|
||||||
|
buf.WriteByte('=')
|
||||||
|
buf.WriteString(url.QueryEscape(v))
|
||||||
|
buf.WriteByte('&')
|
||||||
|
}
|
||||||
|
paramBody = buf.String()
|
||||||
|
paramBody = paramBody[0 : len(paramBody)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
b.buildUrl(paramBody)
|
||||||
url, err := url.Parse(b.url)
|
url, err := url.Parse(b.url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -342,14 +355,12 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var jar http.CookieJar
|
var jar http.CookieJar = nil
|
||||||
if b.setting.EnableCookie {
|
if b.setting.EnableCookie {
|
||||||
if defaultCookieJar == nil {
|
if defaultCookieJar == nil {
|
||||||
createDefaultCookie()
|
createDefaultCookie()
|
||||||
}
|
}
|
||||||
jar = defaultCookieJar
|
jar = defaultCookieJar
|
||||||
} else {
|
|
||||||
jar = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
@ -402,12 +413,11 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
b.body, err = ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
b.body = data
|
return b.body, nil
|
||||||
return data, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToFile saves the body data in response to one file.
|
// ToFile saves the body data in response to one file.
|
||||||
@ -438,8 +448,7 @@ func (b *BeegoHttpRequest) ToJson(v interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(data, v)
|
return json.Unmarshal(data, v)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToXml returns the map that marshals from the body bytes as xml in response .
|
// ToXml returns the map that marshals from the body bytes as xml in response .
|
||||||
@ -449,8 +458,7 @@ func (b *BeegoHttpRequest) ToXml(v interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = xml.Unmarshal(data, v)
|
return xml.Unmarshal(data, v)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response executes request client gets response mannually.
|
// Response executes request client gets response mannually.
|
||||||
|
11
logs/conn.go
11
logs/conn.go
@ -43,11 +43,7 @@ func NewConn() LoggerInterface {
|
|||||||
// init connection writer with json config.
|
// init connection writer with json config.
|
||||||
// json config only need key "level".
|
// json config only need key "level".
|
||||||
func (c *ConnWriter) Init(jsonconfig string) error {
|
func (c *ConnWriter) Init(jsonconfig string) error {
|
||||||
err := json.Unmarshal([]byte(jsonconfig), c)
|
return json.Unmarshal([]byte(jsonconfig), c)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write message in connection.
|
// write message in connection.
|
||||||
@ -77,10 +73,9 @@ func (c *ConnWriter) Flush() {
|
|||||||
|
|
||||||
// destroy connection writer and close tcp listener.
|
// destroy connection writer and close tcp listener.
|
||||||
func (c *ConnWriter) Destroy() {
|
func (c *ConnWriter) Destroy() {
|
||||||
if c.innerWriter == nil {
|
if c.innerWriter != nil {
|
||||||
return
|
c.innerWriter.Close()
|
||||||
}
|
}
|
||||||
c.innerWriter.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConnWriter) connect() error {
|
func (c *ConnWriter) connect() error {
|
||||||
|
@ -50,9 +50,10 @@ type ConsoleWriter struct {
|
|||||||
|
|
||||||
// create ConsoleWriter returning as LoggerInterface.
|
// create ConsoleWriter returning as LoggerInterface.
|
||||||
func NewConsole() LoggerInterface {
|
func NewConsole() LoggerInterface {
|
||||||
cw := new(ConsoleWriter)
|
cw := &ConsoleWriter{
|
||||||
cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime)
|
lg: log.New(os.Stdout, "", log.Ldate|log.Ltime),
|
||||||
cw.Level = LevelDebug
|
Level: LevelDebug,
|
||||||
|
}
|
||||||
return cw
|
return cw
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +63,7 @@ func (c *ConsoleWriter) Init(jsonconfig string) error {
|
|||||||
if len(jsonconfig) == 0 {
|
if len(jsonconfig) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err := json.Unmarshal([]byte(jsonconfig), c)
|
return json.Unmarshal([]byte(jsonconfig), c)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write message in console.
|
// write message in console.
|
||||||
@ -76,9 +73,10 @@ func (c *ConsoleWriter) WriteMsg(msg string, level int) error {
|
|||||||
}
|
}
|
||||||
if goos := runtime.GOOS; goos == "windows" {
|
if goos := runtime.GOOS; goos == "windows" {
|
||||||
c.lg.Println(msg)
|
c.lg.Println(msg)
|
||||||
} else {
|
return nil
|
||||||
c.lg.Println(colors[level](msg))
|
|
||||||
}
|
}
|
||||||
|
c.lg.Println(colors[level](msg))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
logs/file.go
43
logs/file.go
@ -15,10 +15,11 @@
|
|||||||
package logs
|
package logs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -122,11 +123,7 @@ func (w *FileLogWriter) startLogger() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.mw.SetFd(fd)
|
w.mw.SetFd(fd)
|
||||||
err = w.initFd()
|
return w.initFd()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *FileLogWriter) docheck(size int) {
|
func (w *FileLogWriter) docheck(size int) {
|
||||||
@ -169,18 +166,44 @@ func (w *FileLogWriter) initFd() error {
|
|||||||
}
|
}
|
||||||
w.maxsize_cursize = int(finfo.Size())
|
w.maxsize_cursize = int(finfo.Size())
|
||||||
w.daily_opendate = time.Now().Day()
|
w.daily_opendate = time.Now().Day()
|
||||||
|
w.maxlines_curlines = 0
|
||||||
if finfo.Size() > 0 {
|
if finfo.Size() > 0 {
|
||||||
content, err := ioutil.ReadFile(w.Filename)
|
count, err := w.lines()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.maxlines_curlines = len(strings.Split(string(content), "\n"))
|
w.maxlines_curlines = count
|
||||||
} else {
|
|
||||||
w.maxlines_curlines = 0
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *FileLogWriter) lines() (int, error) {
|
||||||
|
fd, err := os.Open(w.Filename)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
buf := make([]byte, 32768) // 32k
|
||||||
|
count := 0
|
||||||
|
lineSep := []byte{'\n'}
|
||||||
|
|
||||||
|
for {
|
||||||
|
c, err := fd.Read(buf)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count += bytes.Count(buf[:c], lineSep)
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 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.log.2013-01-01.2
|
// new file name like xx.log.2013-01-01.2
|
||||||
func (w *FileLogWriter) DoRotate() error {
|
func (w *FileLogWriter) DoRotate() error {
|
||||||
|
@ -292,9 +292,9 @@ func (bl *BeeLogger) Close() {
|
|||||||
fmt.Println("ERROR, unable to WriteMsg (while closing logger):", err)
|
fmt.Println("ERROR, unable to WriteMsg (while closing logger):", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
continue
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
for _, l := range bl.outputs {
|
for _, l := range bl.outputs {
|
||||||
l.Flush()
|
l.Flush()
|
||||||
|
@ -25,7 +25,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
subjectPhrase = "Diagnostic message from server"
|
// no usage
|
||||||
|
// subjectPhrase = "Diagnostic message from server"
|
||||||
)
|
)
|
||||||
|
|
||||||
// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
|
// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
|
||||||
@ -146,9 +147,7 @@ func (s *SmtpWriter) WriteMsg(msg string, level int) error {
|
|||||||
mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress +
|
mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress +
|
||||||
">\r\nSubject: " + s.Subject + "\r\n" + content_type + "\r\n\r\n" + fmt.Sprintf(".%s", time.Now().Format("2006-01-02 15:04:05")) + msg)
|
">\r\nSubject: " + s.Subject + "\r\n" + content_type + "\r\n\r\n" + fmt.Sprintf(".%s", time.Now().Format("2006-01-02 15:04:05")) + msg)
|
||||||
|
|
||||||
err := s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg)
|
return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg)
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// implementing method. empty.
|
// implementing method. empty.
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2014 beego Author. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// http exceptions
|
|
||||||
type HTTPException struct {
|
|
||||||
StatusCode int // http status code 4xx, 5xx
|
|
||||||
Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
// return http exception error string, e.g. "400 Bad Request".
|
|
||||||
func (e *HTTPException) Error() string {
|
|
||||||
return fmt.Sprintf("%d %s", e.StatusCode, e.Description)
|
|
||||||
}
|
|
||||||
|
|
||||||
// map of http exceptions for each http status code int.
|
|
||||||
// defined 400,401,403,404,405,500,502,503 and 504 default.
|
|
||||||
var HTTPExceptionMaps map[int]HTTPException
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
HTTPExceptionMaps = make(map[int]HTTPException)
|
|
||||||
|
|
||||||
// Normal 4XX HTTP Status
|
|
||||||
HTTPExceptionMaps[400] = HTTPException{400, "Bad Request"}
|
|
||||||
HTTPExceptionMaps[401] = HTTPException{401, "Unauthorized"}
|
|
||||||
HTTPExceptionMaps[403] = HTTPException{403, "Forbidden"}
|
|
||||||
HTTPExceptionMaps[404] = HTTPException{404, "Not Found"}
|
|
||||||
HTTPExceptionMaps[405] = HTTPException{405, "Method Not Allowed"}
|
|
||||||
|
|
||||||
// Normal 5XX HTTP Status
|
|
||||||
HTTPExceptionMaps[500] = HTTPException{500, "Internal Server Error"}
|
|
||||||
HTTPExceptionMaps[502] = HTTPException{502, "Bad Gateway"}
|
|
||||||
HTTPExceptionMaps[503] = HTTPException{503, "Service Unavailable"}
|
|
||||||
HTTPExceptionMaps[504] = HTTPException{504, "Gateway Timeout"}
|
|
||||||
}
|
|
@ -34,7 +34,6 @@ type Translation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewLocale(filepath string, defaultlocal string) *Translation {
|
func NewLocale(filepath string, defaultlocal string) *Translation {
|
||||||
i18n := make(map[string]map[string]string)
|
|
||||||
file, err := os.Open(filepath)
|
file, err := os.Open(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("open " + filepath + " err :" + err.Error())
|
panic("open " + filepath + " err :" + err.Error())
|
||||||
@ -43,8 +42,9 @@ func NewLocale(filepath string, defaultlocal string) *Translation {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic("read " + filepath + " err :" + err.Error())
|
panic("read " + filepath + " err :" + err.Error())
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(data, &i18n)
|
|
||||||
if err != nil {
|
i18n := make(map[string]map[string]string)
|
||||||
|
if err = json.Unmarshal(data, &i18n); err != nil {
|
||||||
panic("json.Unmarshal " + filepath + " err :" + err.Error())
|
panic("json.Unmarshal " + filepath + " err :" + err.Error())
|
||||||
}
|
}
|
||||||
return &Translation{
|
return &Translation{
|
||||||
|
@ -19,7 +19,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
beecontext "github.com/astaxie/beego/context"
|
beecontext "github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/middleware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type namespaceCond func(*beecontext.Context) bool
|
type namespaceCond func(*beecontext.Context) bool
|
||||||
@ -57,7 +56,7 @@ func NewNamespace(prefix string, params ...innnerNamespace) *Namespace {
|
|||||||
func (n *Namespace) Cond(cond namespaceCond) *Namespace {
|
func (n *Namespace) Cond(cond namespaceCond) *Namespace {
|
||||||
fn := func(ctx *beecontext.Context) {
|
fn := func(ctx *beecontext.Context) {
|
||||||
if !cond(ctx) {
|
if !cond(ctx) {
|
||||||
middleware.Exception("405", ctx.ResponseWriter, ctx.Request, "Method not allowed")
|
exception("405", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v, ok := n.handlers.filters[BeforeRouter]; ok {
|
if v, ok := n.handlers.filters[BeforeRouter]; ok {
|
||||||
|
@ -104,7 +104,11 @@ func getColumnAddQuery(al *alias, fi *fieldInfo) string {
|
|||||||
typ += " " + "NOT NULL"
|
typ += " " + "NOT NULL"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s", Q, fi.mi.table, Q, Q, fi.column, Q, typ)
|
return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s %s",
|
||||||
|
Q, fi.mi.table, Q,
|
||||||
|
Q, fi.column, Q,
|
||||||
|
typ, getColumnDefault(fi),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create database creation string.
|
// create database creation string.
|
||||||
@ -155,6 +159,9 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
|
|||||||
//if fi.initial.String() != "" {
|
//if fi.initial.String() != "" {
|
||||||
// column += " DEFAULT " + fi.initial.String()
|
// column += " DEFAULT " + fi.initial.String()
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
// Append attribute DEFAULT
|
||||||
|
column += getColumnDefault(fi)
|
||||||
|
|
||||||
if fi.unique {
|
if fi.unique {
|
||||||
column += " " + "UNIQUE"
|
column += " " + "UNIQUE"
|
||||||
@ -239,3 +246,44 @@ func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get string value for the attribute "DEFAULT" for the CREATE, ALTER commands
|
||||||
|
func getColumnDefault(fi *fieldInfo) string {
|
||||||
|
var (
|
||||||
|
v, t, d string
|
||||||
|
)
|
||||||
|
|
||||||
|
// Skip default attribute if field is in relations
|
||||||
|
if fi.rel || fi.reverse {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
t = " DEFAULT '%s' "
|
||||||
|
|
||||||
|
// These defaults will be useful if there no config value orm:"default" and NOT NULL is on
|
||||||
|
switch fi.fieldType {
|
||||||
|
case TypeDateField, TypeDateTimeField:
|
||||||
|
return v;
|
||||||
|
|
||||||
|
case TypeBooleanField, TypeBitField, TypeSmallIntegerField, TypeIntegerField,
|
||||||
|
TypeBigIntegerField, TypePositiveBitField, TypePositiveSmallIntegerField,
|
||||||
|
TypePositiveIntegerField, TypePositiveBigIntegerField, TypeFloatField,
|
||||||
|
TypeDecimalField:
|
||||||
|
d = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.colDefault {
|
||||||
|
if !fi.initial.Exist() {
|
||||||
|
v = fmt.Sprintf(t, "")
|
||||||
|
} else {
|
||||||
|
v = fmt.Sprintf(t, fi.initial.String())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !fi.null {
|
||||||
|
v = fmt.Sprintf(t, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
@ -116,6 +116,7 @@ type fieldInfo struct {
|
|||||||
null bool
|
null bool
|
||||||
index bool
|
index bool
|
||||||
unique bool
|
unique bool
|
||||||
|
colDefault bool
|
||||||
initial StrTo
|
initial StrTo
|
||||||
size int
|
size int
|
||||||
auto_now bool
|
auto_now bool
|
||||||
@ -280,6 +281,11 @@ checkType:
|
|||||||
fi.pk = attrs["pk"]
|
fi.pk = attrs["pk"]
|
||||||
fi.unique = attrs["unique"]
|
fi.unique = attrs["unique"]
|
||||||
|
|
||||||
|
// Mark object property if there is attribute "default" in the orm configuration
|
||||||
|
if _, ok := tags["default"]; ok {
|
||||||
|
fi.colDefault = true
|
||||||
|
}
|
||||||
|
|
||||||
switch fieldType {
|
switch fieldType {
|
||||||
case RelManyToMany, RelReverseMany, RelReverseOne:
|
case RelManyToMany, RelReverseMany, RelReverseOne:
|
||||||
fi.null = false
|
fi.null = false
|
||||||
|
@ -489,10 +489,6 @@ func (o *orm) Driver() Driver {
|
|||||||
return driver(o.alias.Name)
|
return driver(o.alias.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orm) GetDB() dbQuerier {
|
|
||||||
panic(ErrNotImplement)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new orm
|
// create new orm
|
||||||
func NewOrm() Ormer {
|
func NewOrm() Ormer {
|
||||||
BootStrap() // execute only once
|
BootStrap() // execute only once
|
||||||
|
@ -51,7 +51,6 @@ type Ormer interface {
|
|||||||
Rollback() error
|
Rollback() error
|
||||||
Raw(string, ...interface{}) RawSeter
|
Raw(string, ...interface{}) RawSeter
|
||||||
Driver() Driver
|
Driver() Driver
|
||||||
GetDB() dbQuerier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert prepared statement
|
// insert prepared statement
|
||||||
|
@ -57,7 +57,7 @@ func parserPkg(pkgRealpath, pkgpath string) error {
|
|||||||
rep := strings.NewReplacer("/", "_", ".", "_")
|
rep := strings.NewReplacer("/", "_", ".", "_")
|
||||||
commentFilename = COMMENTFL + rep.Replace(pkgpath) + ".go"
|
commentFilename = COMMENTFL + rep.Replace(pkgpath) + ".go"
|
||||||
if !compareFile(pkgRealpath) {
|
if !compareFile(pkgRealpath) {
|
||||||
Info(pkgRealpath + " don't has updated")
|
Info(pkgRealpath + " has not changed, not reloading")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
genInfoList = make(map[string][]ControllerComments)
|
genInfoList = make(map[string][]ControllerComments)
|
||||||
|
@ -217,6 +217,7 @@ func Allow(opts *Options) beego.FilterFunc {
|
|||||||
ctx.Output.Header(key, value)
|
ctx.Output.Header(key, value)
|
||||||
}
|
}
|
||||||
ctx.Output.SetStatus(http.StatusOK)
|
ctx.Output.SetStatus(http.StatusOK)
|
||||||
|
ctx.WriteString("")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
headers = opts.Header(origin)
|
headers = opts.Header(origin)
|
||||||
|
107
router.go
107
router.go
@ -30,7 +30,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
beecontext "github.com/astaxie/beego/context"
|
beecontext "github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/middleware"
|
|
||||||
"github.com/astaxie/beego/toolbox"
|
"github.com/astaxie/beego/toolbox"
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
@ -153,7 +152,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
|
|||||||
if val := reflectVal.MethodByName(colon[1]); val.IsValid() {
|
if val := reflectVal.MethodByName(colon[1]); val.IsValid() {
|
||||||
methods[strings.ToUpper(m)] = colon[1]
|
methods[strings.ToUpper(m)] = colon[1]
|
||||||
} else {
|
} else {
|
||||||
panic(colon[1] + " method doesn't exist in the controller " + t.Name())
|
panic("'" + colon[1] + "' method doesn't exist in the controller " + t.Name())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic(v + " is an invalid method mapping. Method doesn't exist " + m)
|
panic(v + " is an invalid method mapping. Method doesn't exist " + m)
|
||||||
@ -429,7 +428,7 @@ func (p *ControllerRegistor) insertFilterRouter(pos int, mr *FilterRouter) error
|
|||||||
|
|
||||||
// UrlFor does another controller handler in this request function.
|
// UrlFor does another controller handler in this request function.
|
||||||
// it can access any controller method.
|
// it can access any controller method.
|
||||||
func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
func (p *ControllerRegistor) UrlFor(endpoint string, values ...interface{}) string {
|
||||||
paths := strings.Split(endpoint, ".")
|
paths := strings.Split(endpoint, ".")
|
||||||
if len(paths) <= 1 {
|
if len(paths) <= 1 {
|
||||||
Warn("urlfor endpoint must like path.controller.method")
|
Warn("urlfor endpoint must like path.controller.method")
|
||||||
@ -444,9 +443,9 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
|||||||
key := ""
|
key := ""
|
||||||
for k, v := range values {
|
for k, v := range values {
|
||||||
if k%2 == 0 {
|
if k%2 == 0 {
|
||||||
key = v
|
key = fmt.Sprint(v)
|
||||||
} else {
|
} else {
|
||||||
params[key] = v
|
params[key] = fmt.Sprint(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -577,7 +576,6 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin
|
|||||||
|
|
||||||
// Implement http.Handler interface.
|
// Implement http.Handler interface.
|
||||||
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
defer p.recoverPanic(rw, r)
|
|
||||||
starttime := time.Now()
|
starttime := time.Now()
|
||||||
var runrouter reflect.Type
|
var runrouter reflect.Type
|
||||||
var findrouter bool
|
var findrouter bool
|
||||||
@ -600,6 +598,8 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
context.Output.Context = context
|
context.Output.Context = context
|
||||||
context.Output.EnableGzip = EnableGzip
|
context.Output.EnableGzip = EnableGzip
|
||||||
|
|
||||||
|
defer p.recoverPanic(context)
|
||||||
|
|
||||||
var urlPath string
|
var urlPath string
|
||||||
if !RouterCaseSensitive {
|
if !RouterCaseSensitive {
|
||||||
urlPath = strings.ToLower(r.URL.Path)
|
urlPath = strings.ToLower(r.URL.Path)
|
||||||
@ -648,7 +648,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
context.Input.CruSession, err = GlobalSessions.SessionStart(w, r)
|
context.Input.CruSession, err = GlobalSessions.SessionStart(w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error(err)
|
Error(err)
|
||||||
middleware.Exception("503", rw, r, "")
|
exception("503", context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -703,7 +703,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
//if no matches to url, throw a not found exception
|
//if no matches to url, throw a not found exception
|
||||||
if !findrouter {
|
if !findrouter {
|
||||||
middleware.Exception("404", rw, r, "")
|
exception("404", context)
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,7 +719,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
isRunable = true
|
isRunable = true
|
||||||
routerInfo.runfunction(context)
|
routerInfo.runfunction(context)
|
||||||
} else {
|
} else {
|
||||||
middleware.Exception("405", rw, r, "Method Not Allowed")
|
exception("405", context)
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
} else if routerInfo.routerType == routerTypeHandler {
|
} else if routerInfo.routerType == routerTypeHandler {
|
||||||
@ -830,7 +830,7 @@ Admin:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if RunMode == "dev" {
|
if RunMode == "dev" || AccessLogs {
|
||||||
var devinfo string
|
var devinfo string
|
||||||
if findrouter {
|
if findrouter {
|
||||||
if routerInfo != nil {
|
if routerInfo != nil {
|
||||||
@ -852,28 +852,51 @@ Admin:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ControllerRegistor) recoverPanic(rw http.ResponseWriter, r *http.Request) {
|
func (p *ControllerRegistor) recoverPanic(context *beecontext.Context) {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
if err == USERSTOPRUN {
|
if err == USERSTOPRUN {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if he, ok := err.(middleware.HTTPException); ok {
|
if RunMode == "dev" {
|
||||||
rw.WriteHeader(he.StatusCode)
|
if !RecoverPanic {
|
||||||
rw.Write([]byte(he.Description))
|
panic(err)
|
||||||
// catch intented errors, only for HTTP 4XX and 5XX
|
} else {
|
||||||
} else {
|
if ErrorsShow {
|
||||||
if RunMode == "dev" {
|
if handler, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
||||||
if !RecoverPanic {
|
executeError(handler, context)
|
||||||
panic(err)
|
return
|
||||||
} else {
|
|
||||||
if ErrorsShow {
|
|
||||||
if handler, ok := middleware.ErrorMaps[fmt.Sprint(err)]; ok {
|
|
||||||
handler(rw, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var stack string
|
}
|
||||||
Critical("the request url is ", r.URL.Path)
|
var stack string
|
||||||
|
Critical("the request url is ", context.Input.Url())
|
||||||
|
Critical("Handler crashed with error", err)
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
_, file, line, ok := runtime.Caller(i)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
Critical(fmt.Sprintf("%s:%d", file, line))
|
||||||
|
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
|
||||||
|
}
|
||||||
|
showErr(err, context, stack)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !RecoverPanic {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
// in production model show all infomation
|
||||||
|
if ErrorsShow {
|
||||||
|
if handler, ok := ErrorMaps[fmt.Sprint(err)]; ok {
|
||||||
|
executeError(handler, context)
|
||||||
|
return
|
||||||
|
} else if handler, ok := ErrorMaps["503"]; ok {
|
||||||
|
executeError(handler, context)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
context.WriteString(fmt.Sprint(err))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Critical("the request url is ", context.Input.Url())
|
||||||
Critical("Handler crashed with error", err)
|
Critical("Handler crashed with error", err)
|
||||||
for i := 1; ; i++ {
|
for i := 1; ; i++ {
|
||||||
_, file, line, ok := runtime.Caller(i)
|
_, file, line, ok := runtime.Caller(i)
|
||||||
@ -881,39 +904,9 @@ func (p *ControllerRegistor) recoverPanic(rw http.ResponseWriter, r *http.Reques
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
Critical(fmt.Sprintf("%s:%d", file, line))
|
Critical(fmt.Sprintf("%s:%d", file, line))
|
||||||
stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
|
|
||||||
}
|
|
||||||
middleware.ShowErr(err, rw, r, stack)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if !RecoverPanic {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
// in production model show all infomation
|
|
||||||
if ErrorsShow {
|
|
||||||
if handler, ok := middleware.ErrorMaps[fmt.Sprint(err)]; ok {
|
|
||||||
handler(rw, r)
|
|
||||||
return
|
|
||||||
} else if handler, ok := middleware.ErrorMaps["503"]; ok {
|
|
||||||
handler(rw, r)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
rw.Write([]byte(fmt.Sprint(err)))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Critical("the request url is ", r.URL.Path)
|
|
||||||
Critical("Handler crashed with error", err)
|
|
||||||
for i := 1; ; i++ {
|
|
||||||
_, file, line, ok := runtime.Caller(i)
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
Critical(fmt.Sprintf("%s:%d", file, line))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package session
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
@ -74,19 +76,29 @@ func (ls *LedisSessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
type LedisProvider struct {
|
type LedisProvider struct {
|
||||||
maxlifetime int64
|
maxlifetime int64
|
||||||
savePath string
|
savePath string
|
||||||
|
db int
|
||||||
}
|
}
|
||||||
|
|
||||||
// init ledis session
|
// init ledis session
|
||||||
// savepath like ledis server saveDataPath,pool size
|
// savepath like ledis server saveDataPath,pool size
|
||||||
// e.g. 127.0.0.1:6379,100,astaxie
|
// e.g. 127.0.0.1:6379,100,astaxie
|
||||||
func (lp *LedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
func (lp *LedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||||
|
var err error
|
||||||
lp.maxlifetime = maxlifetime
|
lp.maxlifetime = maxlifetime
|
||||||
lp.savePath = savePath
|
configs := strings.Split(savepath, ",")
|
||||||
|
if len(configs) == 1 {
|
||||||
|
lp.savePath = configs[0]
|
||||||
|
} else if len(configs) == 2 {
|
||||||
|
lp.savePath = configs[0]
|
||||||
|
lp.db, err = strconv.Atoi(configs[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
cfg := new(config.Config)
|
cfg := new(config.Config)
|
||||||
cfg.DataDir = lp.savePath
|
cfg.DataDir = lp.savePath
|
||||||
var err error
|
|
||||||
nowLedis, err := ledis.Open(cfg)
|
nowLedis, err := ledis.Open(cfg)
|
||||||
c, err = nowLedis.Select(0)
|
c, err = nowLedis.Select(lp.db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println(err)
|
println(err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -118,12 +118,13 @@ type RedisProvider struct {
|
|||||||
savePath string
|
savePath string
|
||||||
poolsize int
|
poolsize int
|
||||||
password string
|
password string
|
||||||
|
dbNum int
|
||||||
poollist *redis.Pool
|
poollist *redis.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
// init redis session
|
// init redis session
|
||||||
// savepath like redis server addr,pool size,password
|
// savepath like redis server addr,pool size,password,dbnum
|
||||||
// e.g. 127.0.0.1:6379,100,astaxie
|
// e.g. 127.0.0.1:6379,100,astaxie,0
|
||||||
func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
||||||
rp.maxlifetime = maxlifetime
|
rp.maxlifetime = maxlifetime
|
||||||
configs := strings.Split(savePath, ",")
|
configs := strings.Split(savePath, ",")
|
||||||
@ -143,6 +144,16 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
if len(configs) > 2 {
|
if len(configs) > 2 {
|
||||||
rp.password = configs[2]
|
rp.password = configs[2]
|
||||||
}
|
}
|
||||||
|
if len(configs) > 3 {
|
||||||
|
dbnum, err := strconv.Atoi(configs[1])
|
||||||
|
if err != nil || dbnum < 0 {
|
||||||
|
rp.dbNum = 0
|
||||||
|
} else {
|
||||||
|
rp.dbNum = dbnum
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rp.dbNum = 0
|
||||||
|
}
|
||||||
rp.poollist = redis.NewPool(func() (redis.Conn, error) {
|
rp.poollist = redis.NewPool(func() (redis.Conn, error) {
|
||||||
c, err := redis.Dial("tcp", rp.savePath)
|
c, err := redis.Dial("tcp", rp.savePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -154,6 +165,11 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_, err = c.Do("SELECT", rp.dbNum)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return c, err
|
return c, err
|
||||||
}, rp.poolsize)
|
}, rp.poolsize)
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/middleware"
|
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ func serverStaticRouter(ctx *context.Context) {
|
|||||||
//if the request is dir and DirectoryIndex is false then
|
//if the request is dir and DirectoryIndex is false then
|
||||||
if finfo.IsDir() {
|
if finfo.IsDir() {
|
||||||
if !DirectoryIndex {
|
if !DirectoryIndex {
|
||||||
middleware.Exception("403", ctx.ResponseWriter, ctx.Request, "403 Forbidden")
|
exception("403", ctx)
|
||||||
return
|
return
|
||||||
} else if ctx.Input.Request.URL.Path[len(ctx.Input.Request.URL.Path)-1] != '/' {
|
} else if ctx.Input.Request.URL.Path[len(ctx.Input.Request.URL.Path)-1] != '/' {
|
||||||
http.Redirect(ctx.ResponseWriter, ctx.Request, ctx.Input.Request.URL.Path+"/", 302)
|
http.Redirect(ctx.ResponseWriter, ctx.Request, ctx.Input.Request.URL.Path+"/", 302)
|
||||||
|
@ -42,6 +42,9 @@ func init() {
|
|||||||
beegoTplFuncMap["dateformat"] = DateFormat
|
beegoTplFuncMap["dateformat"] = DateFormat
|
||||||
beegoTplFuncMap["date"] = Date
|
beegoTplFuncMap["date"] = Date
|
||||||
beegoTplFuncMap["compare"] = Compare
|
beegoTplFuncMap["compare"] = Compare
|
||||||
|
beegoTplFuncMap["compare_not"] = CompareNot
|
||||||
|
beegoTplFuncMap["not_nil"] = NotNil
|
||||||
|
beegoTplFuncMap["not_null"] = NotNil
|
||||||
beegoTplFuncMap["substr"] = Substr
|
beegoTplFuncMap["substr"] = Substr
|
||||||
beegoTplFuncMap["html2str"] = Html2str
|
beegoTplFuncMap["html2str"] = Html2str
|
||||||
beegoTplFuncMap["str2html"] = Str2html
|
beegoTplFuncMap["str2html"] = Str2html
|
||||||
|
@ -139,6 +139,14 @@ func Compare(a, b interface{}) (equal bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CompareNot(a, b interface{}) (equal bool) {
|
||||||
|
return ! Compare(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotNil(a interface{}) (is_nil bool) {
|
||||||
|
return CompareNot(a, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func Config(returnType, key string, defaultVal interface{}) (value interface{}, err error) {
|
func Config(returnType, key string, defaultVal interface{}) (value interface{}, err error) {
|
||||||
switch returnType {
|
switch returnType {
|
||||||
case "String":
|
case "String":
|
||||||
@ -246,7 +254,7 @@ func Htmlunquote(src string) string {
|
|||||||
// /user/John%20Doe
|
// /user/John%20Doe
|
||||||
//
|
//
|
||||||
// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
|
// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
|
||||||
func UrlFor(endpoint string, values ...string) string {
|
func UrlFor(endpoint string, values ...interface{}) string {
|
||||||
return BeeApp.Handlers.UrlFor(endpoint, values...)
|
return BeeApp.Handlers.UrlFor(endpoint, values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +358,32 @@ func ParseForm(form url.Values, obj interface{}) error {
|
|||||||
}
|
}
|
||||||
fieldV.Set(reflect.ValueOf(t))
|
fieldV.Set(reflect.ValueOf(t))
|
||||||
}
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
if fieldT.Type == sliceOfInts {
|
||||||
|
formVals := form[tag]
|
||||||
|
fieldV.Set(reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(int(1))), len(formVals), len(formVals)))
|
||||||
|
for i := 0; i < len(formVals); i++ {
|
||||||
|
val, err := strconv.Atoi(formVals[i])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fieldV.Index(i).SetInt(int64(val))
|
||||||
|
}
|
||||||
|
} else if fieldT.Type == sliceOfStrings {
|
||||||
|
formVals := form[tag]
|
||||||
|
fieldV.Set(reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf("")), len(formVals), len(formVals)))
|
||||||
|
for i := 0; i < len(formVals); i++ {
|
||||||
|
fieldV.Index(i).SetString(formVals[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sliceOfInts = reflect.TypeOf([]int(nil))
|
||||||
|
var sliceOfStrings = reflect.TypeOf([]string(nil))
|
||||||
|
|
||||||
var unKind = map[reflect.Kind]bool{
|
var unKind = map[reflect.Kind]bool{
|
||||||
reflect.Uintptr: true,
|
reflect.Uintptr: true,
|
||||||
reflect.Complex64: true,
|
reflect.Complex64: true,
|
||||||
|
@ -72,7 +72,7 @@ func TestDate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompare(t *testing.T) {
|
func TestCompareRelated(t *testing.T) {
|
||||||
if !Compare("abc", "abc") {
|
if !Compare("abc", "abc") {
|
||||||
t.Error("should be equal")
|
t.Error("should be equal")
|
||||||
}
|
}
|
||||||
@ -82,6 +82,15 @@ func TestCompare(t *testing.T) {
|
|||||||
if !Compare("1", 1) {
|
if !Compare("1", 1) {
|
||||||
t.Error("should be equal")
|
t.Error("should be equal")
|
||||||
}
|
}
|
||||||
|
if CompareNot("abc", "abc") {
|
||||||
|
t.Error("should be equal")
|
||||||
|
}
|
||||||
|
if !CompareNot("abc", "aBc") {
|
||||||
|
t.Error("should be not equal")
|
||||||
|
}
|
||||||
|
if !NotNil("a string") {
|
||||||
|
t.Error("should not be nil")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHtmlquote(t *testing.T) {
|
func TestHtmlquote(t *testing.T) {
|
||||||
|
@ -84,6 +84,7 @@ type TaskFunc func() error
|
|||||||
|
|
||||||
// task interface
|
// task interface
|
||||||
type Tasker interface {
|
type Tasker interface {
|
||||||
|
GetSpec() string
|
||||||
GetStatus() string
|
GetStatus() string
|
||||||
Run() error
|
Run() error
|
||||||
SetNext(time.Time)
|
SetNext(time.Time)
|
||||||
@ -102,6 +103,7 @@ type taskerr struct {
|
|||||||
type Task struct {
|
type Task struct {
|
||||||
Taskname string
|
Taskname string
|
||||||
Spec *Schedule
|
Spec *Schedule
|
||||||
|
SpecStr string
|
||||||
DoFunc TaskFunc
|
DoFunc TaskFunc
|
||||||
Prev time.Time
|
Prev time.Time
|
||||||
Next time.Time
|
Next time.Time
|
||||||
@ -116,16 +118,22 @@ func NewTask(tname string, spec string, f TaskFunc) *Task {
|
|||||||
Taskname: tname,
|
Taskname: tname,
|
||||||
DoFunc: f,
|
DoFunc: f,
|
||||||
ErrLimit: 100,
|
ErrLimit: 100,
|
||||||
|
SpecStr: spec,
|
||||||
}
|
}
|
||||||
task.SetCron(spec)
|
task.SetCron(spec)
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get spec string
|
||||||
|
func (s *Task) GetSpec() string {
|
||||||
|
return s.SpecStr
|
||||||
|
}
|
||||||
|
|
||||||
// get current task status
|
// get current task status
|
||||||
func (tk *Task) GetStatus() string {
|
func (tk *Task) GetStatus() string {
|
||||||
var str string
|
var str string
|
||||||
for _, v := range tk.Errlist {
|
for _, v := range tk.Errlist {
|
||||||
str += v.t.String() + ":" + v.errinfo + "\n"
|
str += v.t.String() + ":" + v.errinfo + "<br>"
|
||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
3
tree.go
3
tree.go
@ -422,6 +422,9 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string
|
|||||||
// "/admin/" -> ["admin"]
|
// "/admin/" -> ["admin"]
|
||||||
// "/admin/users" -> ["admin", "users"]
|
// "/admin/users" -> ["admin", "users"]
|
||||||
func splitPath(key string) []string {
|
func splitPath(key string) []string {
|
||||||
|
if key == "" {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
elements := strings.Split(key, "/")
|
elements := strings.Split(key, "/")
|
||||||
if elements[0] == "" {
|
if elements[0] == "" {
|
||||||
elements = elements[1:]
|
elements = elements[1:]
|
||||||
|
@ -149,7 +149,11 @@ func TestAddTree2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitPath(t *testing.T) {
|
func TestSplitPath(t *testing.T) {
|
||||||
a := splitPath("/")
|
a := splitPath("")
|
||||||
|
if len(a) != 0 {
|
||||||
|
t.Fatal("/ should retrun []")
|
||||||
|
}
|
||||||
|
a = splitPath("/")
|
||||||
if len(a) != 0 {
|
if len(a) != 0 {
|
||||||
t.Fatal("/ should retrun []")
|
t.Fatal("/ should retrun []")
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ import (
|
|||||||
// Instantiates a Paginator and assigns it to context.Input.Data["paginator"].
|
// Instantiates a Paginator and assigns it to context.Input.Data["paginator"].
|
||||||
func SetPaginator(context *context.Context, per int, nums int64) (paginator *Paginator) {
|
func SetPaginator(context *context.Context, per int, nums int64) (paginator *Paginator) {
|
||||||
paginator = NewPaginator(context.Request, per, nums)
|
paginator = NewPaginator(context.Request, per, nums)
|
||||||
context.Input.Data["paginator"] = paginator
|
context.Input.Data["paginator"] = &paginator
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ func (p *Paginator) Pages() []int {
|
|||||||
|
|
||||||
// Returns URL for a given page index.
|
// Returns URL for a given page index.
|
||||||
func (p *Paginator) PageLink(page int) string {
|
func (p *Paginator) PageLink(page int) string {
|
||||||
link, _ := url.ParseRequestURI(p.Request.RequestURI)
|
link, _ := url.ParseRequestURI(p.Request.URL.String())
|
||||||
values := link.Query()
|
values := link.Query()
|
||||||
if page == 1 {
|
if page == 1 {
|
||||||
values.Del("p")
|
values.Del("p")
|
||||||
|
Loading…
Reference in New Issue
Block a user