diff --git a/README.md b/README.md index 0d7414b8..7b650887 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://drone.io/github.com/astaxie/beego/status.png)](https://drone.io/github.com/astaxie/beego/latest) [![GoDoc](http://godoc.org/github.com/astaxie/beego?status.svg)](http://godoc.org/github.com/astaxie/beego) -beego is an open-source, high-performance, modularity, full-stack web framework. +beego is an open-source, high-performance, modular, full-stack web framework. More info [beego.me](http://beego.me) @@ -19,7 +19,7 @@ More info [beego.me](http://beego.me) * Auto API documents * Annotation router * Namespace -* Powerful develop tools +* Powerful development tools * Full stack for Web & API ## Documentation diff --git a/admin.go b/admin.go index a0905dd3..90142c55 100644 --- a/admin.go +++ b/admin.go @@ -113,8 +113,6 @@ func listConf(rw http.ResponseWriter, r *http.Request) { m["SessionName"] = SessionName m["SessionGCMaxLifetime"] = SessionGCMaxLifetime m["SessionSavePath"] = SessionSavePath - m["SessionHashFunc"] = SessionHashFunc - m["SessionHashKey"] = SessionHashKey m["SessionCookieLifeTime"] = SessionCookieLifeTime m["UseFcgi"] = UseFcgi m["MaxMemory"] = MaxMemory @@ -399,7 +397,7 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) { if err != nil { 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
%s", taskname, t.GetStatus())} } else { data["Message"] = []string{"warning", fmt.Sprintf("there's no task which named: %s", taskname)} } @@ -412,12 +410,14 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) { var fields = []string{ fmt.Sprintf("Task Name"), fmt.Sprintf("Task Spec"), - fmt.Sprintf("Task Function"), + fmt.Sprintf("Task Status"), + fmt.Sprintf("Last Time"), fmt.Sprintf(""), } for tname, tk := range toolbox.AdminTaskList { result = []string{ fmt.Sprintf("%s", tname), + fmt.Sprintf("%s", tk.GetSpec()), fmt.Sprintf("%s", tk.GetStatus()), fmt.Sprintf("%s", tk.GetPrev().String()), } @@ -458,7 +458,7 @@ func (admin *adminApp) Run() { for p, f := range admin.routers { http.Handle(p, f) } - BeeLogger.Info("Running on %s", addr) + BeeLogger.Info("Admin server Running on %s", addr) err := http.ListenAndServe(addr, nil) if err != nil { BeeLogger.Critical("Admin ListenAndServe: ", err) diff --git a/adminui.go b/adminui.go index 77b5cd33..7bb32b34 100644 --- a/adminui.go +++ b/adminui.go @@ -186,7 +186,7 @@ bg-warning {{end}} - Run + Run {{end}} diff --git a/app.go b/app.go index 0b89d89e..35040f33 100644 --- a/app.go +++ b/app.go @@ -19,14 +19,12 @@ import ( "net" "net/http" "net/http/fcgi" + "os" "time" - "github.com/astaxie/beego/context" + "github.com/astaxie/beego/utils" ) -// FilterFunc defines filter function type. -type FilterFunc func(*context.Context) - // App defines beego application with a new PatternServeMux. type App struct { Handlers *ControllerRegistor @@ -64,6 +62,10 @@ func (app *App) Run() { } } else { if HttpPort == 0 { + // remove the Socket file before start + if utils.FileExists(addr) { + os.Remove(addr) + } l, err = net.Listen("unix", addr) } else { l, err = net.Listen("tcp", addr) @@ -85,7 +87,7 @@ func (app *App) Run() { if HttpsPort != 0 { app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort) } - BeeLogger.Info("Running on %s", app.Server.Addr) + BeeLogger.Info("https server Running on %s", app.Server.Addr) err := app.Server.ListenAndServeTLS(HttpCertFile, HttpKeyFile) if err != nil { BeeLogger.Critical("ListenAndServeTLS: ", err) @@ -98,12 +100,29 @@ func (app *App) Run() { if EnableHttpListen { go func() { app.Server.Addr = addr - BeeLogger.Info("Running on %s", app.Server.Addr) - err := app.Server.ListenAndServe() - if err != nil { - BeeLogger.Critical("ListenAndServe: ", err) - time.Sleep(100 * time.Microsecond) - endRunning <- true + BeeLogger.Info("http server Running on %s", app.Server.Addr) + if ListenTCP4 && HttpAddr == "" { + ln, err := net.Listen("tcp4", app.Server.Addr) + if err != nil { + BeeLogger.Critical("ListenAndServe: ", err) + time.Sleep(100 * time.Microsecond) + endRunning <- true + return + } + err = app.Server.Serve(ln) + if err != nil { + BeeLogger.Critical("ListenAndServe: ", err) + time.Sleep(100 * time.Microsecond) + endRunning <- true + return + } + } else { + err := app.Server.ListenAndServe() + if err != nil { + BeeLogger.Critical("ListenAndServe: ", err) + time.Sleep(100 * time.Microsecond) + endRunning <- true + } } }() } diff --git a/beego.go b/beego.go index f23174c7..9c34c9f9 100644 --- a/beego.go +++ b/beego.go @@ -33,83 +33,15 @@ import ( "strconv" "strings" - "github.com/astaxie/beego/middleware" "github.com/astaxie/beego/session" ) // beego web framework version. -const VERSION = "1.4.1" +const VERSION = "1.4.3" type hookfunc func() error //hook function to run 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. // it's an alias method of App.Router. // usage: @@ -280,15 +212,6 @@ func Handler(rootpath string, h http.Handler, options ...interface{}) *App { 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. func SetViewsPath(path string) *App { ViewsPath = path @@ -383,8 +306,6 @@ func initBeforeHttpRun() { `"gclifetime":` + strconv.FormatInt(SessionGCMaxLifetime, 10) + `,` + `"providerConfig":"` + filepath.ToSlash(SessionSavePath) + `",` + `"secure":` + strconv.FormatBool(EnableHttpTLS) + `,` + - `"sessionIDHashFunc":"` + SessionHashFunc + `",` + - `"sessionIDHashKey":"` + SessionHashKey + `",` + `"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` + `"domain":"` + SessionDomain + `",` + `"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}` @@ -404,9 +325,7 @@ func initBeforeHttpRun() { } } - middleware.VERSION = VERSION - middleware.AppName = AppName - middleware.RegisterErrorHandler() + registerDefaultErrorHandler() if EnableDocs { Get("/docs", serverDocs) diff --git a/cache/cache_test.go b/cache/cache_test.go index bf9e79c2..7c43e539 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -15,6 +15,7 @@ package cache import ( + "os" "testing" "time" ) @@ -67,7 +68,7 @@ func TestCache(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 { t.Error("init err") } @@ -112,4 +113,5 @@ func TestFileCache(t *testing.T) { if v := bm.Get("astaxie"); v.(string) != "author" { t.Error("get err") } + os.RemoveAll("cache") } diff --git a/cache/file.go b/cache/file.go index 6ecf6568..bbbbbad2 100644 --- a/cache/file.go +++ b/cache/file.go @@ -92,8 +92,6 @@ func (fc *FileCache) StartAndGC(config string) error { // Init will make new dir for file cache if not exist. 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 _ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle } diff --git a/cache/redis/redis.go b/cache/redis/redis.go index 35cf88cd..0e07eaed 100644 --- a/cache/redis/redis.go +++ b/cache/redis/redis.go @@ -32,6 +32,7 @@ package redis import ( "encoding/json" "errors" + "strconv" "time" "github.com/garyburd/redigo/redis" @@ -48,6 +49,7 @@ var ( type RedisCache struct { p *redis.Pool // redis connection pool conninfo string + dbNum int key string } @@ -75,14 +77,13 @@ func (rc *RedisCache) Get(key string) interface{} { // put cache to redis. func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { var err error - if _, err = rc.do("SET", key, val); err != nil { + if _, err = rc.do("SETEX", key, timeout, val); err != nil { return err } if _, err = rc.do("HSET", rc.key, key, true); err != nil { return err } - _, err = rc.do("EXPIRE", key, timeout) return err } @@ -138,7 +139,7 @@ func (rc *RedisCache) ClearAll() error { } // 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, // so no gc operation. func (rc *RedisCache) StartAndGC(config string) error { @@ -152,9 +153,12 @@ func (rc *RedisCache) StartAndGC(config string) error { if _, ok := cf["conn"]; !ok { return errors.New("config has no conn key") } - + if _, ok := cf["dbNum"]; !ok { + cf["dbNum"] = "0" + } rc.key = cf["key"] rc.conninfo = cf["conn"] + rc.dbNum, _ = strconv.Atoi(cf["dbNum"]) rc.connectInit() c := rc.p.Get() @@ -167,6 +171,11 @@ func (rc *RedisCache) StartAndGC(config string) error { func (rc *RedisCache) connectInit() { dialFunc := func() (c redis.Conn, err error) { c, err = redis.Dial("tcp", rc.conninfo) + _, selecterr := c.Do("SELECT", rc.dbNum) + if selecterr != nil { + c.Close() + return nil, selecterr + } return } // initialize a new pool diff --git a/config.go b/config.go index 84f8cf39..f326ad22 100644 --- a/config.go +++ b/config.go @@ -40,6 +40,7 @@ var ( EnableHttpListen bool HttpAddr string HttpPort int + ListenTCP4 bool EnableHttpTLS bool HttpsPort int HttpCertFile string @@ -55,8 +56,6 @@ var ( SessionName string // the cookie name when saving session id into cookie. SessionGCMaxLifetime int64 // session gc time for auto cleaning expired session. SessionSavePath string // if use mysql/redis/file provider, define save path to connection info. - SessionHashFunc string // session hash generation func. - SessionHashKey string // session hash salt string. SessionCookieLifeTime int // the life time of session id in cookie. SessionAutoSetCookie bool // auto setcookie SessionDomain string // the cookie domain default is empty @@ -82,6 +81,7 @@ var ( AppConfigProvider string // config provider EnableDocs bool // enable generate docs & server docs API Swagger RouterCaseSensitive bool // router case sensitive default is true + AccessLogs bool // print access logs, default is false ) type beegoAppConfig struct { @@ -111,7 +111,7 @@ func (b *beegoAppConfig) String(key string) string { func (b *beegoAppConfig) Strings(key string) []string { v := b.innerConfig.Strings(RunMode + "::" + key) - if len(v) == 0 { + if v[0] == "" { return b.innerConfig.Strings(key) } return v @@ -236,8 +236,6 @@ func init() { SessionName = "beegosessionID" SessionGCMaxLifetime = 3600 SessionSavePath = "" - SessionHashFunc = "sha1" - SessionHashKey = "beegoserversessionkey" SessionCookieLifeTime = 0 //set cookie default is the brower life SessionAutoSetCookie = true @@ -277,9 +275,10 @@ func init() { if err != nil { fmt.Println("init console log error:", err) } + SetLogFuncCall(true) err = ParseConfig() - if err != nil && !os.IsNotExist(err) { + if err != nil && os.IsNotExist(err) { // for init if doesn't have app.conf will not panic ac := config.NewFakeConfig() AppConfig = &beegoAppConfig{ac} @@ -308,6 +307,10 @@ func ParseConfig() (err error) { HttpPort = v } + if v, err := AppConfig.Bool("ListenTCP4"); err == nil { + ListenTCP4 = v + } + if v, err := AppConfig.Bool("EnableHttpListen"); err == nil { EnableHttpListen = v } @@ -348,14 +351,6 @@ func ParseConfig() (err error) { SessionSavePath = sesssavepath } - if sesshashfunc := AppConfig.String("SessionHashFunc"); sesshashfunc != "" { - SessionHashFunc = sesshashfunc - } - - if sesshashkey := AppConfig.String("SessionHashKey"); sesshashkey != "" { - SessionHashKey = sesshashkey - } - if sessMaxLifeTime, err := AppConfig.Int64("SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 { SessionGCMaxLifetime = sessMaxLifeTime } diff --git a/config/json.go b/config/json.go index ae86ea53..e2b53793 100644 --- a/config/json.go +++ b/config/json.go @@ -17,13 +17,10 @@ package config import ( "encoding/json" "errors" - "fmt" "io/ioutil" "os" - "path" "strings" "sync" - "time" ) // 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 { return nil, err } + + return js.ParseData(content) +} + +// ParseData returns a ConfigContainer with json string +func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { x := &JsonConfigContainer{ data: make(map[string]interface{}), } - err = json.Unmarshal(content, &x.data) + err := json.Unmarshal(data, &x.data) if err != nil { var wrappingArray []interface{} - err2 := json.Unmarshal(content, &wrappingArray) + err2 := json.Unmarshal(data, &wrappingArray) if err2 != nil { return nil, err } @@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { 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. // Only when get value, support key as section:name type. type JsonConfigContainer struct { @@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) { // DefaultBool return the bool value if has no error // otherwise return the defaultval func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { - if v, err := c.Bool(key); err != nil { - return defaultval - } else { + if v, err := c.Bool(key); err == nil { return v } + return defaultval } // 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. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { - if v, err := c.Int(key); err != nil { - return defaultval - } else { + if v, err := c.Int(key); err == nil { return v } + return defaultval } // 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. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { - if v, err := c.Int64(key); err != nil { - return defaultval - } else { + if v, err := c.Int64(key); err == nil { return v } + return defaultval } // 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. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { - if v, err := c.Float(key); err != nil { - return defaultval - } else { + if v, err := c.Float(key); err == nil { return v } + return defaultval } // 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. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { - if v := c.String(key); v == "" { - return defaultval - } else { + // TODO FIXME should not use "" to replace non existance + if v := c.String(key); v != "" { return v } + return defaultval } // Strings returns the []string value for a given key. func (c *JsonConfigContainer) Strings(key string) []string { + stringVal := c.String(key) + if stringVal == "" { + return []string{} + } return strings.Split(c.String(key), ";") } // DefaultStrings returns the []string value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { - if v := c.Strings(key); len(v) == 0 { - return defaultval - } else { + if v := c.Strings(key); len(v) > 0 { return v } + return defaultval } // GetSection returns map for the given section func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { if v, ok := c.data[section]; ok { return v.(map[string]string), nil - } else { - return nil, errors.New("not exist setction") } + return nil, errors.New("nonexist section " + section) } // SaveConfigFile save the config into file @@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { return err } -// WriteValue writes a new value for key. +// Set writes a new value for key. func (c *JsonConfigContainer) Set(key, val string) error { c.Lock() defer c.Unlock() @@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { // section.key or key func (c *JsonConfigContainer) getData(key string) interface{} { - c.RLock() - defer c.RUnlock() if len(key) == 0 { return nil } - sectionKey := strings.Split(key, "::") - if len(sectionKey) >= 2 { - curValue, ok := c.data[sectionKey[0]] + + c.RLock() + defer c.RUnlock() + + sectionKeys := strings.Split(key, "::") + if len(sectionKeys) >= 2 { + curValue, ok := c.data[sectionKeys[0]] if !ok { return nil } - for _, key := range sectionKey[1:] { + for _, key := range sectionKeys[1:] { if v, ok := curValue.(map[string]interface{}); ok { if curValue, ok = v[key]; !ok { return nil diff --git a/config/json_test.go b/config/json_test.go index 409e2c12..5aedae36 100644 --- a/config/json_test.go +++ b/config/json_test.go @@ -21,6 +21,7 @@ import ( var jsoncontext = `{ "appname": "beeapi", +"testnames": "foo;bar", "httpport": 8080, "mysqlport": 3600, "PI": 3.1415976, @@ -28,8 +29,8 @@ var jsoncontext = `{ "autorender": false, "copyrequestbody": true, "database": { - "host": "host", - "port": "port", + "host": "host", + "port": "port", "database": "database", "username": "username", "password": "password", @@ -122,6 +123,12 @@ func TestJson(t *testing.T) { if jsonconf.String("runmode") != "dev" { t.Fatal("runmode not equal to dev") } + if v := jsonconf.Strings("unknown"); len(v) > 0 { + t.Fatal("unknown strings, the length should be 0") + } + if v := jsonconf.Strings("testnames"); len(v) != 2 { + t.Fatal("testnames length should be 2") + } if v, err := jsonconf.Bool("autorender"); err != nil || v != false { t.Error(v) t.Fatal(err) @@ -179,4 +186,8 @@ func TestJson(t *testing.T) { if _, err := jsonconf.Bool("unknown"); err == nil { t.Error("unknown keys should return an error when expecting a Bool") } + + if !jsonconf.DefaultBool("unknow", true) { + t.Error("unknown keys with default value wrong") + } } diff --git a/context/context.go b/context/context.go index d31076d4..f6aa85d6 100644 --- a/context/context.go +++ b/context/context.go @@ -31,7 +31,6 @@ import ( "strings" "time" - "github.com/astaxie/beego/middleware" "github.com/astaxie/beego/utils" ) @@ -53,22 +52,9 @@ func (ctx *Context) Redirect(status int, localurl string) { } // Abort stops this request. -// if middleware.ErrorMaps exists, panic body. -// if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string. +// if beego.ErrorMaps exists, panic body. func (ctx *Context) Abort(status int, body string) { ctx.ResponseWriter.WriteHeader(status) - // first panic from ErrorMaps, is is user defined error functions. - 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 panic(body) } @@ -154,8 +140,11 @@ func (ctx *Context) CheckXsrfCookie() bool { } if token == "" { 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") + return false } return true } diff --git a/context/input.go b/context/input.go index 6c662820..f535e6a2 100644 --- a/context/input.go +++ b/context/input.go @@ -27,7 +27,7 @@ import ( "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. type BeegoInput struct { CruSession session.SessionStore @@ -72,11 +72,11 @@ func (input *BeegoInput) Site() string { func (input *BeegoInput) Scheme() string { if 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. @@ -153,12 +153,12 @@ func (input *BeegoInput) IsSecure() bool { 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 { 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 { return strings.Contains(input.Header("Content-Type"), "multipart/form-data") } @@ -189,16 +189,24 @@ func (input *BeegoInput) Proxy() []string { return []string{} } +// Referer returns http referer header. +func (input *BeegoInput) Referer() string { + return input.Header("Referer") +} + // Refer returns http referer header. func (input *BeegoInput) Refer() string { - return input.Header("Referer") + return input.Referer() } // SubDomains returns sub domain string. // if aa.bb.domain.com, returns aa.bb . func (input *BeegoInput) SubDomains() string { parts := strings.Split(input.Host(), ".") - return strings.Join(parts[len(parts)-2:], ".") + if len(parts) >= 3 { + return strings.Join(parts[:len(parts)-2], ".") + } + return "" } // 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. +// if non-existed, return empty string. func (input *BeegoInput) Header(key string) string { 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. +// if non-existed, return empty string. func (input *BeegoInput) Session(key interface{}) interface{} { 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 { requestbody, _ := ioutil.ReadAll(input.Request.Body) input.Request.Body.Close() diff --git a/context/input_test.go b/context/input_test.go index ddd1a056..4566f6d6 100644 --- a/context/input_test.go +++ b/context/input_test.go @@ -70,3 +70,45 @@ func TestParse(t *testing.T) { } 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()) + } +} diff --git a/context/output.go b/context/output.go index 6298ee77..2141513d 100644 --- a/context/output.go +++ b/context/output.go @@ -188,7 +188,7 @@ func sanitizeValue(v string) string { // Json writes json to response body. // if coding is true, it converts utf-8 to \u0000 type. func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) error { - output.Header("Content-Type", "application/json;charset=UTF-8") + output.Header("Content-Type", "application/json; charset=utf-8") var content []byte var err error if hasIndent { @@ -209,7 +209,7 @@ func (output *BeegoOutput) Json(data interface{}, hasIndent bool, coding bool) e // Jsonp writes jsonp to response body. 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 err error if hasIndent { @@ -235,7 +235,7 @@ func (output *BeegoOutput) Jsonp(data interface{}, hasIndent bool) error { // Xml writes xml string to response body. func (output *BeegoOutput) Xml(data interface{}, hasIndent bool) error { - output.Header("Content-Type", "application/xml;charset=UTF-8") + output.Header("Content-Type", "application/xml; charset=utf-8") var content []byte var err error if hasIndent { diff --git a/controller.go b/controller.go index 72ba323b..e056f52d 100644 --- a/controller.go +++ b/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. func (c *Controller) Abort(code string) { status, err := strconv.Atoi(code) - if err == nil { - c.Ctx.Abort(status, code) - } else { - c.Ctx.Abort(200, code) + if err != nil { + status = 200 } + c.CustomAbort(status, code) } // CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body. func (c *Controller) CustomAbort(status int, body string) { - 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. @@ -289,7 +295,7 @@ func (c *Controller) StopRun() { // UrlFor does another controller handler in this request function. // it goes to this controller method if endpoint is not clear. -func (c *Controller) UrlFor(endpoint string, values ...string) string { +func (c *Controller) UrlFor(endpoint string, values ...interface{}) string { if len(endpoint) <= 0 { return "" } @@ -363,67 +369,144 @@ func (c *Controller) ParseForm(obj interface{}) error { return ParseForm(c.Input(), obj) } -// GetString returns the input value by key string. -func (c *Controller) GetString(key string) string { - return c.Ctx.Input.Query(key) +// GetString returns the input value by key string or the default value while it's present and input is blank +func (c *Controller) GetString(key string, def ...string) string { + 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. -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() if f == nil { - return []string{} + return defv } + vs := f[key] if len(vs) > 0 { return vs + } else { + return defv } - return []string{} } -// GetInt returns input as an int -func (c *Controller) GetInt(key string) (int, error) { - return strconv.Atoi(c.Ctx.Input.Query(key)) +// GetInt returns input as an int or the default value while it's present and input is blank +func (c *Controller) GetInt(key string, def ...int) (int, error) { + 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 -func (c *Controller) GetInt8(key string) (int8, error) { - i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 8) - i8 := int8(i64) +// GetInt8 return input as an int8 or the default value while it's present and input is blank +func (c *Controller) GetInt8(key string, def ...int8) (int8, error) { + var defv int8 + 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 -func (c *Controller) GetInt16(key string) (int16, error) { - i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 16) - i16 := int16(i64) +// GetInt16 returns input as an int16 or the default value while it's present and input is blank +func (c *Controller) GetInt16(key string, def ...int16) (int16, error) { + var defv int16 + 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 -func (c *Controller) GetInt32(key string) (int32, error) { - i64, err := strconv.ParseInt(c.Ctx.Input.Query(key), 10, 32) - i32 := int32(i64) +// GetInt32 returns input as an int32 or the default value while it's present and input is blank +func (c *Controller) GetInt32(key string, def ...int32) (int32, error) { + var defv int32 + 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. -func (c *Controller) GetInt64(key string) (int64, error) { - return strconv.ParseInt(c.Ctx.Input.Query(key), 10, 64) +// GetInt64 returns input value as int64 or the default value while it's present and input is blank. +func (c *Controller) GetInt64(key string, def ...int64) (int64, error) { + 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. -func (c *Controller) GetBool(key string) (bool, error) { - return strconv.ParseBool(c.Ctx.Input.Query(key)) +// GetBool returns input value as bool or the default value while it's present and input is blank. +func (c *Controller) GetBool(key string, def ...bool) (bool, error) { + 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. -func (c *Controller) GetFloat(key string) (float64, error) { - return strconv.ParseFloat(c.Ctx.Input.Query(key), 64) +// GetFloat returns input value as float64 or the default value while it's present and input is blank. +func (c *Controller) GetFloat(key string, def ...float64) (float64, error) { + 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. diff --git a/middleware/error.go b/error.go similarity index 51% rename from middleware/error.go rename to error.go index 3b7191e9..71be6916 100644 --- a/middleware/error.go +++ b/error.go @@ -12,20 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -package middleware +package beego import ( "fmt" "html/template" "net/http" + "reflect" "runtime" "strconv" + "strings" + + "github.com/astaxie/beego/context" + "github.com/astaxie/beego/utils" ) -var ( - AppName string - VERSION string +const ( + errorTypeHandler = iota + errorTypeController ) + var tpl = ` @@ -76,18 +82,18 @@ var tpl = ` ` // 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) data := make(map[string]string) data["AppError"] = AppName + ":" + fmt.Sprint(err) - data["RequestMethod"] = r.Method - data["RequestURL"] = r.RequestURI - data["RemoteAddr"] = r.RemoteAddr + data["RequestMethod"] = ctx.Input.Method() + data["RequestURL"] = ctx.Input.Uri() + data["RemoteAddr"] = ctx.Input.IP() data["Stack"] = Stack data["BeegoVersion"] = VERSION data["GoVersion"] = runtime.Version() - rw.WriteHeader(500) - t.Execute(rw, data) + ctx.Output.SetStatus(500) + t.Execute(ctx.ResponseWriter, data) } var errtpl = ` @@ -190,15 +196,68 @@ var errtpl = ` ` +type errorInfo struct { + controllerType reflect.Type + handler http.HandlerFunc + method string + errorType int +} + // map of http handlers for each error string. -var ErrorMaps map[string]http.HandlerFunc +var ErrorMaps map[string]*errorInfo 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("
The page you have requested can't be authorized." + + "
Perhaps you are here because:" + + "

") + 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("
The page you have requested Payment Required." + + "
Perhaps you are here because:" + + "

") + 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("
The page you have requested is forbidden." + + "
Perhaps you are here because:" + + "

") + data["BeegoVersion"] = VERSION + t.Execute(rw, data) } // 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) data := make(map[string]interface{}) data["Title"] = "Page Not Found" @@ -211,45 +270,66 @@ func NotFound(rw http.ResponseWriter, r *http.Request) { "
You like 404 pages" + "") data["BeegoVersion"] = VERSION - //rw.WriteHeader(http.StatusNotFound) t.Execute(rw, data) } -// show 401 unauthorized error. -func Unauthorized(rw http.ResponseWriter, r *http.Request) { +// show 405 Method Not Allowed +func methodNotAllowed(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) - data["Title"] = "Unauthorized" - data["Content"] = template.HTML("
The page you have requested can't be authorized." + + data["Title"] = "Method Not Allowed" + data["Content"] = template.HTML("
The method you have requested Not Allowed." + "
Perhaps you are here because:" + "

") data["BeegoVersion"] = VERSION - //rw.WriteHeader(http.StatusUnauthorized) t.Execute(rw, data) } -// show 403 forbidden error. -func Forbidden(rw http.ResponseWriter, r *http.Request) { +// show 500 internal server error. +func internalServerError(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) - data["Title"] = "Forbidden" - data["Content"] = template.HTML("
The page you have requested is forbidden." + - "
Perhaps you are here because:" + + data["Title"] = "Internal Server Error" + data["Content"] = template.HTML("
The page you have requested is down right now." + "

") + "
Please try again later and report the error to the website administrator" + + "
") + data["BeegoVersion"] = VERSION + 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("
The page you have requested is Not Implemented." + + "

") + 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("
The page you have requested is down right now." + + "

") data["BeegoVersion"] = VERSION - //rw.WriteHeader(http.StatusForbidden) t.Execute(rw, data) } // 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) data := make(map[string]interface{}) data["Title"] = "Service Unavailable" @@ -260,80 +340,151 @@ func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { "
Please try again later." + "") data["BeegoVersion"] = VERSION - //rw.WriteHeader(http.StatusServiceUnavailable) t.Execute(rw, data) } -// show 500 internal server error. -func InternalServerError(rw http.ResponseWriter, r *http.Request) { +// show 504 Gateway Timeout. +func gatewayTimeout(rw http.ResponseWriter, r *http.Request) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := make(map[string]interface{}) - data["Title"] = "Internal Server Error" - data["Content"] = template.HTML("
The page you have requested is down right now." + + data["Title"] = "Gateway Timeout" + data["Content"] = template.HTML("
The page you have requested is unavailable." + + "
Perhaps you are here because:" + "

") + "

The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI." + + "
Please try again later." + + "") data["BeegoVersion"] = VERSION - //rw.WriteHeader(http.StatusInternalServerError) 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. -func RegisterErrorHandler() { - if _, ok := ErrorMaps["404"]; !ok { - ErrorMaps["404"] = NotFound +func registerDefaultErrorHandler() { + if _, ok := ErrorMaps["401"]; !ok { + Errorhandler("401", unauthorized) } - if _, ok := ErrorMaps["401"]; !ok { - ErrorMaps["401"] = Unauthorized + if _, ok := ErrorMaps["402"]; !ok { + Errorhandler("402", paymentRequired) } if _, ok := ErrorMaps["403"]; !ok { - ErrorMaps["403"] = Forbidden + Errorhandler("403", forbidden) } - if _, ok := ErrorMaps["503"]; !ok { - ErrorMaps["503"] = ServiceUnavailable + if _, ok := ErrorMaps["404"]; !ok { + Errorhandler("404", notFound) + } + + if _, ok := ErrorMaps["405"]; !ok { + Errorhandler("405", methodNotAllowed) } 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. // 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 { - isint, err := strconv.Atoi(errcode) - if err != nil { - isint = 500 - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.WriteHeader(isint) - h(w, r) + executeError(h, ctx) + return + } else if h, ok := ErrorMaps["503"]; ok { + executeError(h, ctx) return } else { - isint, err := strconv.Atoi(errcode) - if err != nil { - isint = 500 - } - if isint == 400 { - msg = "404 page not found" - } - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.WriteHeader(isint) - fmt.Fprintln(w, msg) - return + ctx.WriteString(errcode) + } +} + +func executeError(err *errorInfo, ctx *context.Context) { + if err.errorType == errorTypeHandler { + err.handler(ctx.ResponseWriter, ctx.Request) + return + } + if err.errorType == errorTypeController { + //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() } } diff --git a/example/beeapi/controllers/default.go b/example/beeapi/controllers/default.go index c6e53e74..a2184075 100644 --- a/example/beeapi/controllers/default.go +++ b/example/beeapi/controllers/default.go @@ -17,47 +17,47 @@ type ObjectController struct { beego.Controller } -func (this *ObjectController) Post() { +func (o *ObjectController) Post() { var ob models.Object - json.Unmarshal(this.Ctx.Input.RequestBody, &ob) + json.Unmarshal(o.Ctx.Input.RequestBody, &ob) objectid := models.AddOne(ob) - this.Data["json"] = map[string]string{"ObjectId": objectid} - this.ServeJson() + o.Data["json"] = map[string]string{"ObjectId": objectid} + o.ServeJson() } -func (this *ObjectController) Get() { - objectId := this.Ctx.Input.Params[":objectId"] +func (o *ObjectController) Get() { + objectId := o.Ctx.Input.Params[":objectId"] if objectId != "" { ob, err := models.GetOne(objectId) if err != nil { - this.Data["json"] = err + o.Data["json"] = err } else { - this.Data["json"] = ob + o.Data["json"] = ob } } else { obs := models.GetAll() - this.Data["json"] = obs + o.Data["json"] = obs } - this.ServeJson() + o.ServeJson() } -func (this *ObjectController) Put() { - objectId := this.Ctx.Input.Params[":objectId"] +func (o *ObjectController) Put() { + objectId := o.Ctx.Input.Params[":objectId"] var ob models.Object - json.Unmarshal(this.Ctx.Input.RequestBody, &ob) + json.Unmarshal(o.Ctx.Input.RequestBody, &ob) err := models.Update(objectId, ob.Score) if err != nil { - this.Data["json"] = err + o.Data["json"] = err } else { - this.Data["json"] = "update success!" + o.Data["json"] = "update success!" } - this.ServeJson() + o.ServeJson() } -func (this *ObjectController) Delete() { - objectId := this.Ctx.Input.Params[":objectId"] +func (o *ObjectController) Delete() { + objectId := o.Ctx.Input.Params[":objectId"] models.Delete(objectId) - this.Data["json"] = "delete success!" - this.ServeJson() + o.Data["json"] = "delete success!" + o.ServeJson() } diff --git a/example/chat/controllers/default.go b/example/chat/controllers/default.go index 370e6db1..95ef8a9b 100644 --- a/example/chat/controllers/default.go +++ b/example/chat/controllers/default.go @@ -14,7 +14,7 @@ type MainController struct { beego.Controller } -func (this *MainController) Get() { - this.Data["host"] = this.Ctx.Request.Host - this.TplNames = "index.tpl" +func (m *MainController) Get() { + m.Data["host"] = m.Ctx.Request.Host + m.TplNames = "index.tpl" } diff --git a/example/chat/controllers/ws.go b/example/chat/controllers/ws.go index 862f89c9..fc3917b3 100644 --- a/example/chat/controllers/ws.go +++ b/example/chat/controllers/ws.go @@ -150,14 +150,14 @@ type WSController struct { } var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, + ReadBufferSize: 1024, + WriteBufferSize: 1024, } -func (this *WSController) Get() { - ws, err := upgrader.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request,nil) +func (w *WSController) Get() { + ws, err := upgrader.Upgrade(w.Ctx.ResponseWriter, w.Ctx.Request, nil) if _, ok := err.(websocket.HandshakeError); ok { - http.Error(this.Ctx.ResponseWriter, "Not a websocket handshake", 400) + http.Error(w.Ctx.ResponseWriter, "Not a websocket handshake", 400) return } else if err != nil { return diff --git a/example/chat/views/index.tpl b/example/chat/views/index.tpl index 75bffa62..3a9d8838 100644 --- a/example/chat/views/index.tpl +++ b/example/chat/views/index.tpl @@ -2,7 +2,7 @@ Chat Example - +