Merge branch 'astaxie-master'
Showing
159 changed files
with
2487 additions
and
919 deletions
.go_style
0 → 100644
| ... | @@ -2,9 +2,7 @@ | ... | @@ -2,9 +2,7 @@ |
| 2 | 2 | ||
| 3 | [](https://drone.io/github.com/astaxie/beego/latest) | 3 | [](https://drone.io/github.com/astaxie/beego/latest) |
| 4 | 4 | ||
| 5 | beego is a Go Framework inspired by tornado and sinatra. | 5 | beego is an open-source, high-performance, modularity, full-stack web framework. |
| 6 | |||
| 7 | It is a simple & powerful web framework. | ||
| 8 | 6 | ||
| 9 | More info [beego.me](http://beego.me) | 7 | More info [beego.me](http://beego.me) |
| 10 | 8 | ||
| ... | @@ -12,20 +10,18 @@ More info [beego.me](http://beego.me) | ... | @@ -12,20 +10,18 @@ More info [beego.me](http://beego.me) |
| 12 | 10 | ||
| 13 | * RESTful support | 11 | * RESTful support |
| 14 | * MVC architecture | 12 | * MVC architecture |
| 15 | * Session support (store in memory, file, Redis or MySQL) | 13 | * modularity |
| 16 | * Cache support (store in memory, Redis or Memcache) | 14 | * auto API documents |
| 17 | * Global Config | 15 | * annotation router |
| 18 | * Intelligent routing | 16 | * namespace |
| 19 | * Thread-safe map | 17 | * powerful develop tools |
| 20 | * Friendly displaying of errors | 18 | * full stack for web & API |
| 21 | * Useful template functions | ||
| 22 | |||
| 23 | 19 | ||
| 24 | ## Documentation | 20 | ## Documentation |
| 25 | 21 | ||
| 26 | [English](http://beego.me/docs/intro/) | 22 | [English](http://beego.me/docs/intro/) |
| 27 | 23 | ||
| 28 | [API](http://gowalker.org/github.com/astaxie/beego) | 24 | [API](http://godoc.org/github.com/astaxie/beego) |
| 29 | 25 | ||
| 30 | [中文文档](http://beego.me/docs/intro/) | 26 | [中文文档](http://beego.me/docs/intro/) |
| 31 | 27 | ||
| ... | @@ -33,7 +29,4 @@ More info [beego.me](http://beego.me) | ... | @@ -33,7 +29,4 @@ More info [beego.me](http://beego.me) |
| 33 | ## LICENSE | 29 | ## LICENSE |
| 34 | 30 | ||
| 35 | beego is licensed under the Apache Licence, Version 2.0 | 31 | beego is licensed under the Apache Licence, Version 2.0 |
| 36 | (http://www.apache.org/licenses/LICENSE-2.0.html). | ||
| 37 | |||
| 38 | [][koding] | ||
| 39 | [koding]: https://koding.com/Teamwork?import=https://github.com/astaxie/beego/archive/master.zip&c=git1 | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 32 | (http://www.apache.org/licenses/LICENSE-2.0.html). | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
This diff is collapsed.
Click to expand it.
adminui.go
0 → 100644
This diff is collapsed.
Click to expand it.
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ||
| ... | @@ -66,6 +74,7 @@ func (app *App) Run() { | ... | @@ -66,6 +74,7 @@ func (app *App) Run() { |
| 66 | 74 | ||
| 67 | if EnableHttpTLS { | 75 | if EnableHttpTLS { |
| 68 | go func() { | 76 | go func() { |
| 77 | time.Sleep(20 * time.Microsecond) | ||
| 69 | if HttpsPort != 0 { | 78 | if HttpsPort != 0 { |
| 70 | app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort) | 79 | app.Server.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort) |
| 71 | } | 80 | } |
| ... | @@ -80,6 +89,7 @@ func (app *App) Run() { | ... | @@ -80,6 +89,7 @@ func (app *App) Run() { |
| 80 | 89 | ||
| 81 | if EnableHttpListen { | 90 | if EnableHttpListen { |
| 82 | go func() { | 91 | go func() { |
| 92 | app.Server.Addr = addr | ||
| 83 | err := app.Server.ListenAndServe() | 93 | err := app.Server.ListenAndServe() |
| 84 | if err != nil { | 94 | if err != nil { |
| 85 | BeeLogger.Critical("ListenAndServe: ", err) | 95 | BeeLogger.Critical("ListenAndServe: ", err) | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 15 | // beego is an open-source, high-performance, modularity, full-stack web framework | ||
| 16 | // | ||
| 17 | // package main | ||
| 18 | // | ||
| 19 | // import "github.com/astaxie/beego" | ||
| 20 | // | ||
| 21 | // func main() { | ||
| 22 | // beego.Run() | ||
| 23 | // } | ||
| 24 | // | ||
| 25 | // more infomation: http://beego.me | ||
| 7 | package beego | 26 | package beego |
| 8 | 27 | ||
| 9 | import ( | 28 | import ( |
| ... | @@ -19,7 +38,7 @@ import ( | ... | @@ -19,7 +38,7 @@ import ( |
| 19 | ) | 38 | ) |
| 20 | 39 | ||
| 21 | // beego web framework version. | 40 | // beego web framework version. |
| 22 | const VERSION = "1.3.1" | 41 | const VERSION = "1.4.0" |
| 23 | 42 | ||
| 24 | type hookfunc func() error //hook function to run | 43 | type hookfunc func() error //hook function to run |
| 25 | var hooks []hookfunc //hook function slice to store the hookfunc | 44 | var hooks []hookfunc //hook function slice to store the hookfunc |
| ... | @@ -359,6 +378,7 @@ func initBeforeHttpRun() { | ... | @@ -359,6 +378,7 @@ func initBeforeHttpRun() { |
| 359 | `"sessionIDHashFunc":"` + SessionHashFunc + `",` + | 378 | `"sessionIDHashFunc":"` + SessionHashFunc + `",` + |
| 360 | `"sessionIDHashKey":"` + SessionHashKey + `",` + | 379 | `"sessionIDHashKey":"` + SessionHashKey + `",` + |
| 361 | `"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` + | 380 | `"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` + |
| 381 | `"domain":"` + SessionDomain + `",` + | ||
| 362 | `"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}` | 382 | `"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}` |
| 363 | } | 383 | } |
| 364 | GlobalSessions, err = session.NewManager(SessionProvider, | 384 | GlobalSessions, err = session.NewManager(SessionProvider, |
| ... | @@ -380,14 +400,13 @@ func initBeforeHttpRun() { | ... | @@ -380,14 +400,13 @@ func initBeforeHttpRun() { |
| 380 | middleware.AppName = AppName | 400 | middleware.AppName = AppName |
| 381 | middleware.RegisterErrorHandler() | 401 | middleware.RegisterErrorHandler() |
| 382 | 402 | ||
| 383 | for u, _ := range StaticDir { | ||
| 384 | Get(u, serverStaticRouter) | ||
| 385 | Get(u+"/*", serverStaticRouter) | ||
| 386 | } | ||
| 387 | if EnableDocs { | 403 | if EnableDocs { |
| 388 | Get("/docs", serverDocs) | 404 | Get("/docs", serverDocs) |
| 389 | Get("/docs/*", serverDocs) | 405 | Get("/docs/*", serverDocs) |
| 390 | } | 406 | } |
| 407 | |||
| 408 | //init mime | ||
| 409 | AddAPPStartHook(initMime) | ||
| 391 | } | 410 | } |
| 392 | 411 | ||
| 393 | // this function is for test package init | 412 | // this function is for test package init |
| ... | @@ -406,6 +425,4 @@ func TestBeegoInit(apppath string) { | ... | @@ -406,6 +425,4 @@ func TestBeegoInit(apppath string) { |
| 406 | 425 | ||
| 407 | func init() { | 426 | func init() { |
| 408 | hooks = make([]hookfunc, 0) | 427 | hooks = make([]hookfunc, 0) |
| 409 | //init mime | ||
| 410 | AddAPPStartHook(initMime) | ||
| 411 | } | 428 | } | ... | ... |
| ... | @@ -22,7 +22,7 @@ First you must import it | ... | @@ -22,7 +22,7 @@ First you must import it |
| 22 | 22 | ||
| 23 | Then init a Cache (example with memory adapter) | 23 | Then init a Cache (example with memory adapter) |
| 24 | 24 | ||
| 25 | bm, err := NewCache("memory", `{"interval":60}`) | 25 | bm, err := cache.NewCache("memory", `{"interval":60}`) |
| 26 | 26 | ||
| 27 | Use it like this: | 27 | Use it like this: |
| 28 | 28 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 15 | // Usage: | ||
| 16 | // | ||
| 17 | // import( | ||
| 18 | // "github.com/astaxie/beego/cache" | ||
| 19 | // ) | ||
| 20 | // | ||
| 21 | // bm, err := cache.NewCache("memory", `{"interval":60}`) | ||
| 22 | // | ||
| 23 | // Use it like this: | ||
| 24 | // | ||
| 25 | // bm.Put("astaxie", 1, 10) | ||
| 26 | // bm.Get("astaxie") | ||
| 27 | // bm.IsExist("astaxie") | ||
| 28 | // bm.Delete("astaxie") | ||
| 29 | // | ||
| 30 | // more docs http://beego.me/docs/module/cache.md | ||
| 7 | package cache | 31 | package cache |
| 8 | 32 | ||
| 9 | import ( | 33 | import ( |
| ... | @@ -13,7 +37,7 @@ import ( | ... | @@ -13,7 +37,7 @@ import ( |
| 13 | // Cache interface contains all behaviors for cache adapter. | 37 | // Cache interface contains all behaviors for cache adapter. |
| 14 | // usage: | 38 | // usage: |
| 15 | // cache.Register("file",cache.NewFileCache()) // this operation is run in init method of file.go. | 39 | // cache.Register("file",cache.NewFileCache()) // this operation is run in init method of file.go. |
| 16 | // c := cache.NewCache("file","{....}") | 40 | // c,err := cache.NewCache("file","{....}") |
| 17 | // c.Put("key",value,3600) | 41 | // c.Put("key",value,3600) |
| 18 | // v := c.Get("key") | 42 | // v := c.Get("key") |
| 19 | // | 43 | // |
| ... | @@ -31,11 +55,11 @@ type Cache interface { | ... | @@ -31,11 +55,11 @@ type Cache interface { |
| 31 | Incr(key string) error | 55 | Incr(key string) error |
| 32 | // decrease cached int value by key, as a counter. | 56 | // decrease cached int value by key, as a counter. |
| 33 | Decr(key string) error | 57 | Decr(key string) error |
| 34 | // check cached value is existed or not. | 58 | // check if cached value exists or not. |
| 35 | IsExist(key string) bool | 59 | IsExist(key string) bool |
| 36 | // clear all cache. | 60 | // clear all cache. |
| 37 | ClearAll() error | 61 | ClearAll() error |
| 38 | // start gc routine via config string setting. | 62 | // start gc routine based on config string settings. |
| 39 | StartAndGC(config string) error | 63 | StartAndGC(config string) error |
| 40 | } | 64 | } |
| 41 | 65 | ||
| ... | @@ -48,23 +72,24 @@ func Register(name string, adapter Cache) { | ... | @@ -48,23 +72,24 @@ func Register(name string, adapter Cache) { |
| 48 | if adapter == nil { | 72 | if adapter == nil { |
| 49 | panic("cache: Register adapter is nil") | 73 | panic("cache: Register adapter is nil") |
| 50 | } | 74 | } |
| 51 | if _, dup := adapters[name]; dup { | 75 | if _, ok := adapters[name]; ok { |
| 52 | panic("cache: Register called twice for adapter " + name) | 76 | panic("cache: Register called twice for adapter " + name) |
| 53 | } | 77 | } |
| 54 | adapters[name] = adapter | 78 | adapters[name] = adapter |
| 55 | } | 79 | } |
| 56 | 80 | ||
| 57 | // Create a new cache driver by adapter and config string. | 81 | // Create a new cache driver by adapter name and config string. |
| 58 | // config need to be correct JSON as string: {"interval":360}. | 82 | // config need to be correct JSON as string: {"interval":360}. |
| 59 | // it will start gc automatically. | 83 | // it will start gc automatically. |
| 60 | func NewCache(adapterName, config string) (Cache, error) { | 84 | func NewCache(adapterName, config string) (adapter Cache, e error) { |
| 61 | adapter, ok := adapters[adapterName] | 85 | adapter, ok := adapters[adapterName] |
| 62 | if !ok { | 86 | if !ok { |
| 63 | return nil, fmt.Errorf("cache: unknown adaptername %q (forgotten import?)", adapterName) | 87 | e = fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName) |
| 88 | return | ||
| 64 | } | 89 | } |
| 65 | err := adapter.StartAndGC(config) | 90 | err := adapter.StartAndGC(config) |
| 66 | if err != nil { | 91 | if err != nil { |
| 67 | return nil, err | 92 | adapter = nil |
| 68 | } | 93 | } |
| 69 | return adapter, nil | 94 | return |
| 70 | } | 95 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package cache | 15 | package cache |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package cache | 15 | package cache |
| 8 | 16 | ||
| ... | @@ -19,12 +27,11 @@ func GetString(v interface{}) string { | ... | @@ -19,12 +27,11 @@ func GetString(v interface{}) string { |
| 19 | case []byte: | 27 | case []byte: |
| 20 | return string(result) | 28 | return string(result) |
| 21 | default: | 29 | default: |
| 22 | if v == nil { | 30 | if v != nil { |
| 23 | return "" | ||
| 24 | } else { | ||
| 25 | return fmt.Sprintf("%v", result) | 31 | return fmt.Sprintf("%v", result) |
| 26 | } | 32 | } |
| 27 | } | 33 | } |
| 34 | return "" | ||
| 28 | } | 35 | } |
| 29 | 36 | ||
| 30 | // convert interface to int. | 37 | // convert interface to int. |
| ... | @@ -37,12 +44,9 @@ func GetInt(v interface{}) int { | ... | @@ -37,12 +44,9 @@ func GetInt(v interface{}) int { |
| 37 | case int64: | 44 | case int64: |
| 38 | return int(result) | 45 | return int(result) |
| 39 | default: | 46 | default: |
| 40 | d := GetString(v) | 47 | if d := GetString(v); d != "" { |
| 41 | if d != "" { | 48 | value, _ := strconv.Atoi(d) |
| 42 | value, err := strconv.Atoi(d) | 49 | return value |
| 43 | if err == nil { | ||
| 44 | return value | ||
| 45 | } | ||
| 46 | } | 50 | } |
| 47 | } | 51 | } |
| 48 | return 0 | 52 | return 0 |
| ... | @@ -58,12 +62,10 @@ func GetInt64(v interface{}) int64 { | ... | @@ -58,12 +62,10 @@ func GetInt64(v interface{}) int64 { |
| 58 | case int64: | 62 | case int64: |
| 59 | return result | 63 | return result |
| 60 | default: | 64 | default: |
| 61 | d := GetString(v) | 65 | |
| 62 | if d != "" { | 66 | if d := GetString(v); d != "" { |
| 63 | result, err := strconv.ParseInt(d, 10, 64) | 67 | value, _ := strconv.ParseInt(d, 10, 64) |
| 64 | if err == nil { | 68 | return value |
| 65 | return result | ||
| 66 | } | ||
| 67 | } | 69 | } |
| 68 | } | 70 | } |
| 69 | return 0 | 71 | return 0 |
| ... | @@ -75,12 +77,9 @@ func GetFloat64(v interface{}) float64 { | ... | @@ -75,12 +77,9 @@ func GetFloat64(v interface{}) float64 { |
| 75 | case float64: | 77 | case float64: |
| 76 | return result | 78 | return result |
| 77 | default: | 79 | default: |
| 78 | d := GetString(v) | 80 | if d := GetString(v); d != "" { |
| 79 | if d != "" { | 81 | value, _ := strconv.ParseFloat(d, 64) |
| 80 | value, err := strconv.ParseFloat(d, 64) | 82 | return value |
| 81 | if err == nil { | ||
| 82 | return value | ||
| 83 | } | ||
| 84 | } | 83 | } |
| 85 | } | 84 | } |
| 86 | return 0 | 85 | return 0 |
| ... | @@ -92,12 +91,9 @@ func GetBool(v interface{}) bool { | ... | @@ -92,12 +91,9 @@ func GetBool(v interface{}) bool { |
| 92 | case bool: | 91 | case bool: |
| 93 | return result | 92 | return result |
| 94 | default: | 93 | default: |
| 95 | d := GetString(v) | 94 | if d := GetString(v); d != "" { |
| 96 | if d != "" { | 95 | value, _ := strconv.ParseBool(d) |
| 97 | result, err := strconv.ParseBool(d) | 96 | return value |
| 98 | if err == nil { | ||
| 99 | return result | ||
| 100 | } | ||
| 101 | } | 97 | } |
| 102 | } | 98 | } |
| 103 | return false | 99 | return false | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package cache | 15 | package cache |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package cache | 15 | package cache |
| 8 | 16 | ||
| ... | @@ -57,12 +65,10 @@ func NewFileCache() *FileCache { | ... | @@ -57,12 +65,10 @@ func NewFileCache() *FileCache { |
| 57 | 65 | ||
| 58 | // Start and begin gc for file cache. | 66 | // Start and begin gc for file cache. |
| 59 | // the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0} | 67 | // the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0} |
| 60 | func (this *FileCache) StartAndGC(config string) error { | 68 | func (fc *FileCache) StartAndGC(config string) error { |
| 61 | 69 | ||
| 62 | var cfg map[string]string | 70 | var cfg map[string]string |
| 63 | json.Unmarshal([]byte(config), &cfg) | 71 | json.Unmarshal([]byte(config), &cfg) |
| 64 | //fmt.Println(cfg) | ||
| 65 | //fmt.Println(config) | ||
| 66 | if _, ok := cfg["CachePath"]; !ok { | 72 | if _, ok := cfg["CachePath"]; !ok { |
| 67 | cfg["CachePath"] = FileCachePath | 73 | cfg["CachePath"] = FileCachePath |
| 68 | } | 74 | } |
| ... | @@ -75,69 +81,53 @@ func (this *FileCache) StartAndGC(config string) error { | ... | @@ -75,69 +81,53 @@ func (this *FileCache) StartAndGC(config string) error { |
| 75 | if _, ok := cfg["EmbedExpiry"]; !ok { | 81 | if _, ok := cfg["EmbedExpiry"]; !ok { |
| 76 | cfg["EmbedExpiry"] = strconv.FormatInt(FileCacheEmbedExpiry, 10) | 82 | cfg["EmbedExpiry"] = strconv.FormatInt(FileCacheEmbedExpiry, 10) |
| 77 | } | 83 | } |
| 78 | this.CachePath = cfg["CachePath"] | 84 | fc.CachePath = cfg["CachePath"] |
| 79 | this.FileSuffix = cfg["FileSuffix"] | 85 | fc.FileSuffix = cfg["FileSuffix"] |
| 80 | this.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"]) | 86 | fc.DirectoryLevel, _ = strconv.Atoi(cfg["DirectoryLevel"]) |
| 81 | this.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"]) | 87 | fc.EmbedExpiry, _ = strconv.Atoi(cfg["EmbedExpiry"]) |
| 82 | 88 | ||
| 83 | this.Init() | 89 | fc.Init() |
| 84 | return nil | 90 | return nil |
| 85 | } | 91 | } |
| 86 | 92 | ||
| 87 | // Init will make new dir for file cache if not exist. | 93 | // Init will make new dir for file cache if not exist. |
| 88 | func (this *FileCache) Init() { | 94 | func (fc *FileCache) Init() { |
| 89 | app := filepath.Dir(os.Args[0]) | 95 | app := filepath.Dir(os.Args[0]) |
| 90 | this.CachePath = filepath.Join(app, this.CachePath) | 96 | fc.CachePath = filepath.Join(app, fc.CachePath) |
| 91 | ok, err := exists(this.CachePath) | 97 | if ok, _ := exists(fc.CachePath); !ok { // todo : error handle |
| 92 | if err != nil { // print error | 98 | _ = os.MkdirAll(fc.CachePath, os.ModePerm) // todo : error handle |
| 93 | //fmt.Println(err) | ||
| 94 | } | 99 | } |
| 95 | if !ok { | ||
| 96 | if err = os.Mkdir(this.CachePath, os.ModePerm); err != nil { | ||
| 97 | //fmt.Println(err); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | //fmt.Println(this.getCacheFileName("123456")); | ||
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | // get cached file name. it's md5 encoded. | 102 | // get cached file name. it's md5 encoded. |
| 104 | func (this *FileCache) getCacheFileName(key string) string { | 103 | func (fc *FileCache) getCacheFileName(key string) string { |
| 105 | m := md5.New() | 104 | m := md5.New() |
| 106 | io.WriteString(m, key) | 105 | io.WriteString(m, key) |
| 107 | keyMd5 := hex.EncodeToString(m.Sum(nil)) | 106 | keyMd5 := hex.EncodeToString(m.Sum(nil)) |
| 108 | cachePath := this.CachePath | 107 | cachePath := fc.CachePath |
| 109 | //fmt.Println("cachepath : " , cachePath) | 108 | switch fc.DirectoryLevel { |
| 110 | //fmt.Println("md5" , keyMd5); | ||
| 111 | switch this.DirectoryLevel { | ||
| 112 | case 2: | 109 | case 2: |
| 113 | cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4]) | 110 | cachePath = filepath.Join(cachePath, keyMd5[0:2], keyMd5[2:4]) |
| 114 | case 1: | 111 | case 1: |
| 115 | cachePath = filepath.Join(cachePath, keyMd5[0:2]) | 112 | cachePath = filepath.Join(cachePath, keyMd5[0:2]) |
| 116 | } | 113 | } |
| 117 | 114 | ||
| 118 | ok, err := exists(cachePath) | 115 | if ok, _ := exists(cachePath); !ok { // todo : error handle |
| 119 | if err != nil { | 116 | _ = os.MkdirAll(cachePath, os.ModePerm) // todo : error handle |
| 120 | //fmt.Println(err) | ||
| 121 | } | 117 | } |
| 122 | if !ok { | 118 | |
| 123 | if err = os.MkdirAll(cachePath, os.ModePerm); err != nil { | 119 | return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, fc.FileSuffix)) |
| 124 | //fmt.Println(err); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, this.FileSuffix)) | ||
| 128 | } | 120 | } |
| 129 | 121 | ||
| 130 | // Get value from file cache. | 122 | // Get value from file cache. |
| 131 | // if non-exist or expired, return empty string. | 123 | // if non-exist or expired, return empty string. |
| 132 | func (this *FileCache) Get(key string) interface{} { | 124 | func (fc *FileCache) Get(key string) interface{} { |
| 133 | filename := this.getCacheFileName(key) | 125 | fileData, err := File_get_contents(fc.getCacheFileName(key)) |
| 134 | filedata, err := File_get_contents(filename) | ||
| 135 | //fmt.Println("get length:" , len(filedata)); | ||
| 136 | if err != nil { | 126 | if err != nil { |
| 137 | return "" | 127 | return "" |
| 138 | } | 128 | } |
| 139 | var to FileCacheItem | 129 | var to FileCacheItem |
| 140 | Gob_decode(filedata, &to) | 130 | Gob_decode(fileData, &to) |
| 141 | if to.Expired < time.Now().Unix() { | 131 | if to.Expired < time.Now().Unix() { |
| 142 | return "" | 132 | return "" |
| 143 | } | 133 | } |
| ... | @@ -147,12 +137,10 @@ func (this *FileCache) Get(key string) interface{} { | ... | @@ -147,12 +137,10 @@ func (this *FileCache) Get(key string) interface{} { |
| 147 | // Put value into file cache. | 137 | // Put value into file cache. |
| 148 | // timeout means how long to keep this file, unit of ms. | 138 | // timeout means how long to keep this file, unit of ms. |
| 149 | // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever. | 139 | // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever. |
| 150 | func (this *FileCache) Put(key string, val interface{}, timeout int64) error { | 140 | func (fc *FileCache) Put(key string, val interface{}, timeout int64) error { |
| 151 | gob.Register(val) | 141 | gob.Register(val) |
| 152 | 142 | ||
| 153 | filename := this.getCacheFileName(key) | 143 | item := FileCacheItem{Data: val} |
| 154 | var item FileCacheItem | ||
| 155 | item.Data = val | ||
| 156 | if timeout == FileCacheEmbedExpiry { | 144 | if timeout == FileCacheEmbedExpiry { |
| 157 | item.Expired = time.Now().Unix() + (86400 * 365 * 10) // ten years | 145 | item.Expired = time.Now().Unix() + (86400 * 365 * 10) // ten years |
| 158 | } else { | 146 | } else { |
| ... | @@ -163,13 +151,12 @@ func (this *FileCache) Put(key string, val interface{}, timeout int64) error { | ... | @@ -163,13 +151,12 @@ func (this *FileCache) Put(key string, val interface{}, timeout int64) error { |
| 163 | if err != nil { | 151 | if err != nil { |
| 164 | return err | 152 | return err |
| 165 | } | 153 | } |
| 166 | err = File_put_contents(filename, data) | 154 | return File_put_contents(fc.getCacheFileName(key), data) |
| 167 | return err | ||
| 168 | } | 155 | } |
| 169 | 156 | ||
| 170 | // Delete file cache value. | 157 | // Delete file cache value. |
| 171 | func (this *FileCache) Delete(key string) error { | 158 | func (fc *FileCache) Delete(key string) error { |
| 172 | filename := this.getCacheFileName(key) | 159 | filename := fc.getCacheFileName(key) |
| 173 | if ok, _ := exists(filename); ok { | 160 | if ok, _ := exists(filename); ok { |
| 174 | return os.Remove(filename) | 161 | return os.Remove(filename) |
| 175 | } | 162 | } |
| ... | @@ -177,44 +164,41 @@ func (this *FileCache) Delete(key string) error { | ... | @@ -177,44 +164,41 @@ func (this *FileCache) Delete(key string) error { |
| 177 | } | 164 | } |
| 178 | 165 | ||
| 179 | // Increase cached int value. | 166 | // Increase cached int value. |
| 180 | // this value is saving forever unless Delete. | 167 | // fc value is saving forever unless Delete. |
| 181 | func (this *FileCache) Incr(key string) error { | 168 | func (fc *FileCache) Incr(key string) error { |
| 182 | data := this.Get(key) | 169 | data := fc.Get(key) |
| 183 | var incr int | 170 | var incr int |
| 184 | //fmt.Println(reflect.TypeOf(data).Name()) | ||
| 185 | if reflect.TypeOf(data).Name() != "int" { | 171 | if reflect.TypeOf(data).Name() != "int" { |
| 186 | incr = 0 | 172 | incr = 0 |
| 187 | } else { | 173 | } else { |
| 188 | incr = data.(int) + 1 | 174 | incr = data.(int) + 1 |
| 189 | } | 175 | } |
| 190 | this.Put(key, incr, FileCacheEmbedExpiry) | 176 | fc.Put(key, incr, FileCacheEmbedExpiry) |
| 191 | return nil | 177 | return nil |
| 192 | } | 178 | } |
| 193 | 179 | ||
| 194 | // Decrease cached int value. | 180 | // Decrease cached int value. |
| 195 | func (this *FileCache) Decr(key string) error { | 181 | func (fc *FileCache) Decr(key string) error { |
| 196 | data := this.Get(key) | 182 | data := fc.Get(key) |
| 197 | var decr int | 183 | var decr int |
| 198 | if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 { | 184 | if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 { |
| 199 | decr = 0 | 185 | decr = 0 |
| 200 | } else { | 186 | } else { |
| 201 | decr = data.(int) - 1 | 187 | decr = data.(int) - 1 |
| 202 | } | 188 | } |
| 203 | this.Put(key, decr, FileCacheEmbedExpiry) | 189 | fc.Put(key, decr, FileCacheEmbedExpiry) |
| 204 | return nil | 190 | return nil |
| 205 | } | 191 | } |
| 206 | 192 | ||
| 207 | // Check value is exist. | 193 | // Check value is exist. |
| 208 | func (this *FileCache) IsExist(key string) bool { | 194 | func (fc *FileCache) IsExist(key string) bool { |
| 209 | filename := this.getCacheFileName(key) | 195 | ret, _ := exists(fc.getCacheFileName(key)) |
| 210 | ret, _ := exists(filename) | ||
| 211 | return ret | 196 | return ret |
| 212 | } | 197 | } |
| 213 | 198 | ||
| 214 | // Clean cached files. | 199 | // Clean cached files. |
| 215 | // not implemented. | 200 | // not implemented. |
| 216 | func (this *FileCache) ClearAll() error { | 201 | func (fc *FileCache) ClearAll() error { |
| 217 | //this.CachePath | ||
| 218 | return nil | 202 | return nil |
| 219 | } | 203 | } |
| 220 | 204 | ||
| ... | @@ -232,22 +216,22 @@ func exists(path string) (bool, error) { | ... | @@ -232,22 +216,22 @@ func exists(path string) (bool, error) { |
| 232 | 216 | ||
| 233 | // Get bytes to file. | 217 | // Get bytes to file. |
| 234 | // if non-exist, create this file. | 218 | // if non-exist, create this file. |
| 235 | func File_get_contents(filename string) ([]byte, error) { | 219 | func File_get_contents(filename string) (data []byte, e error) { |
| 236 | f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) | 220 | f, e := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) |
| 237 | if err != nil { | 221 | if e != nil { |
| 238 | return []byte(""), err | 222 | return |
| 239 | } | 223 | } |
| 240 | defer f.Close() | 224 | defer f.Close() |
| 241 | stat, err := f.Stat() | 225 | stat, e := f.Stat() |
| 242 | if err != nil { | 226 | if e != nil { |
| 243 | return []byte(""), err | 227 | return |
| 244 | } | 228 | } |
| 245 | data := make([]byte, stat.Size()) | 229 | data = make([]byte, stat.Size()) |
| 246 | result, err := f.Read(data) | 230 | result, e := f.Read(data) |
| 247 | if int64(result) == stat.Size() { | 231 | if e != nil || int64(result) != stat.Size() { |
| 248 | return data, err | 232 | return nil, e |
| 249 | } | 233 | } |
| 250 | return []byte(""), err | 234 | return |
| 251 | } | 235 | } |
| 252 | 236 | ||
| 253 | // Put bytes to file. | 237 | // Put bytes to file. | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | 6 | // | |
| 7 | package cache | 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | // package memcahe for cache provider | ||
| 16 | // | ||
| 17 | // depend on github.com/bradfitz/gomemcache/memcache | ||
| 18 | // | ||
| 19 | // go install github.com/bradfitz/gomemcache/memcache | ||
| 20 | // | ||
| 21 | // Usage: | ||
| 22 | // import( | ||
| 23 | // _ "github.com/astaxie/beego/cache/memcache" | ||
| 24 | // "github.com/astaxie/beego/cache" | ||
| 25 | // ) | ||
| 26 | // | ||
| 27 | // bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`) | ||
| 28 | // | ||
| 29 | // more docs http://beego.me/docs/module/cache.md | ||
| 30 | package memcache | ||
| 8 | 31 | ||
| 9 | import ( | 32 | import ( |
| 10 | "encoding/json" | 33 | "encoding/json" |
| 11 | "errors" | 34 | "errors" |
| 35 | "strings" | ||
| 12 | 36 | ||
| 13 | "github.com/beego/memcache" | 37 | "github.com/bradfitz/gomemcache/memcache" |
| 14 | 38 | ||
| 15 | "github.com/astaxie/beego/cache" | 39 | "github.com/astaxie/beego/cache" |
| 16 | ) | 40 | ) |
| 17 | 41 | ||
| 18 | // Memcache adapter. | 42 | // Memcache adapter. |
| 19 | type MemcacheCache struct { | 43 | type MemcacheCache struct { |
| 20 | c *memcache.Connection | 44 | conn *memcache.Client |
| 21 | conninfo string | 45 | conninfo []string |
| 22 | } | 46 | } |
| 23 | 47 | ||
| 24 | // create new memcache adapter. | 48 | // create new memcache adapter. |
| ... | @@ -28,32 +52,21 @@ func NewMemCache() *MemcacheCache { | ... | @@ -28,32 +52,21 @@ func NewMemCache() *MemcacheCache { |
| 28 | 52 | ||
| 29 | // get value from memcache. | 53 | // get value from memcache. |
| 30 | func (rc *MemcacheCache) Get(key string) interface{} { | 54 | func (rc *MemcacheCache) Get(key string) interface{} { |
| 31 | if rc.c == nil { | 55 | if rc.conn == nil { |
| 32 | var err error | 56 | if err := rc.connectInit(); err != nil { |
| 33 | rc.c, err = rc.connectInit() | ||
| 34 | if err != nil { | ||
| 35 | return err | 57 | return err |
| 36 | } | 58 | } |
| 37 | } | 59 | } |
| 38 | v, err := rc.c.Get(key) | 60 | if item, err := rc.conn.Get(key); err == nil { |
| 39 | if err != nil { | 61 | return string(item.Value) |
| 40 | return nil | ||
| 41 | } | ||
| 42 | var contain interface{} | ||
| 43 | if len(v) > 0 { | ||
| 44 | contain = string(v[0].Value) | ||
| 45 | } else { | ||
| 46 | contain = nil | ||
| 47 | } | 62 | } |
| 48 | return contain | 63 | return nil |
| 49 | } | 64 | } |
| 50 | 65 | ||
| 51 | // put value to memcache. only support string. | 66 | // put value to memcache. only support string. |
| 52 | func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { | 67 | func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { |
| 53 | if rc.c == nil { | 68 | if rc.conn == nil { |
| 54 | var err error | 69 | if err := rc.connectInit(); err != nil { |
| 55 | rc.c, err = rc.connectInit() | ||
| 56 | if err != nil { | ||
| 57 | return err | 70 | return err |
| 58 | } | 71 | } |
| 59 | } | 72 | } |
| ... | @@ -61,69 +74,64 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { | ... | @@ -61,69 +74,64 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { |
| 61 | if !ok { | 74 | if !ok { |
| 62 | return errors.New("val must string") | 75 | return errors.New("val must string") |
| 63 | } | 76 | } |
| 64 | stored, err := rc.c.Set(key, 0, uint64(timeout), []byte(v)) | 77 | item := memcache.Item{Key: key, Value: []byte(v), Expiration: int32(timeout)} |
| 65 | if err == nil && stored == false { | 78 | return rc.conn.Set(&item) |
| 66 | return errors.New("stored fail") | ||
| 67 | } | ||
| 68 | return err | ||
| 69 | } | 79 | } |
| 70 | 80 | ||
| 71 | // delete value in memcache. | 81 | // delete value in memcache. |
| 72 | func (rc *MemcacheCache) Delete(key string) error { | 82 | func (rc *MemcacheCache) Delete(key string) error { |
| 73 | if rc.c == nil { | 83 | if rc.conn == nil { |
| 74 | var err error | 84 | if err := rc.connectInit(); err != nil { |
| 75 | rc.c, err = rc.connectInit() | ||
| 76 | if err != nil { | ||
| 77 | return err | 85 | return err |
| 78 | } | 86 | } |
| 79 | } | 87 | } |
| 80 | _, err := rc.c.Delete(key) | 88 | return rc.conn.Delete(key) |
| 81 | return err | ||
| 82 | } | 89 | } |
| 83 | 90 | ||
| 84 | // [Not Support] | ||
| 85 | // increase counter. | 91 | // increase counter. |
| 86 | func (rc *MemcacheCache) Incr(key string) error { | 92 | func (rc *MemcacheCache) Incr(key string) error { |
| 87 | return errors.New("not support in memcache") | 93 | if rc.conn == nil { |
| 94 | if err := rc.connectInit(); err != nil { | ||
| 95 | return err | ||
| 96 | } | ||
| 97 | } | ||
| 98 | _, err := rc.conn.Increment(key, 1) | ||
| 99 | return err | ||
| 88 | } | 100 | } |
| 89 | 101 | ||
| 90 | // [Not Support] | ||
| 91 | // decrease counter. | 102 | // decrease counter. |
| 92 | func (rc *MemcacheCache) Decr(key string) error { | 103 | func (rc *MemcacheCache) Decr(key string) error { |
| 93 | return errors.New("not support in memcache") | 104 | if rc.conn == nil { |
| 105 | if err := rc.connectInit(); err != nil { | ||
| 106 | return err | ||
| 107 | } | ||
| 108 | } | ||
| 109 | _, err := rc.conn.Decrement(key, 1) | ||
| 110 | return err | ||
| 94 | } | 111 | } |
| 95 | 112 | ||
| 96 | // check value exists in memcache. | 113 | // check value exists in memcache. |
| 97 | func (rc *MemcacheCache) IsExist(key string) bool { | 114 | func (rc *MemcacheCache) IsExist(key string) bool { |
| 98 | if rc.c == nil { | 115 | if rc.conn == nil { |
| 99 | var err error | 116 | if err := rc.connectInit(); err != nil { |
| 100 | rc.c, err = rc.connectInit() | ||
| 101 | if err != nil { | ||
| 102 | return false | 117 | return false |
| 103 | } | 118 | } |
| 104 | } | 119 | } |
| 105 | v, err := rc.c.Get(key) | 120 | _, err := rc.conn.Get(key) |
| 106 | if err != nil { | 121 | if err != nil { |
| 107 | return false | 122 | return false |
| 108 | } | 123 | } |
| 109 | if len(v) == 0 { | 124 | return true |
| 110 | return false | ||
| 111 | } else { | ||
| 112 | return true | ||
| 113 | } | ||
| 114 | } | 125 | } |
| 115 | 126 | ||
| 116 | // clear all cached in memcache. | 127 | // clear all cached in memcache. |
| 117 | func (rc *MemcacheCache) ClearAll() error { | 128 | func (rc *MemcacheCache) ClearAll() error { |
| 118 | if rc.c == nil { | 129 | if rc.conn == nil { |
| 119 | var err error | 130 | if err := rc.connectInit(); err != nil { |
| 120 | rc.c, err = rc.connectInit() | ||
| 121 | if err != nil { | ||
| 122 | return err | 131 | return err |
| 123 | } | 132 | } |
| 124 | } | 133 | } |
| 125 | err := rc.c.FlushAll() | 134 | return rc.conn.FlushAll() |
| 126 | return err | ||
| 127 | } | 135 | } |
| 128 | 136 | ||
| 129 | // start memcache adapter. | 137 | // start memcache adapter. |
| ... | @@ -135,24 +143,19 @@ func (rc *MemcacheCache) StartAndGC(config string) error { | ... | @@ -135,24 +143,19 @@ func (rc *MemcacheCache) StartAndGC(config string) error { |
| 135 | if _, ok := cf["conn"]; !ok { | 143 | if _, ok := cf["conn"]; !ok { |
| 136 | return errors.New("config has no conn key") | 144 | return errors.New("config has no conn key") |
| 137 | } | 145 | } |
| 138 | rc.conninfo = cf["conn"] | 146 | rc.conninfo = strings.Split(cf["conn"], ";") |
| 139 | var err error | 147 | if rc.conn == nil { |
| 140 | if rc.c != nil { | 148 | if err := rc.connectInit(); err != nil { |
| 141 | rc.c, err = rc.connectInit() | 149 | return err |
| 142 | if err != nil { | ||
| 143 | return errors.New("dial tcp conn error") | ||
| 144 | } | 150 | } |
| 145 | } | 151 | } |
| 146 | return nil | 152 | return nil |
| 147 | } | 153 | } |
| 148 | 154 | ||
| 149 | // connect to memcache and keep the connection. | 155 | // connect to memcache and keep the connection. |
| 150 | func (rc *MemcacheCache) connectInit() (*memcache.Connection, error) { | 156 | func (rc *MemcacheCache) connectInit() error { |
| 151 | c, err := memcache.Connect(rc.conninfo) | 157 | rc.conn = memcache.New(rc.conninfo...) |
| 152 | if err != nil { | 158 | return nil |
| 153 | return nil, err | ||
| 154 | } | ||
| 155 | return c, nil | ||
| 156 | } | 159 | } |
| 157 | 160 | ||
| 158 | func init() { | 161 | func init() { | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package cache | 15 | package cache |
| 8 | 16 | ||
| ... | @@ -46,15 +54,14 @@ func NewMemoryCache() *MemoryCache { | ... | @@ -46,15 +54,14 @@ func NewMemoryCache() *MemoryCache { |
| 46 | func (bc *MemoryCache) Get(name string) interface{} { | 54 | func (bc *MemoryCache) Get(name string) interface{} { |
| 47 | bc.lock.RLock() | 55 | bc.lock.RLock() |
| 48 | defer bc.lock.RUnlock() | 56 | defer bc.lock.RUnlock() |
| 49 | itm, ok := bc.items[name] | 57 | if itm, ok := bc.items[name]; ok { |
| 50 | if !ok { | 58 | if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired { |
| 51 | return nil | 59 | go bc.Delete(name) |
| 52 | } | 60 | return nil |
| 53 | if (time.Now().Unix() - itm.Lastaccess.Unix()) > itm.expired { | 61 | } |
| 54 | go bc.Delete(name) | 62 | return itm.val |
| 55 | return nil | ||
| 56 | } | 63 | } |
| 57 | return itm.val | 64 | return nil |
| 58 | } | 65 | } |
| 59 | 66 | ||
| 60 | // Put cache to memory. | 67 | // Put cache to memory. |
| ... | @@ -62,12 +69,11 @@ func (bc *MemoryCache) Get(name string) interface{} { | ... | @@ -62,12 +69,11 @@ func (bc *MemoryCache) Get(name string) interface{} { |
| 62 | func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error { | 69 | func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error { |
| 63 | bc.lock.Lock() | 70 | bc.lock.Lock() |
| 64 | defer bc.lock.Unlock() | 71 | defer bc.lock.Unlock() |
| 65 | t := MemoryItem{ | 72 | bc.items[name] = &MemoryItem{ |
| 66 | val: value, | 73 | val: value, |
| 67 | Lastaccess: time.Now(), | 74 | Lastaccess: time.Now(), |
| 68 | expired: expired, | 75 | expired: expired, |
| 69 | } | 76 | } |
| 70 | bc.items[name] = &t | ||
| 71 | return nil | 77 | return nil |
| 72 | } | 78 | } |
| 73 | 79 | ||
| ... | @@ -79,8 +85,7 @@ func (bc *MemoryCache) Delete(name string) error { | ... | @@ -79,8 +85,7 @@ func (bc *MemoryCache) Delete(name string) error { |
| 79 | return errors.New("key not exist") | 85 | return errors.New("key not exist") |
| 80 | } | 86 | } |
| 81 | delete(bc.items, name) | 87 | delete(bc.items, name) |
| 82 | _, valid := bc.items[name] | 88 | if _, ok := bc.items[name]; ok { |
| 83 | if valid { | ||
| 84 | return errors.New("delete key error") | 89 | return errors.New("delete key error") |
| 85 | } | 90 | } |
| 86 | return nil | 91 | return nil |
| ... | @@ -211,8 +216,7 @@ func (bc *MemoryCache) item_expired(name string) bool { | ... | @@ -211,8 +216,7 @@ func (bc *MemoryCache) item_expired(name string) bool { |
| 211 | if !ok { | 216 | if !ok { |
| 212 | return true | 217 | return true |
| 213 | } | 218 | } |
| 214 | sec := time.Now().Unix() - itm.Lastaccess.Unix() | 219 | if time.Now().Unix()-itm.Lastaccess.Unix() >= itm.expired { |
| 215 | if sec >= itm.expired { | ||
| 216 | delete(bc.items, name) | 220 | delete(bc.items, name) |
| 217 | return true | 221 | return true |
| 218 | } | 222 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | 6 | // | |
| 7 | package cache | 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | // package redis for cache provider | ||
| 16 | // | ||
| 17 | // depend on github.com/garyburd/redigo/redis | ||
| 18 | // | ||
| 19 | // go install github.com/garyburd/redigo/redis | ||
| 20 | // | ||
| 21 | // Usage: | ||
| 22 | // import( | ||
| 23 | // _ "github.com/astaxie/beego/cache/redis" | ||
| 24 | // "github.com/astaxie/beego/cache" | ||
| 25 | // ) | ||
| 26 | // | ||
| 27 | // bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`) | ||
| 28 | // | ||
| 29 | // more docs http://beego.me/docs/module/cache.md | ||
| 30 | package redis | ||
| 8 | 31 | ||
| 9 | import ( | 32 | import ( |
| 10 | "encoding/json" | 33 | "encoding/json" |
| 11 | "errors" | 34 | "errors" |
| 12 | "time" | 35 | "time" |
| 13 | 36 | ||
| 14 | "github.com/beego/redigo/redis" | 37 | "github.com/garyburd/redigo/redis" |
| 15 | 38 | ||
| 16 | "github.com/astaxie/beego/cache" | 39 | "github.com/astaxie/beego/cache" |
| 17 | ) | 40 | ) |
| ... | @@ -43,52 +66,74 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa | ... | @@ -43,52 +66,74 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa |
| 43 | 66 | ||
| 44 | // Get cache from redis. | 67 | // Get cache from redis. |
| 45 | func (rc *RedisCache) Get(key string) interface{} { | 68 | func (rc *RedisCache) Get(key string) interface{} { |
| 46 | v, err := rc.do("HGET", rc.key, key) | 69 | if v, err := rc.do("GET", key); err == nil { |
| 47 | if err != nil { | 70 | return v |
| 48 | return nil | ||
| 49 | } | 71 | } |
| 50 | 72 | return nil | |
| 51 | return v | ||
| 52 | } | 73 | } |
| 53 | 74 | ||
| 54 | // put cache to redis. | 75 | // put cache to redis. |
| 55 | // timeout is ignored. | ||
| 56 | func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { | 76 | func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { |
| 57 | _, err := rc.do("HSET", rc.key, key, val) | 77 | var err error |
| 78 | if _, err = rc.do("SET", key, val); err != nil { | ||
| 79 | return err | ||
| 80 | } | ||
| 81 | |||
| 82 | if _, err = rc.do("HSET", rc.key, key, true); err != nil { | ||
| 83 | return err | ||
| 84 | } | ||
| 85 | _, err = rc.do("EXPIRE", key, timeout) | ||
| 58 | return err | 86 | return err |
| 59 | } | 87 | } |
| 60 | 88 | ||
| 61 | // delete cache in redis. | 89 | // delete cache in redis. |
| 62 | func (rc *RedisCache) Delete(key string) error { | 90 | func (rc *RedisCache) Delete(key string) error { |
| 63 | _, err := rc.do("HDEL", rc.key, key) | 91 | var err error |
| 92 | if _, err = rc.do("DEL", key); err != nil { | ||
| 93 | return err | ||
| 94 | } | ||
| 95 | _, err = rc.do("HDEL", rc.key, key) | ||
| 64 | return err | 96 | return err |
| 65 | } | 97 | } |
| 66 | 98 | ||
| 67 | // check cache exist in redis. | 99 | // check cache's existence in redis. |
| 68 | func (rc *RedisCache) IsExist(key string) bool { | 100 | func (rc *RedisCache) IsExist(key string) bool { |
| 69 | v, err := redis.Bool(rc.do("HEXISTS", rc.key, key)) | 101 | v, err := redis.Bool(rc.do("EXISTS", key)) |
| 70 | if err != nil { | 102 | if err != nil { |
| 71 | return false | 103 | return false |
| 72 | } | 104 | } |
| 73 | 105 | if v == false { | |
| 106 | if _, err = rc.do("HDEL", rc.key, key); err != nil { | ||
| 107 | return false | ||
| 108 | } | ||
| 109 | } | ||
| 74 | return v | 110 | return v |
| 75 | } | 111 | } |
| 76 | 112 | ||
| 77 | // increase counter in redis. | 113 | // increase counter in redis. |
| 78 | func (rc *RedisCache) Incr(key string) error { | 114 | func (rc *RedisCache) Incr(key string) error { |
| 79 | _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, 1)) | 115 | _, err := redis.Bool(rc.do("INCRBY", key, 1)) |
| 80 | return err | 116 | return err |
| 81 | } | 117 | } |
| 82 | 118 | ||
| 83 | // decrease counter in redis. | 119 | // decrease counter in redis. |
| 84 | func (rc *RedisCache) Decr(key string) error { | 120 | func (rc *RedisCache) Decr(key string) error { |
| 85 | _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, -1)) | 121 | _, err := redis.Bool(rc.do("INCRBY", key, -1)) |
| 86 | return err | 122 | return err |
| 87 | } | 123 | } |
| 88 | 124 | ||
| 89 | // clean all cache in redis. delete this redis collection. | 125 | // clean all cache in redis. delete this redis collection. |
| 90 | func (rc *RedisCache) ClearAll() error { | 126 | func (rc *RedisCache) ClearAll() error { |
| 91 | _, err := rc.do("DEL", rc.key) | 127 | cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key)) |
| 128 | if err != nil { | ||
| 129 | return err | ||
| 130 | } | ||
| 131 | for _, str := range cachedKeys { | ||
| 132 | if _, err = rc.do("DEL", str); err != nil { | ||
| 133 | return err | ||
| 134 | } | ||
| 135 | } | ||
| 136 | _, err = rc.do("DEL", rc.key) | ||
| 92 | return err | 137 | return err |
| 93 | } | 138 | } |
| 94 | 139 | ||
| ... | @@ -114,26 +159,21 @@ func (rc *RedisCache) StartAndGC(config string) error { | ... | @@ -114,26 +159,21 @@ func (rc *RedisCache) StartAndGC(config string) error { |
| 114 | 159 | ||
| 115 | c := rc.p.Get() | 160 | c := rc.p.Get() |
| 116 | defer c.Close() | 161 | defer c.Close() |
| 117 | if err := c.Err(); err != nil { | ||
| 118 | return err | ||
| 119 | } | ||
| 120 | 162 | ||
| 121 | return nil | 163 | return c.Err() |
| 122 | } | 164 | } |
| 123 | 165 | ||
| 124 | // connect to redis. | 166 | // connect to redis. |
| 125 | func (rc *RedisCache) connectInit() { | 167 | func (rc *RedisCache) connectInit() { |
| 168 | dialFunc := func() (c redis.Conn, err error) { | ||
| 169 | c, err = redis.Dial("tcp", rc.conninfo) | ||
| 170 | return | ||
| 171 | } | ||
| 126 | // initialize a new pool | 172 | // initialize a new pool |
| 127 | rc.p = &redis.Pool{ | 173 | rc.p = &redis.Pool{ |
| 128 | MaxIdle: 3, | 174 | MaxIdle: 3, |
| 129 | IdleTimeout: 180 * time.Second, | 175 | IdleTimeout: 180 * time.Second, |
| 130 | Dial: func() (redis.Conn, error) { | 176 | Dial: dialFunc, |
| 131 | c, err := redis.Dial("tcp", rc.conninfo) | ||
| 132 | if err != nil { | ||
| 133 | return nil, err | ||
| 134 | } | ||
| 135 | return c, nil | ||
| 136 | }, | ||
| 137 | } | 177 | } |
| 138 | } | 178 | } |
| 139 | 179 | ... | ... |
cache/redis/redis_test.go
0 → 100644
| 1 | // Copyright 2014 beego Author. All Rights Reserved. | ||
| 2 | // | ||
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | // you may not use this file except in compliance with the License. | ||
| 5 | // You may obtain a copy of the License at | ||
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | package redis | ||
| 16 | |||
| 17 | import ( | ||
| 18 | "testing" | ||
| 19 | "time" | ||
| 20 | |||
| 21 | "github.com/garyburd/redigo/redis" | ||
| 22 | |||
| 23 | "github.com/astaxie/beego/cache" | ||
| 24 | ) | ||
| 25 | |||
| 26 | func TestRedisCache(t *testing.T) { | ||
| 27 | bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`) | ||
| 28 | if err != nil { | ||
| 29 | t.Error("init err") | ||
| 30 | } | ||
| 31 | if err = bm.Put("astaxie", 1, 10); err != nil { | ||
| 32 | t.Error("set Error", err) | ||
| 33 | } | ||
| 34 | if !bm.IsExist("astaxie") { | ||
| 35 | t.Error("check err") | ||
| 36 | } | ||
| 37 | |||
| 38 | time.Sleep(10 * time.Second) | ||
| 39 | |||
| 40 | if bm.IsExist("astaxie") { | ||
| 41 | t.Error("check err") | ||
| 42 | } | ||
| 43 | if err = bm.Put("astaxie", 1, 10); err != nil { | ||
| 44 | t.Error("set Error", err) | ||
| 45 | } | ||
| 46 | |||
| 47 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { | ||
| 48 | t.Error("get err") | ||
| 49 | } | ||
| 50 | |||
| 51 | if err = bm.Incr("astaxie"); err != nil { | ||
| 52 | t.Error("Incr Error", err) | ||
| 53 | } | ||
| 54 | |||
| 55 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 { | ||
| 56 | t.Error("get err") | ||
| 57 | } | ||
| 58 | |||
| 59 | if err = bm.Decr("astaxie"); err != nil { | ||
| 60 | t.Error("Decr Error", err) | ||
| 61 | } | ||
| 62 | |||
| 63 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { | ||
| 64 | t.Error("get err") | ||
| 65 | } | ||
| 66 | bm.Delete("astaxie") | ||
| 67 | if bm.IsExist("astaxie") { | ||
| 68 | t.Error("delete err") | ||
| 69 | } | ||
| 70 | //test string | ||
| 71 | if err = bm.Put("astaxie", "author", 10); err != nil { | ||
| 72 | t.Error("set Error", err) | ||
| 73 | } | ||
| 74 | if !bm.IsExist("astaxie") { | ||
| 75 | t.Error("check err") | ||
| 76 | } | ||
| 77 | |||
| 78 | if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" { | ||
| 79 | t.Error("get err") | ||
| 80 | } | ||
| 81 | // test clear all | ||
| 82 | if err = bm.ClearAll(); err != nil { | ||
| 83 | t.Error("clear all err") | ||
| 84 | } | ||
| 85 | } |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ||
| ... | @@ -52,6 +60,7 @@ var ( | ... | @@ -52,6 +60,7 @@ var ( |
| 52 | SessionHashKey string // session hash salt string. | 60 | SessionHashKey string // session hash salt string. |
| 53 | SessionCookieLifeTime int // the life time of session id in cookie. | 61 | SessionCookieLifeTime int // the life time of session id in cookie. |
| 54 | SessionAutoSetCookie bool // auto setcookie | 62 | SessionAutoSetCookie bool // auto setcookie |
| 63 | SessionDomain string // the cookie domain default is empty | ||
| 55 | UseFcgi bool | 64 | UseFcgi bool |
| 56 | MaxMemory int64 | 65 | MaxMemory int64 |
| 57 | EnableGzip bool // flag of enable gzip | 66 | EnableGzip bool // flag of enable gzip |
| ... | @@ -180,147 +189,147 @@ func ParseConfig() (err error) { | ... | @@ -180,147 +189,147 @@ func ParseConfig() (err error) { |
| 180 | return err | 189 | return err |
| 181 | } else { | 190 | } else { |
| 182 | 191 | ||
| 183 | if v, err := getConfig("string", "HttpAddr"); err == nil { | 192 | if v, err := GetConfig("string", "HttpAddr"); err == nil { |
| 184 | HttpAddr = v.(string) | 193 | HttpAddr = v.(string) |
| 185 | } | 194 | } |
| 186 | 195 | ||
| 187 | if v, err := getConfig("int", "HttpPort"); err == nil { | 196 | if v, err := GetConfig("int", "HttpPort"); err == nil { |
| 188 | HttpPort = v.(int) | 197 | HttpPort = v.(int) |
| 189 | } | 198 | } |
| 190 | 199 | ||
| 191 | if v, err := getConfig("bool", "EnableHttpListen"); err == nil { | 200 | if v, err := GetConfig("bool", "EnableHttpListen"); err == nil { |
| 192 | EnableHttpListen = v.(bool) | 201 | EnableHttpListen = v.(bool) |
| 193 | } | 202 | } |
| 194 | 203 | ||
| 195 | if maxmemory, err := getConfig("int64", "MaxMemory"); err == nil { | 204 | if maxmemory, err := GetConfig("int64", "MaxMemory"); err == nil { |
| 196 | MaxMemory = maxmemory.(int64) | 205 | MaxMemory = maxmemory.(int64) |
| 197 | } | 206 | } |
| 198 | 207 | ||
| 199 | if appname, _ := getConfig("string", "AppName"); appname != "" { | 208 | if appname, _ := GetConfig("string", "AppName"); appname != "" { |
| 200 | AppName = appname.(string) | 209 | AppName = appname.(string) |
| 201 | } | 210 | } |
| 202 | 211 | ||
| 203 | if runmode, _ := getConfig("string", "RunMode"); runmode != "" { | 212 | if runmode, _ := GetConfig("string", "RunMode"); runmode != "" { |
| 204 | RunMode = runmode.(string) | 213 | RunMode = runmode.(string) |
| 205 | } | 214 | } |
| 206 | 215 | ||
| 207 | if autorender, err := getConfig("bool", "AutoRender"); err == nil { | 216 | if autorender, err := GetConfig("bool", "AutoRender"); err == nil { |
| 208 | AutoRender = autorender.(bool) | 217 | AutoRender = autorender.(bool) |
| 209 | } | 218 | } |
| 210 | 219 | ||
| 211 | if autorecover, err := getConfig("bool", "RecoverPanic"); err == nil { | 220 | if autorecover, err := GetConfig("bool", "RecoverPanic"); err == nil { |
| 212 | RecoverPanic = autorecover.(bool) | 221 | RecoverPanic = autorecover.(bool) |
| 213 | } | 222 | } |
| 214 | 223 | ||
| 215 | if views, _ := getConfig("string", "ViewsPath"); views != "" { | 224 | if views, _ := GetConfig("string", "ViewsPath"); views != "" { |
| 216 | ViewsPath = views.(string) | 225 | ViewsPath = views.(string) |
| 217 | } | 226 | } |
| 218 | 227 | ||
| 219 | if sessionon, err := getConfig("bool", "SessionOn"); err == nil { | 228 | if sessionon, err := GetConfig("bool", "SessionOn"); err == nil { |
| 220 | SessionOn = sessionon.(bool) | 229 | SessionOn = sessionon.(bool) |
| 221 | } | 230 | } |
| 222 | 231 | ||
| 223 | if sessProvider, _ := getConfig("string", "SessionProvider"); sessProvider != "" { | 232 | if sessProvider, _ := GetConfig("string", "SessionProvider"); sessProvider != "" { |
| 224 | SessionProvider = sessProvider.(string) | 233 | SessionProvider = sessProvider.(string) |
| 225 | } | 234 | } |
| 226 | 235 | ||
| 227 | if sessName, _ := getConfig("string", "SessionName"); sessName != "" { | 236 | if sessName, _ := GetConfig("string", "SessionName"); sessName != "" { |
| 228 | SessionName = sessName.(string) | 237 | SessionName = sessName.(string) |
| 229 | } | 238 | } |
| 230 | 239 | ||
| 231 | if sesssavepath, _ := getConfig("string", "SessionSavePath"); sesssavepath != "" { | 240 | if sesssavepath, _ := GetConfig("string", "SessionSavePath"); sesssavepath != "" { |
| 232 | SessionSavePath = sesssavepath.(string) | 241 | SessionSavePath = sesssavepath.(string) |
| 233 | } | 242 | } |
| 234 | 243 | ||
| 235 | if sesshashfunc, _ := getConfig("string", "SessionHashFunc"); sesshashfunc != "" { | 244 | if sesshashfunc, _ := GetConfig("string", "SessionHashFunc"); sesshashfunc != "" { |
| 236 | SessionHashFunc = sesshashfunc.(string) | 245 | SessionHashFunc = sesshashfunc.(string) |
| 237 | } | 246 | } |
| 238 | 247 | ||
| 239 | if sesshashkey, _ := getConfig("string", "SessionHashKey"); sesshashkey != "" { | 248 | if sesshashkey, _ := GetConfig("string", "SessionHashKey"); sesshashkey != "" { |
| 240 | SessionHashKey = sesshashkey.(string) | 249 | SessionHashKey = sesshashkey.(string) |
| 241 | } | 250 | } |
| 242 | 251 | ||
| 243 | if sessMaxLifeTime, err := getConfig("int64", "SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 { | 252 | if sessMaxLifeTime, err := GetConfig("int64", "SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 { |
| 244 | SessionGCMaxLifetime = sessMaxLifeTime.(int64) | 253 | SessionGCMaxLifetime = sessMaxLifeTime.(int64) |
| 245 | } | 254 | } |
| 246 | 255 | ||
| 247 | if sesscookielifetime, err := getConfig("int", "SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 { | 256 | if sesscookielifetime, err := GetConfig("int", "SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 { |
| 248 | SessionCookieLifeTime = sesscookielifetime.(int) | 257 | SessionCookieLifeTime = sesscookielifetime.(int) |
| 249 | } | 258 | } |
| 250 | 259 | ||
| 251 | if usefcgi, err := getConfig("bool", "UseFcgi"); err == nil { | 260 | if usefcgi, err := GetConfig("bool", "UseFcgi"); err == nil { |
| 252 | UseFcgi = usefcgi.(bool) | 261 | UseFcgi = usefcgi.(bool) |
| 253 | } | 262 | } |
| 254 | 263 | ||
| 255 | if enablegzip, err := getConfig("bool", "EnableGzip"); err == nil { | 264 | if enablegzip, err := GetConfig("bool", "EnableGzip"); err == nil { |
| 256 | EnableGzip = enablegzip.(bool) | 265 | EnableGzip = enablegzip.(bool) |
| 257 | } | 266 | } |
| 258 | 267 | ||
| 259 | if directoryindex, err := getConfig("bool", "DirectoryIndex"); err == nil { | 268 | if directoryindex, err := GetConfig("bool", "DirectoryIndex"); err == nil { |
| 260 | DirectoryIndex = directoryindex.(bool) | 269 | DirectoryIndex = directoryindex.(bool) |
| 261 | } | 270 | } |
| 262 | 271 | ||
| 263 | if timeout, err := getConfig("int64", "HttpServerTimeOut"); err == nil { | 272 | if timeout, err := GetConfig("int64", "HttpServerTimeOut"); err == nil { |
| 264 | HttpServerTimeOut = timeout.(int64) | 273 | HttpServerTimeOut = timeout.(int64) |
| 265 | } | 274 | } |
| 266 | 275 | ||
| 267 | if errorsshow, err := getConfig("bool", "ErrorsShow"); err == nil { | 276 | if errorsshow, err := GetConfig("bool", "ErrorsShow"); err == nil { |
| 268 | ErrorsShow = errorsshow.(bool) | 277 | ErrorsShow = errorsshow.(bool) |
| 269 | } | 278 | } |
| 270 | 279 | ||
| 271 | if copyrequestbody, err := getConfig("bool", "CopyRequestBody"); err == nil { | 280 | if copyrequestbody, err := GetConfig("bool", "CopyRequestBody"); err == nil { |
| 272 | CopyRequestBody = copyrequestbody.(bool) | 281 | CopyRequestBody = copyrequestbody.(bool) |
| 273 | } | 282 | } |
| 274 | 283 | ||
| 275 | if xsrfkey, _ := getConfig("string", "XSRFKEY"); xsrfkey != "" { | 284 | if xsrfkey, _ := GetConfig("string", "XSRFKEY"); xsrfkey != "" { |
| 276 | XSRFKEY = xsrfkey.(string) | 285 | XSRFKEY = xsrfkey.(string) |
| 277 | } | 286 | } |
| 278 | 287 | ||
| 279 | if enablexsrf, err := getConfig("bool", "EnableXSRF"); err == nil { | 288 | if enablexsrf, err := GetConfig("bool", "EnableXSRF"); err == nil { |
| 280 | EnableXSRF = enablexsrf.(bool) | 289 | EnableXSRF = enablexsrf.(bool) |
| 281 | } | 290 | } |
| 282 | 291 | ||
| 283 | if expire, err := getConfig("int", "XSRFExpire"); err == nil { | 292 | if expire, err := GetConfig("int", "XSRFExpire"); err == nil { |
| 284 | XSRFExpire = expire.(int) | 293 | XSRFExpire = expire.(int) |
| 285 | } | 294 | } |
| 286 | 295 | ||
| 287 | if tplleft, _ := getConfig("string", "TemplateLeft"); tplleft != "" { | 296 | if tplleft, _ := GetConfig("string", "TemplateLeft"); tplleft != "" { |
| 288 | TemplateLeft = tplleft.(string) | 297 | TemplateLeft = tplleft.(string) |
| 289 | } | 298 | } |
| 290 | 299 | ||
| 291 | if tplright, _ := getConfig("string", "TemplateRight"); tplright != "" { | 300 | if tplright, _ := GetConfig("string", "TemplateRight"); tplright != "" { |
| 292 | TemplateRight = tplright.(string) | 301 | TemplateRight = tplright.(string) |
| 293 | } | 302 | } |
| 294 | 303 | ||
| 295 | if httptls, err := getConfig("bool", "EnableHttpTLS"); err == nil { | 304 | if httptls, err := GetConfig("bool", "EnableHttpTLS"); err == nil { |
| 296 | EnableHttpTLS = httptls.(bool) | 305 | EnableHttpTLS = httptls.(bool) |
| 297 | } | 306 | } |
| 298 | 307 | ||
| 299 | if httpsport, err := getConfig("int", "HttpsPort"); err == nil { | 308 | if httpsport, err := GetConfig("int", "HttpsPort"); err == nil { |
| 300 | HttpsPort = httpsport.(int) | 309 | HttpsPort = httpsport.(int) |
| 301 | } | 310 | } |
| 302 | 311 | ||
| 303 | if certfile, _ := getConfig("string", "HttpCertFile"); certfile != "" { | 312 | if certfile, _ := GetConfig("string", "HttpCertFile"); certfile != "" { |
| 304 | HttpCertFile = certfile.(string) | 313 | HttpCertFile = certfile.(string) |
| 305 | } | 314 | } |
| 306 | 315 | ||
| 307 | if keyfile, _ := getConfig("string", "HttpKeyFile"); keyfile != "" { | 316 | if keyfile, _ := GetConfig("string", "HttpKeyFile"); keyfile != "" { |
| 308 | HttpKeyFile = keyfile.(string) | 317 | HttpKeyFile = keyfile.(string) |
| 309 | } | 318 | } |
| 310 | 319 | ||
| 311 | if serverName, _ := getConfig("string", "BeegoServerName"); serverName != "" { | 320 | if serverName, _ := GetConfig("string", "BeegoServerName"); serverName != "" { |
| 312 | BeegoServerName = serverName.(string) | 321 | BeegoServerName = serverName.(string) |
| 313 | } | 322 | } |
| 314 | 323 | ||
| 315 | if flashname, _ := getConfig("string", "FlashName"); flashname != "" { | 324 | if flashname, _ := GetConfig("string", "FlashName"); flashname != "" { |
| 316 | FlashName = flashname.(string) | 325 | FlashName = flashname.(string) |
| 317 | } | 326 | } |
| 318 | 327 | ||
| 319 | if flashseperator, _ := getConfig("string", "FlashSeperator"); flashseperator != "" { | 328 | if flashseperator, _ := GetConfig("string", "FlashSeperator"); flashseperator != "" { |
| 320 | FlashSeperator = flashseperator.(string) | 329 | FlashSeperator = flashseperator.(string) |
| 321 | } | 330 | } |
| 322 | 331 | ||
| 323 | if sd, _ := getConfig("string", "StaticDir"); sd != "" { | 332 | if sd, _ := GetConfig("string", "StaticDir"); sd != "" { |
| 324 | for k := range StaticDir { | 333 | for k := range StaticDir { |
| 325 | delete(StaticDir, k) | 334 | delete(StaticDir, k) |
| 326 | } | 335 | } |
| ... | @@ -334,7 +343,7 @@ func ParseConfig() (err error) { | ... | @@ -334,7 +343,7 @@ func ParseConfig() (err error) { |
| 334 | } | 343 | } |
| 335 | } | 344 | } |
| 336 | 345 | ||
| 337 | if sgz, _ := getConfig("string", "StaticExtensionsToGzip"); sgz != "" { | 346 | if sgz, _ := GetConfig("string", "StaticExtensionsToGzip"); sgz != "" { |
| 338 | extensions := strings.Split(sgz.(string), ",") | 347 | extensions := strings.Split(sgz.(string), ",") |
| 339 | if len(extensions) > 0 { | 348 | if len(extensions) > 0 { |
| 340 | StaticExtensionsToGzip = []string{} | 349 | StaticExtensionsToGzip = []string{} |
| ... | @@ -351,26 +360,37 @@ func ParseConfig() (err error) { | ... | @@ -351,26 +360,37 @@ func ParseConfig() (err error) { |
| 351 | } | 360 | } |
| 352 | } | 361 | } |
| 353 | 362 | ||
| 354 | if enableadmin, err := getConfig("bool", "EnableAdmin"); err == nil { | 363 | if enableadmin, err := GetConfig("bool", "EnableAdmin"); err == nil { |
| 355 | EnableAdmin = enableadmin.(bool) | 364 | EnableAdmin = enableadmin.(bool) |
| 356 | } | 365 | } |
| 357 | 366 | ||
| 358 | if adminhttpaddr, _ := getConfig("string", "AdminHttpAddr"); adminhttpaddr != "" { | 367 | if adminhttpaddr, _ := GetConfig("string", "AdminHttpAddr"); adminhttpaddr != "" { |
| 359 | AdminHttpAddr = adminhttpaddr.(string) | 368 | AdminHttpAddr = adminhttpaddr.(string) |
| 360 | } | 369 | } |
| 361 | 370 | ||
| 362 | if adminhttpport, err := getConfig("int", "AdminHttpPort"); err == nil { | 371 | if adminhttpport, err := GetConfig("int", "AdminHttpPort"); err == nil { |
| 363 | AdminHttpPort = adminhttpport.(int) | 372 | AdminHttpPort = adminhttpport.(int) |
| 364 | } | 373 | } |
| 365 | 374 | ||
| 366 | if enabledocs, err := getConfig("bool", "EnableDocs"); err == nil { | 375 | if enabledocs, err := GetConfig("bool", "EnableDocs"); err == nil { |
| 367 | EnableDocs = enabledocs.(bool) | 376 | EnableDocs = enabledocs.(bool) |
| 368 | } | 377 | } |
| 369 | } | 378 | } |
| 370 | return nil | 379 | return nil |
| 371 | } | 380 | } |
| 372 | 381 | ||
| 373 | func getConfig(typ, key string) (interface{}, error) { | 382 | // Getconfig throw the Runmode |
| 383 | // [dev] | ||
| 384 | // name = astaixe | ||
| 385 | // IsEnable = false | ||
| 386 | // [prod] | ||
| 387 | // name = slene | ||
| 388 | // IsEnable = true | ||
| 389 | // | ||
| 390 | // usage: | ||
| 391 | // GetConfig("string", "name") | ||
| 392 | // GetConfig("bool", "IsEnable") | ||
| 393 | func GetConfig(typ, key string) (interface{}, error) { | ||
| 374 | switch typ { | 394 | switch typ { |
| 375 | case "string": | 395 | case "string": |
| 376 | v := AppConfig.String(RunMode + "::" + key) | 396 | v := AppConfig.String(RunMode + "::" + key) | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 15 | // Usage: | ||
| 16 | // import( | ||
| 17 | // "github.com/astaxie/beego/config" | ||
| 18 | // ) | ||
| 19 | // | ||
| 20 | // cnf, err := config.NewConfig("ini", "config.conf") | ||
| 21 | // | ||
| 22 | // cnf APIS: | ||
| 23 | // | ||
| 24 | // cnf.Set(key, val string) error | ||
| 25 | // cnf.String(key string) string | ||
| 26 | // cnf.Strings(key string) []string | ||
| 27 | // cnf.Int(key string) (int, error) | ||
| 28 | // cnf.Int64(key string) (int64, error) | ||
| 29 | // cnf.Bool(key string) (bool, error) | ||
| 30 | // cnf.Float(key string) (float64, error) | ||
| 31 | // cnf.DefaultString(key string, defaultval string) string | ||
| 32 | // cnf.DefaultStrings(key string, defaultval []string) []string | ||
| 33 | // cnf.DefaultInt(key string, defaultval int) int | ||
| 34 | // cnf.DefaultInt64(key string, defaultval int64) int64 | ||
| 35 | // cnf.DefaultBool(key string, defaultval bool) bool | ||
| 36 | // cnf.DefaultFloat(key string, defaultval float64) float64 | ||
| 37 | // cnf.DIY(key string) (interface{}, error) | ||
| 38 | // cnf.GetSection(section string) (map[string]string, error) | ||
| 39 | // cnf.SaveConfigFile(filename string) error | ||
| 40 | // | ||
| 41 | // more docs http://beego.me/docs/module/config.md | ||
| 7 | package config | 42 | package config |
| 8 | 43 | ||
| 9 | import ( | 44 | import ( |
| ... | @@ -19,12 +54,21 @@ type ConfigContainer interface { | ... | @@ -19,12 +54,21 @@ type ConfigContainer interface { |
| 19 | Int64(key string) (int64, error) | 54 | Int64(key string) (int64, error) |
| 20 | Bool(key string) (bool, error) | 55 | Bool(key string) (bool, error) |
| 21 | Float(key string) (float64, error) | 56 | Float(key string) (float64, error) |
| 57 | DefaultString(key string, defaultval string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. | ||
| 58 | DefaultStrings(key string, defaultval []string) []string //get string slice | ||
| 59 | DefaultInt(key string, defaultval int) int | ||
| 60 | DefaultInt64(key string, defaultval int64) int64 | ||
| 61 | DefaultBool(key string, defaultval bool) bool | ||
| 62 | DefaultFloat(key string, defaultval float64) float64 | ||
| 22 | DIY(key string) (interface{}, error) | 63 | DIY(key string) (interface{}, error) |
| 64 | GetSection(section string) (map[string]string, error) | ||
| 65 | SaveConfigFile(filename string) error | ||
| 23 | } | 66 | } |
| 24 | 67 | ||
| 25 | // Config is the adapter interface for parsing config file to get raw data to ConfigContainer. | 68 | // Config is the adapter interface for parsing config file to get raw data to ConfigContainer. |
| 26 | type Config interface { | 69 | type Config interface { |
| 27 | Parse(key string) (ConfigContainer, error) | 70 | Parse(key string) (ConfigContainer, error) |
| 71 | ParseData(data []byte) (ConfigContainer, error) | ||
| 28 | } | 72 | } |
| 29 | 73 | ||
| 30 | var adapters = make(map[string]Config) | 74 | var adapters = make(map[string]Config) |
| ... | @@ -36,7 +80,7 @@ func Register(name string, adapter Config) { | ... | @@ -36,7 +80,7 @@ func Register(name string, adapter Config) { |
| 36 | if adapter == nil { | 80 | if adapter == nil { |
| 37 | panic("config: Register adapter is nil") | 81 | panic("config: Register adapter is nil") |
| 38 | } | 82 | } |
| 39 | if _, dup := adapters[name]; dup { | 83 | if _, ok := adapters[name]; ok { |
| 40 | panic("config: Register called twice for adapter " + name) | 84 | panic("config: Register called twice for adapter " + name) |
| 41 | } | 85 | } |
| 42 | adapters[name] = adapter | 86 | adapters[name] = adapter |
| ... | @@ -51,3 +95,13 @@ func NewConfig(adapterName, fileaname string) (ConfigContainer, error) { | ... | @@ -51,3 +95,13 @@ func NewConfig(adapterName, fileaname string) (ConfigContainer, error) { |
| 51 | } | 95 | } |
| 52 | return adapter.Parse(fileaname) | 96 | return adapter.Parse(fileaname) |
| 53 | } | 97 | } |
| 98 | |||
| 99 | // adapterName is ini/json/xml/yaml. | ||
| 100 | // data is the config data. | ||
| 101 | func NewConfigData(adapterName string, data []byte) (ConfigContainer, error) { | ||
| 102 | adapter, ok := adapters[adapterName] | ||
| 103 | if !ok { | ||
| 104 | return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName) | ||
| 105 | } | ||
| 106 | return adapter.ParseData(data) | ||
| 107 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package config |
| 8 | 16 | ||
| ... | @@ -17,13 +25,11 @@ type fakeConfigContainer struct { | ... | @@ -17,13 +25,11 @@ type fakeConfigContainer struct { |
| 17 | } | 25 | } |
| 18 | 26 | ||
| 19 | func (c *fakeConfigContainer) getData(key string) string { | 27 | func (c *fakeConfigContainer) getData(key string) string { |
| 20 | key = strings.ToLower(key) | 28 | return c.data[strings.ToLower(key)] |
| 21 | return c.data[key] | ||
| 22 | } | 29 | } |
| 23 | 30 | ||
| 24 | func (c *fakeConfigContainer) Set(key, val string) error { | 31 | func (c *fakeConfigContainer) Set(key, val string) error { |
| 25 | key = strings.ToLower(key) | 32 | c.data[strings.ToLower(key)] = val |
| 26 | c.data[key] = val | ||
| 27 | return nil | 33 | return nil |
| 28 | } | 34 | } |
| 29 | 35 | ||
| ... | @@ -31,34 +37,89 @@ func (c *fakeConfigContainer) String(key string) string { | ... | @@ -31,34 +37,89 @@ func (c *fakeConfigContainer) String(key string) string { |
| 31 | return c.getData(key) | 37 | return c.getData(key) |
| 32 | } | 38 | } |
| 33 | 39 | ||
| 40 | func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string { | ||
| 41 | if v := c.getData(key); v == "" { | ||
| 42 | return defaultval | ||
| 43 | } else { | ||
| 44 | return v | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 34 | func (c *fakeConfigContainer) Strings(key string) []string { | 48 | func (c *fakeConfigContainer) Strings(key string) []string { |
| 35 | return strings.Split(c.getData(key), ";") | 49 | return strings.Split(c.getData(key), ";") |
| 36 | } | 50 | } |
| 37 | 51 | ||
| 52 | func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string { | ||
| 53 | if v := c.Strings(key); len(v) == 0 { | ||
| 54 | return defaultval | ||
| 55 | } else { | ||
| 56 | return v | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 38 | func (c *fakeConfigContainer) Int(key string) (int, error) { | 60 | func (c *fakeConfigContainer) Int(key string) (int, error) { |
| 39 | return strconv.Atoi(c.getData(key)) | 61 | return strconv.Atoi(c.getData(key)) |
| 40 | } | 62 | } |
| 41 | 63 | ||
| 64 | func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int { | ||
| 65 | if v, err := c.Int(key); err != nil { | ||
| 66 | return defaultval | ||
| 67 | } else { | ||
| 68 | return v | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 42 | func (c *fakeConfigContainer) Int64(key string) (int64, error) { | 72 | func (c *fakeConfigContainer) Int64(key string) (int64, error) { |
| 43 | return strconv.ParseInt(c.getData(key), 10, 64) | 73 | return strconv.ParseInt(c.getData(key), 10, 64) |
| 44 | } | 74 | } |
| 45 | 75 | ||
| 76 | func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | ||
| 77 | if v, err := c.Int64(key); err != nil { | ||
| 78 | return defaultval | ||
| 79 | } else { | ||
| 80 | return v | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 46 | func (c *fakeConfigContainer) Bool(key string) (bool, error) { | 84 | func (c *fakeConfigContainer) Bool(key string) (bool, error) { |
| 47 | return strconv.ParseBool(c.getData(key)) | 85 | return strconv.ParseBool(c.getData(key)) |
| 48 | } | 86 | } |
| 49 | 87 | ||
| 88 | func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { | ||
| 89 | if v, err := c.Bool(key); err != nil { | ||
| 90 | return defaultval | ||
| 91 | } else { | ||
| 92 | return v | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 50 | func (c *fakeConfigContainer) Float(key string) (float64, error) { | 96 | func (c *fakeConfigContainer) Float(key string) (float64, error) { |
| 51 | return strconv.ParseFloat(c.getData(key), 64) | 97 | return strconv.ParseFloat(c.getData(key), 64) |
| 52 | } | 98 | } |
| 53 | 99 | ||
| 100 | func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | ||
| 101 | if v, err := c.Float(key); err != nil { | ||
| 102 | return defaultval | ||
| 103 | } else { | ||
| 104 | return v | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 54 | func (c *fakeConfigContainer) DIY(key string) (interface{}, error) { | 108 | func (c *fakeConfigContainer) DIY(key string) (interface{}, error) { |
| 55 | key = strings.ToLower(key) | 109 | if v, ok := c.data[strings.ToLower(key)]; ok { |
| 56 | if v, ok := c.data[key]; ok { | ||
| 57 | return v, nil | 110 | return v, nil |
| 58 | } | 111 | } |
| 59 | return nil, errors.New("key not find") | 112 | return nil, errors.New("key not find") |
| 60 | } | 113 | } |
| 61 | 114 | ||
| 115 | func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) { | ||
| 116 | return nil, errors.New("not implement in the fakeConfigContainer") | ||
| 117 | } | ||
| 118 | |||
| 119 | func (c *fakeConfigContainer) SaveConfigFile(filename string) error { | ||
| 120 | return errors.New("not implement in the fakeConfigContainer") | ||
| 121 | } | ||
| 122 | |||
| 62 | var _ ConfigContainer = new(fakeConfigContainer) | 123 | var _ ConfigContainer = new(fakeConfigContainer) |
| 63 | 124 | ||
| 64 | func NewFakeConfig() ConfigContainer { | 125 | func NewFakeConfig() ConfigContainer { | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package config |
| 8 | 16 | ||
| ... | @@ -10,11 +18,15 @@ import ( | ... | @@ -10,11 +18,15 @@ import ( |
| 10 | "bufio" | 18 | "bufio" |
| 11 | "bytes" | 19 | "bytes" |
| 12 | "errors" | 20 | "errors" |
| 21 | "fmt" | ||
| 13 | "io" | 22 | "io" |
| 23 | "io/ioutil" | ||
| 14 | "os" | 24 | "os" |
| 25 | "path" | ||
| 15 | "strconv" | 26 | "strconv" |
| 16 | "strings" | 27 | "strings" |
| 17 | "sync" | 28 | "sync" |
| 29 | "time" | ||
| 18 | "unicode" | 30 | "unicode" |
| 19 | ) | 31 | ) |
| 20 | 32 | ||
| ... | @@ -27,6 +39,7 @@ var ( | ... | @@ -27,6 +39,7 @@ var ( |
| 27 | bDQuote = []byte{'"'} // quote signal | 39 | bDQuote = []byte{'"'} // quote signal |
| 28 | sectionStart = []byte{'['} // section start signal | 40 | sectionStart = []byte{'['} // section start signal |
| 29 | sectionEnd = []byte{']'} // section end signal | 41 | sectionEnd = []byte{']'} // section end signal |
| 42 | lineBreak = "\n" | ||
| 30 | ) | 43 | ) |
| 31 | 44 | ||
| 32 | // IniConfig implements Config to parse ini file. | 45 | // IniConfig implements Config to parse ini file. |
| ... | @@ -80,8 +93,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { | ... | @@ -80,8 +93,7 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { |
| 80 | } | 93 | } |
| 81 | 94 | ||
| 82 | if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) { | 95 | if bytes.HasPrefix(line, sectionStart) && bytes.HasSuffix(line, sectionEnd) { |
| 83 | section = string(line[1 : len(line)-1]) | 96 | section = strings.ToLower(string(line[1 : len(line)-1])) // section name case insensitive |
| 84 | section = strings.ToLower(section) // section name case insensitive | ||
| 85 | if comment.Len() > 0 { | 97 | if comment.Len() > 0 { |
| 86 | cfg.sectionComment[section] = comment.String() | 98 | cfg.sectionComment[section] = comment.String() |
| 87 | comment.Reset() | 99 | comment.Reset() |
| ... | @@ -89,67 +101,124 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { | ... | @@ -89,67 +101,124 @@ func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { |
| 89 | if _, ok := cfg.data[section]; !ok { | 101 | if _, ok := cfg.data[section]; !ok { |
| 90 | cfg.data[section] = make(map[string]string) | 102 | cfg.data[section] = make(map[string]string) |
| 91 | } | 103 | } |
| 92 | } else { | 104 | continue |
| 93 | if _, ok := cfg.data[section]; !ok { | 105 | } |
| 94 | cfg.data[section] = make(map[string]string) | ||
| 95 | } | ||
| 96 | keyval := bytes.SplitN(line, bEqual, 2) | ||
| 97 | val := bytes.TrimSpace(keyval[1]) | ||
| 98 | if bytes.HasPrefix(val, bDQuote) { | ||
| 99 | val = bytes.Trim(val, `"`) | ||
| 100 | } | ||
| 101 | 106 | ||
| 102 | key := string(bytes.TrimSpace(keyval[0])) // key name case insensitive | 107 | if _, ok := cfg.data[section]; !ok { |
| 103 | key = strings.ToLower(key) | 108 | cfg.data[section] = make(map[string]string) |
| 104 | cfg.data[section][key] = string(val) | 109 | } |
| 105 | if comment.Len() > 0 { | 110 | keyValue := bytes.SplitN(line, bEqual, 2) |
| 106 | cfg.keycomment[section+"."+key] = comment.String() | 111 | val := bytes.TrimSpace(keyValue[1]) |
| 107 | comment.Reset() | 112 | if bytes.HasPrefix(val, bDQuote) { |
| 108 | } | 113 | val = bytes.Trim(val, `"`) |
| 114 | } | ||
| 115 | |||
| 116 | key := string(bytes.TrimSpace(keyValue[0])) // key name case insensitive | ||
| 117 | key = strings.ToLower(key) | ||
| 118 | cfg.data[section][key] = string(val) | ||
| 119 | if comment.Len() > 0 { | ||
| 120 | cfg.keyComment[section+"."+key] = comment.String() | ||
| 121 | comment.Reset() | ||
| 109 | } | 122 | } |
| 110 | 123 | ||
| 111 | } | 124 | } |
| 112 | return cfg, nil | 125 | return cfg, nil |
| 113 | } | 126 | } |
| 114 | 127 | ||
| 128 | func (ini *IniConfig) ParseData(data []byte) (ConfigContainer, error) { | ||
| 129 | // Save memory data to temporary file | ||
| 130 | tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) | ||
| 131 | os.MkdirAll(path.Dir(tmpName), os.ModePerm) | ||
| 132 | if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { | ||
| 133 | return nil, err | ||
| 134 | } | ||
| 135 | return ini.Parse(tmpName) | ||
| 136 | } | ||
| 137 | |||
| 115 | // A Config represents the ini configuration. | 138 | // A Config represents the ini configuration. |
| 116 | // When set and get value, support key as section:name type. | 139 | // When set and get value, support key as section:name type. |
| 117 | type IniConfigContainer struct { | 140 | type IniConfigContainer struct { |
| 118 | filename string | 141 | filename string |
| 119 | data map[string]map[string]string // section=> key:val | 142 | data map[string]map[string]string // section=> key:val |
| 120 | sectionComment map[string]string // section : comment | 143 | sectionComment map[string]string // section : comment |
| 121 | keycomment map[string]string // id: []{comment, key...}; id 1 is for main comment. | 144 | keyComment map[string]string // id: []{comment, key...}; id 1 is for main comment. |
| 122 | sync.RWMutex | 145 | sync.RWMutex |
| 123 | } | 146 | } |
| 124 | 147 | ||
| 125 | // Bool returns the boolean value for a given key. | 148 | // Bool returns the boolean value for a given key. |
| 126 | func (c *IniConfigContainer) Bool(key string) (bool, error) { | 149 | func (c *IniConfigContainer) Bool(key string) (bool, error) { |
| 127 | key = strings.ToLower(key) | 150 | return strconv.ParseBool(c.getdata(strings.ToLower(key))) |
| 128 | return strconv.ParseBool(c.getdata(key)) | 151 | } |
| 152 | |||
| 153 | // DefaultBool returns the boolean value for a given key. | ||
| 154 | // if err != nil return defaltval | ||
| 155 | func (c *IniConfigContainer) DefaultBool(key string, defaultval bool) bool { | ||
| 156 | if v, err := c.Bool(key); err != nil { | ||
| 157 | return defaultval | ||
| 158 | } else { | ||
| 159 | return v | ||
| 160 | } | ||
| 129 | } | 161 | } |
| 130 | 162 | ||
| 131 | // Int returns the integer value for a given key. | 163 | // Int returns the integer value for a given key. |
| 132 | func (c *IniConfigContainer) Int(key string) (int, error) { | 164 | func (c *IniConfigContainer) Int(key string) (int, error) { |
| 133 | key = strings.ToLower(key) | 165 | return strconv.Atoi(c.getdata(strings.ToLower(key))) |
| 134 | return strconv.Atoi(c.getdata(key)) | 166 | } |
| 167 | |||
| 168 | // DefaultInt returns the integer value for a given key. | ||
| 169 | // if err != nil return defaltval | ||
| 170 | func (c *IniConfigContainer) DefaultInt(key string, defaultval int) int { | ||
| 171 | if v, err := c.Int(key); err != nil { | ||
| 172 | return defaultval | ||
| 173 | } else { | ||
| 174 | return v | ||
| 175 | } | ||
| 135 | } | 176 | } |
| 136 | 177 | ||
| 137 | // Int64 returns the int64 value for a given key. | 178 | // Int64 returns the int64 value for a given key. |
| 138 | func (c *IniConfigContainer) Int64(key string) (int64, error) { | 179 | func (c *IniConfigContainer) Int64(key string) (int64, error) { |
| 139 | key = strings.ToLower(key) | 180 | return strconv.ParseInt(c.getdata(strings.ToLower(key)), 10, 64) |
| 140 | return strconv.ParseInt(c.getdata(key), 10, 64) | 181 | } |
| 182 | |||
| 183 | // DefaultInt64 returns the int64 value for a given key. | ||
| 184 | // if err != nil return defaltval | ||
| 185 | func (c *IniConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | ||
| 186 | if v, err := c.Int64(key); err != nil { | ||
| 187 | return defaultval | ||
| 188 | } else { | ||
| 189 | return v | ||
| 190 | } | ||
| 141 | } | 191 | } |
| 142 | 192 | ||
| 143 | // Float returns the float value for a given key. | 193 | // Float returns the float value for a given key. |
| 144 | func (c *IniConfigContainer) Float(key string) (float64, error) { | 194 | func (c *IniConfigContainer) Float(key string) (float64, error) { |
| 145 | key = strings.ToLower(key) | 195 | return strconv.ParseFloat(c.getdata(strings.ToLower(key)), 64) |
| 146 | return strconv.ParseFloat(c.getdata(key), 64) | 196 | } |
| 197 | |||
| 198 | // DefaultFloat returns the float64 value for a given key. | ||
| 199 | // if err != nil return defaltval | ||
| 200 | func (c *IniConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | ||
| 201 | if v, err := c.Float(key); err != nil { | ||
| 202 | return defaultval | ||
| 203 | } else { | ||
| 204 | return v | ||
| 205 | } | ||
| 147 | } | 206 | } |
| 148 | 207 | ||
| 149 | // String returns the string value for a given key. | 208 | // String returns the string value for a given key. |
| 150 | func (c *IniConfigContainer) String(key string) string { | 209 | func (c *IniConfigContainer) String(key string) string { |
| 151 | key = strings.ToLower(key) | 210 | key = strings.ToLower(key) |
| 152 | return c.getdata(key) | 211 | return c.getdata(strings.ToLower(key)) |
| 212 | } | ||
| 213 | |||
| 214 | // DefaultString returns the string value for a given key. | ||
| 215 | // if err != nil return defaltval | ||
| 216 | func (c *IniConfigContainer) DefaultString(key string, defaultval string) string { | ||
| 217 | if v := c.String(key); v == "" { | ||
| 218 | return defaultval | ||
| 219 | } else { | ||
| 220 | return v | ||
| 221 | } | ||
| 153 | } | 222 | } |
| 154 | 223 | ||
| 155 | // Strings returns the []string value for a given key. | 224 | // Strings returns the []string value for a given key. |
| ... | @@ -157,6 +226,78 @@ func (c *IniConfigContainer) Strings(key string) []string { | ... | @@ -157,6 +226,78 @@ func (c *IniConfigContainer) Strings(key string) []string { |
| 157 | return strings.Split(c.String(key), ";") | 226 | return strings.Split(c.String(key), ";") |
| 158 | } | 227 | } |
| 159 | 228 | ||
| 229 | // DefaultStrings returns the []string value for a given key. | ||
| 230 | // if err != nil return defaltval | ||
| 231 | func (c *IniConfigContainer) DefaultStrings(key string, defaultval []string) []string { | ||
| 232 | if v := c.Strings(key); len(v) == 0 { | ||
| 233 | return defaultval | ||
| 234 | } else { | ||
| 235 | return v | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // GetSection returns map for the given section | ||
| 240 | func (c *IniConfigContainer) GetSection(section string) (map[string]string, error) { | ||
| 241 | if v, ok := c.data[section]; ok { | ||
| 242 | return v, nil | ||
| 243 | } else { | ||
| 244 | return nil, errors.New("not exist setction") | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | // SaveConfigFile save the config into file | ||
| 249 | func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) { | ||
| 250 | // Write configuration file by filename. | ||
| 251 | f, err := os.Create(filename) | ||
| 252 | if err != nil { | ||
| 253 | return err | ||
| 254 | } | ||
| 255 | defer f.Close() | ||
| 256 | |||
| 257 | buf := bytes.NewBuffer(nil) | ||
| 258 | for section, dt := range c.data { | ||
| 259 | // Write section comments. | ||
| 260 | if v, ok := c.sectionComment[section]; ok { | ||
| 261 | if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil { | ||
| 262 | return err | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | if section != DEFAULT_SECTION { | ||
| 267 | // Write section name. | ||
| 268 | if _, err = buf.WriteString(string(sectionStart) + section + string(sectionEnd) + lineBreak); err != nil { | ||
| 269 | return err | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | for key, val := range dt { | ||
| 274 | if key != " " { | ||
| 275 | // Write key comments. | ||
| 276 | if v, ok := c.keyComment[key]; ok { | ||
| 277 | if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil { | ||
| 278 | return err | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | // Write key and value. | ||
| 283 | if _, err = buf.WriteString(key + string(bEqual) + val + lineBreak); err != nil { | ||
| 284 | return err | ||
| 285 | } | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | // Put a line between sections. | ||
| 290 | if _, err = buf.WriteString(lineBreak); err != nil { | ||
| 291 | return err | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | if _, err = buf.WriteTo(f); err != nil { | ||
| 296 | return err | ||
| 297 | } | ||
| 298 | return nil | ||
| 299 | } | ||
| 300 | |||
| 160 | // WriteValue writes a new value for key. | 301 | // WriteValue writes a new value for key. |
| 161 | // if write to one section, the key need be "section::key". | 302 | // if write to one section, the key need be "section::key". |
| 162 | // if the section is not existed, it panics. | 303 | // if the section is not existed, it panics. |
| ... | @@ -167,16 +308,19 @@ func (c *IniConfigContainer) Set(key, value string) error { | ... | @@ -167,16 +308,19 @@ func (c *IniConfigContainer) Set(key, value string) error { |
| 167 | return errors.New("key is empty") | 308 | return errors.New("key is empty") |
| 168 | } | 309 | } |
| 169 | 310 | ||
| 170 | var section, k string | 311 | var ( |
| 171 | key = strings.ToLower(key) | 312 | section, k string |
| 172 | sectionkey := strings.Split(key, "::") | 313 | sectionKey []string = strings.Split(key, "::") |
| 173 | if len(sectionkey) >= 2 { | 314 | ) |
| 174 | section = sectionkey[0] | 315 | |
| 175 | k = sectionkey[1] | 316 | if len(sectionKey) >= 2 { |
| 317 | section = sectionKey[0] | ||
| 318 | k = sectionKey[1] | ||
| 176 | } else { | 319 | } else { |
| 177 | section = DEFAULT_SECTION | 320 | section = DEFAULT_SECTION |
| 178 | k = sectionkey[0] | 321 | k = sectionKey[0] |
| 179 | } | 322 | } |
| 323 | |||
| 180 | if _, ok := c.data[section]; !ok { | 324 | if _, ok := c.data[section]; !ok { |
| 181 | c.data[section] = make(map[string]string) | 325 | c.data[section] = make(map[string]string) |
| 182 | } | 326 | } |
| ... | @@ -186,8 +330,7 @@ func (c *IniConfigContainer) Set(key, value string) error { | ... | @@ -186,8 +330,7 @@ func (c *IniConfigContainer) Set(key, value string) error { |
| 186 | 330 | ||
| 187 | // DIY returns the raw value by a given key. | 331 | // DIY returns the raw value by a given key. |
| 188 | func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) { | 332 | func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) { |
| 189 | key = strings.ToLower(key) | 333 | if v, ok := c.data[strings.ToLower(key)]; ok { |
| 190 | if v, ok := c.data[key]; ok { | ||
| 191 | return v, nil | 334 | return v, nil |
| 192 | } | 335 | } |
| 193 | return v, errors.New("key not find") | 336 | return v, errors.New("key not find") |
| ... | @@ -201,18 +344,19 @@ func (c *IniConfigContainer) getdata(key string) string { | ... | @@ -201,18 +344,19 @@ func (c *IniConfigContainer) getdata(key string) string { |
| 201 | return "" | 344 | return "" |
| 202 | } | 345 | } |
| 203 | 346 | ||
| 204 | var section, k string | 347 | var ( |
| 205 | key = strings.ToLower(key) | 348 | section, k string |
| 206 | sectionkey := strings.Split(key, "::") | 349 | sectionKey []string = strings.Split(key, "::") |
| 207 | if len(sectionkey) >= 2 { | 350 | ) |
| 208 | section = sectionkey[0] | 351 | if len(sectionKey) >= 2 { |
| 209 | k = sectionkey[1] | 352 | section = sectionKey[0] |
| 353 | k = sectionKey[1] | ||
| 210 | } else { | 354 | } else { |
| 211 | section = DEFAULT_SECTION | 355 | section = DEFAULT_SECTION |
| 212 | k = sectionkey[0] | 356 | k = sectionKey[0] |
| 213 | } | 357 | } |
| 214 | if v, ok := c.data[section]; ok { | 358 | if v, ok := c.data[section]; ok { |
| 215 | if vv, o := v[k]; o { | 359 | if vv, ok := v[k]; ok { |
| 216 | return vv | 360 | return vv |
| 217 | } | 361 | } |
| 218 | } | 362 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package config |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package config |
| 8 | 16 | ||
| 9 | import ( | 17 | import ( |
| 10 | "encoding/json" | 18 | "encoding/json" |
| 11 | "errors" | 19 | "errors" |
| 20 | "fmt" | ||
| 12 | "io/ioutil" | 21 | "io/ioutil" |
| 13 | "os" | 22 | "os" |
| 23 | "path" | ||
| 14 | "strings" | 24 | "strings" |
| 15 | "sync" | 25 | "sync" |
| 26 | "time" | ||
| 16 | ) | 27 | ) |
| 17 | 28 | ||
| 18 | // JsonConfig is a json config parser and implements Config interface. | 29 | // JsonConfig is a json config parser and implements Config interface. |
| ... | @@ -26,13 +37,13 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { | ... | @@ -26,13 +37,13 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { |
| 26 | return nil, err | 37 | return nil, err |
| 27 | } | 38 | } |
| 28 | defer file.Close() | 39 | defer file.Close() |
| 29 | x := &JsonConfigContainer{ | ||
| 30 | data: make(map[string]interface{}), | ||
| 31 | } | ||
| 32 | content, err := ioutil.ReadAll(file) | 40 | content, err := ioutil.ReadAll(file) |
| 33 | if err != nil { | 41 | if err != nil { |
| 34 | return nil, err | 42 | return nil, err |
| 35 | } | 43 | } |
| 44 | x := &JsonConfigContainer{ | ||
| 45 | data: make(map[string]interface{}), | ||
| 46 | } | ||
| 36 | err = json.Unmarshal(content, &x.data) | 47 | err = json.Unmarshal(content, &x.data) |
| 37 | if err != nil { | 48 | if err != nil { |
| 38 | var wrappingArray []interface{} | 49 | var wrappingArray []interface{} |
| ... | @@ -45,6 +56,16 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { | ... | @@ -45,6 +56,16 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { |
| 45 | return x, nil | 56 | return x, nil |
| 46 | } | 57 | } |
| 47 | 58 | ||
| 59 | func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { | ||
| 60 | // Save memory data to temporary file | ||
| 61 | tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) | ||
| 62 | os.MkdirAll(path.Dir(tmpName), os.ModePerm) | ||
| 63 | if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { | ||
| 64 | return nil, err | ||
| 65 | } | ||
| 66 | return js.Parse(tmpName) | ||
| 67 | } | ||
| 68 | |||
| 48 | // A Config represents the json configuration. | 69 | // A Config represents the json configuration. |
| 49 | // Only when get value, support key as section:name type. | 70 | // Only when get value, support key as section:name type. |
| 50 | type JsonConfigContainer struct { | 71 | type JsonConfigContainer struct { |
| ... | @@ -54,71 +75,110 @@ type JsonConfigContainer struct { | ... | @@ -54,71 +75,110 @@ type JsonConfigContainer struct { |
| 54 | 75 | ||
| 55 | // Bool returns the boolean value for a given key. | 76 | // Bool returns the boolean value for a given key. |
| 56 | func (c *JsonConfigContainer) Bool(key string) (bool, error) { | 77 | func (c *JsonConfigContainer) Bool(key string) (bool, error) { |
| 57 | val := c.getdata(key) | 78 | val := c.getData(key) |
| 58 | if val != nil { | 79 | if val != nil { |
| 59 | if v, ok := val.(bool); ok { | 80 | if v, ok := val.(bool); ok { |
| 60 | return v, nil | 81 | return v, nil |
| 61 | } else { | ||
| 62 | return false, errors.New("not bool value") | ||
| 63 | } | 82 | } |
| 83 | return false, errors.New("not bool value") | ||
| 84 | } | ||
| 85 | return false, errors.New("not exist key:" + key) | ||
| 86 | } | ||
| 87 | |||
| 88 | // DefaultBool return the bool value if has no error | ||
| 89 | // otherwise return the defaultval | ||
| 90 | func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { | ||
| 91 | if v, err := c.Bool(key); err != nil { | ||
| 92 | return defaultval | ||
| 64 | } else { | 93 | } else { |
| 65 | return false, errors.New("not exist key:" + key) | 94 | return v |
| 66 | } | 95 | } |
| 67 | } | 96 | } |
| 68 | 97 | ||
| 69 | // Int returns the integer value for a given key. | 98 | // Int returns the integer value for a given key. |
| 70 | func (c *JsonConfigContainer) Int(key string) (int, error) { | 99 | func (c *JsonConfigContainer) Int(key string) (int, error) { |
| 71 | val := c.getdata(key) | 100 | val := c.getData(key) |
| 72 | if val != nil { | 101 | if val != nil { |
| 73 | if v, ok := val.(float64); ok { | 102 | if v, ok := val.(float64); ok { |
| 74 | return int(v), nil | 103 | return int(v), nil |
| 75 | } else { | ||
| 76 | return 0, errors.New("not int value") | ||
| 77 | } | 104 | } |
| 105 | return 0, errors.New("not int value") | ||
| 106 | } | ||
| 107 | return 0, errors.New("not exist key:" + key) | ||
| 108 | } | ||
| 109 | |||
| 110 | // DefaultInt returns the integer value for a given key. | ||
| 111 | // if err != nil return defaltval | ||
| 112 | func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { | ||
| 113 | if v, err := c.Int(key); err != nil { | ||
| 114 | return defaultval | ||
| 78 | } else { | 115 | } else { |
| 79 | return 0, errors.New("not exist key:" + key) | 116 | return v |
| 80 | } | 117 | } |
| 81 | } | 118 | } |
| 82 | 119 | ||
| 83 | // Int64 returns the int64 value for a given key. | 120 | // Int64 returns the int64 value for a given key. |
| 84 | func (c *JsonConfigContainer) Int64(key string) (int64, error) { | 121 | func (c *JsonConfigContainer) Int64(key string) (int64, error) { |
| 85 | val := c.getdata(key) | 122 | val := c.getData(key) |
| 86 | if val != nil { | 123 | if val != nil { |
| 87 | if v, ok := val.(float64); ok { | 124 | if v, ok := val.(float64); ok { |
| 88 | return int64(v), nil | 125 | return int64(v), nil |
| 89 | } else { | ||
| 90 | return 0, errors.New("not int64 value") | ||
| 91 | } | 126 | } |
| 127 | return 0, errors.New("not int64 value") | ||
| 128 | } | ||
| 129 | return 0, errors.New("not exist key:" + key) | ||
| 130 | } | ||
| 131 | |||
| 132 | // DefaultInt64 returns the int64 value for a given key. | ||
| 133 | // if err != nil return defaltval | ||
| 134 | func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | ||
| 135 | if v, err := c.Int64(key); err != nil { | ||
| 136 | return defaultval | ||
| 92 | } else { | 137 | } else { |
| 93 | return 0, errors.New("not exist key:" + key) | 138 | return v |
| 94 | } | 139 | } |
| 95 | } | 140 | } |
| 96 | 141 | ||
| 97 | // Float returns the float value for a given key. | 142 | // Float returns the float value for a given key. |
| 98 | func (c *JsonConfigContainer) Float(key string) (float64, error) { | 143 | func (c *JsonConfigContainer) Float(key string) (float64, error) { |
| 99 | val := c.getdata(key) | 144 | val := c.getData(key) |
| 100 | if val != nil { | 145 | if val != nil { |
| 101 | if v, ok := val.(float64); ok { | 146 | if v, ok := val.(float64); ok { |
| 102 | return v, nil | 147 | return v, nil |
| 103 | } else { | ||
| 104 | return 0.0, errors.New("not float64 value") | ||
| 105 | } | 148 | } |
| 149 | return 0.0, errors.New("not float64 value") | ||
| 150 | } | ||
| 151 | return 0.0, errors.New("not exist key:" + key) | ||
| 152 | } | ||
| 153 | |||
| 154 | // DefaultFloat returns the float64 value for a given key. | ||
| 155 | // if err != nil return defaltval | ||
| 156 | func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | ||
| 157 | if v, err := c.Float(key); err != nil { | ||
| 158 | return defaultval | ||
| 106 | } else { | 159 | } else { |
| 107 | return 0.0, errors.New("not exist key:" + key) | 160 | return v |
| 108 | } | 161 | } |
| 109 | } | 162 | } |
| 110 | 163 | ||
| 111 | // String returns the string value for a given key. | 164 | // String returns the string value for a given key. |
| 112 | func (c *JsonConfigContainer) String(key string) string { | 165 | func (c *JsonConfigContainer) String(key string) string { |
| 113 | val := c.getdata(key) | 166 | val := c.getData(key) |
| 114 | if val != nil { | 167 | if val != nil { |
| 115 | if v, ok := val.(string); ok { | 168 | if v, ok := val.(string); ok { |
| 116 | return v | 169 | return v |
| 117 | } else { | ||
| 118 | return "" | ||
| 119 | } | 170 | } |
| 171 | } | ||
| 172 | return "" | ||
| 173 | } | ||
| 174 | |||
| 175 | // DefaultString returns the string value for a given key. | ||
| 176 | // if err != nil return defaltval | ||
| 177 | func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { | ||
| 178 | if v := c.String(key); v == "" { | ||
| 179 | return defaultval | ||
| 120 | } else { | 180 | } else { |
| 121 | return "" | 181 | return v |
| 122 | } | 182 | } |
| 123 | } | 183 | } |
| 124 | 184 | ||
| ... | @@ -127,6 +187,41 @@ func (c *JsonConfigContainer) Strings(key string) []string { | ... | @@ -127,6 +187,41 @@ func (c *JsonConfigContainer) Strings(key string) []string { |
| 127 | return strings.Split(c.String(key), ";") | 187 | return strings.Split(c.String(key), ";") |
| 128 | } | 188 | } |
| 129 | 189 | ||
| 190 | // DefaultStrings returns the []string value for a given key. | ||
| 191 | // if err != nil return defaltval | ||
| 192 | func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { | ||
| 193 | if v := c.Strings(key); len(v) == 0 { | ||
| 194 | return defaultval | ||
| 195 | } else { | ||
| 196 | return v | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | // GetSection returns map for the given section | ||
| 201 | func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { | ||
| 202 | if v, ok := c.data[section]; ok { | ||
| 203 | return v.(map[string]string), nil | ||
| 204 | } else { | ||
| 205 | return nil, errors.New("not exist setction") | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | // SaveConfigFile save the config into file | ||
| 210 | func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { | ||
| 211 | // Write configuration file by filename. | ||
| 212 | f, err := os.Create(filename) | ||
| 213 | if err != nil { | ||
| 214 | return err | ||
| 215 | } | ||
| 216 | defer f.Close() | ||
| 217 | b, err := json.MarshalIndent(c.data, "", " ") | ||
| 218 | if err != nil { | ||
| 219 | return err | ||
| 220 | } | ||
| 221 | _, err = f.Write(b) | ||
| 222 | return err | ||
| 223 | } | ||
| 224 | |||
| 130 | // WriteValue writes a new value for key. | 225 | // WriteValue writes a new value for key. |
| 131 | func (c *JsonConfigContainer) Set(key, val string) error { | 226 | func (c *JsonConfigContainer) Set(key, val string) error { |
| 132 | c.Lock() | 227 | c.Lock() |
| ... | @@ -137,39 +232,37 @@ func (c *JsonConfigContainer) Set(key, val string) error { | ... | @@ -137,39 +232,37 @@ func (c *JsonConfigContainer) Set(key, val string) error { |
| 137 | 232 | ||
| 138 | // DIY returns the raw value by a given key. | 233 | // DIY returns the raw value by a given key. |
| 139 | func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { | 234 | func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { |
| 140 | val := c.getdata(key) | 235 | val := c.getData(key) |
| 141 | if val != nil { | 236 | if val != nil { |
| 142 | return val, nil | 237 | return val, nil |
| 143 | } else { | ||
| 144 | return nil, errors.New("not exist key") | ||
| 145 | } | 238 | } |
| 239 | return nil, errors.New("not exist key") | ||
| 146 | } | 240 | } |
| 147 | 241 | ||
| 148 | // section.key or key | 242 | // section.key or key |
| 149 | func (c *JsonConfigContainer) getdata(key string) interface{} { | 243 | func (c *JsonConfigContainer) getData(key string) interface{} { |
| 150 | c.RLock() | 244 | c.RLock() |
| 151 | defer c.RUnlock() | 245 | defer c.RUnlock() |
| 152 | if len(key) == 0 { | 246 | if len(key) == 0 { |
| 153 | return nil | 247 | return nil |
| 154 | } | 248 | } |
| 155 | sectionkey := strings.Split(key, "::") | 249 | sectionKey := strings.Split(key, "::") |
| 156 | if len(sectionkey) >= 2 { | 250 | if len(sectionKey) >= 2 { |
| 157 | cruval, ok := c.data[sectionkey[0]] | 251 | curValue, ok := c.data[sectionKey[0]] |
| 158 | if !ok { | 252 | if !ok { |
| 159 | return nil | 253 | return nil |
| 160 | } | 254 | } |
| 161 | for _, key := range sectionkey[1:] { | 255 | for _, key := range sectionKey[1:] { |
| 162 | if v, ok := cruval.(map[string]interface{}); !ok { | 256 | if v, ok := curValue.(map[string]interface{}); ok { |
| 163 | return nil | 257 | if curValue, ok = v[key]; !ok { |
| 164 | } else if cruval, ok = v[key]; !ok { | 258 | return nil |
| 165 | return nil | 259 | } |
| 166 | } | 260 | } |
| 167 | } | 261 | } |
| 168 | return cruval | 262 | return curValue |
| 169 | } else { | 263 | } |
| 170 | if v, ok := c.data[key]; ok { | 264 | if v, ok := c.data[key]; ok { |
| 171 | return v | 265 | return v |
| 172 | } | ||
| 173 | } | 266 | } |
| 174 | return nil | 267 | return nil |
| 175 | } | 268 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package config |
| 8 | 16 | ||
| ... | @@ -61,13 +69,13 @@ func TestJsonStartsWithArray(t *testing.T) { | ... | @@ -61,13 +69,13 @@ func TestJsonStartsWithArray(t *testing.T) { |
| 61 | t.Fatal(err) | 69 | t.Fatal(err) |
| 62 | } | 70 | } |
| 63 | rootArray, err := jsonconf.DIY("rootArray") | 71 | rootArray, err := jsonconf.DIY("rootArray") |
| 64 | if (err != nil) { | 72 | if err != nil { |
| 65 | t.Error("array does not exist as element") | 73 | t.Error("array does not exist as element") |
| 66 | } | 74 | } |
| 67 | rootArrayCasted := rootArray.([]interface{}) | 75 | rootArrayCasted := rootArray.([]interface{}) |
| 68 | if (rootArrayCasted == nil) { | 76 | if rootArrayCasted == nil { |
| 69 | t.Error("array from root is nil") | 77 | t.Error("array from root is nil") |
| 70 | }else { | 78 | } else { |
| 71 | elem := rootArrayCasted[0].(map[string]interface{}) | 79 | elem := rootArrayCasted[0].(map[string]interface{}) |
| 72 | if elem["url"] != "user" || elem["serviceAPI"] != "http://www.test.com/user" { | 80 | if elem["url"] != "user" || elem["serviceAPI"] != "http://www.test.com/user" { |
| 73 | t.Error("array[0] values are not valid") | 81 | t.Error("array[0] values are not valid") | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | // package xml for config provider |
| 16 | // | ||
| 17 | // depend on github.com/beego/x2j | ||
| 18 | // | ||
| 19 | // go install github.com/beego/x2j | ||
| 20 | // | ||
| 21 | // Usage: | ||
| 22 | // import( | ||
| 23 | // _ "github.com/astaxie/beego/config/xml" | ||
| 24 | // "github.com/astaxie/beego/config" | ||
| 25 | // ) | ||
| 26 | // | ||
| 27 | // cnf, err := config.NewConfig("xml", "config.xml") | ||
| 28 | // | ||
| 29 | // more docs http://beego.me/docs/module/config.md | ||
| 30 | package xml | ||
| 8 | 31 | ||
| 9 | import ( | 32 | import ( |
| 33 | "encoding/xml" | ||
| 10 | "errors" | 34 | "errors" |
| 35 | "fmt" | ||
| 11 | "io/ioutil" | 36 | "io/ioutil" |
| 12 | "os" | 37 | "os" |
| 38 | "path" | ||
| 13 | "strconv" | 39 | "strconv" |
| 14 | "strings" | 40 | "strings" |
| 15 | "sync" | 41 | "sync" |
| 42 | "time" | ||
| 16 | 43 | ||
| 17 | "github.com/astaxie/beego/config" | 44 | "github.com/astaxie/beego/config" |
| 18 | "github.com/beego/x2j" | 45 | "github.com/beego/x2j" |
| ... | @@ -21,31 +48,41 @@ import ( | ... | @@ -21,31 +48,41 @@ import ( |
| 21 | // XmlConfig is a xml config parser and implements Config interface. | 48 | // XmlConfig is a xml config parser and implements Config interface. |
| 22 | // xml configurations should be included in <config></config> tag. | 49 | // xml configurations should be included in <config></config> tag. |
| 23 | // only support key/value pair as <key>value</key> as each item. | 50 | // only support key/value pair as <key>value</key> as each item. |
| 24 | type XMLConfig struct { | 51 | type XMLConfig struct{} |
| 25 | } | ||
| 26 | 52 | ||
| 27 | // Parse returns a ConfigContainer with parsed xml config map. | 53 | // Parse returns a ConfigContainer with parsed xml config map. |
| 28 | func (xmls *XMLConfig) Parse(filename string) (config.ConfigContainer, error) { | 54 | func (xc *XMLConfig) Parse(filename string) (config.ConfigContainer, error) { |
| 29 | file, err := os.Open(filename) | 55 | file, err := os.Open(filename) |
| 30 | if err != nil { | 56 | if err != nil { |
| 31 | return nil, err | 57 | return nil, err |
| 32 | } | 58 | } |
| 33 | defer file.Close() | 59 | defer file.Close() |
| 34 | x := &XMLConfigContainer{ | 60 | |
| 35 | data: make(map[string]interface{}), | 61 | x := &XMLConfigContainer{data: make(map[string]interface{})} |
| 36 | } | ||
| 37 | content, err := ioutil.ReadAll(file) | 62 | content, err := ioutil.ReadAll(file) |
| 38 | if err != nil { | 63 | if err != nil { |
| 39 | return nil, err | 64 | return nil, err |
| 40 | } | 65 | } |
| 66 | |||
| 41 | d, err := x2j.DocToMap(string(content)) | 67 | d, err := x2j.DocToMap(string(content)) |
| 42 | if err != nil { | 68 | if err != nil { |
| 43 | return nil, err | 69 | return nil, err |
| 44 | } | 70 | } |
| 71 | |||
| 45 | x.data = d["config"].(map[string]interface{}) | 72 | x.data = d["config"].(map[string]interface{}) |
| 46 | return x, nil | 73 | return x, nil |
| 47 | } | 74 | } |
| 48 | 75 | ||
| 76 | func (x *XMLConfig) ParseData(data []byte) (config.ConfigContainer, error) { | ||
| 77 | // Save memory data to temporary file | ||
| 78 | tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) | ||
| 79 | os.MkdirAll(path.Dir(tmpName), os.ModePerm) | ||
| 80 | if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { | ||
| 81 | return nil, err | ||
| 82 | } | ||
| 83 | return x.Parse(tmpName) | ||
| 84 | } | ||
| 85 | |||
| 49 | // A Config represents the xml configuration. | 86 | // A Config represents the xml configuration. |
| 50 | type XMLConfigContainer struct { | 87 | type XMLConfigContainer struct { |
| 51 | data map[string]interface{} | 88 | data map[string]interface{} |
| ... | @@ -57,21 +94,61 @@ func (c *XMLConfigContainer) Bool(key string) (bool, error) { | ... | @@ -57,21 +94,61 @@ func (c *XMLConfigContainer) Bool(key string) (bool, error) { |
| 57 | return strconv.ParseBool(c.data[key].(string)) | 94 | return strconv.ParseBool(c.data[key].(string)) |
| 58 | } | 95 | } |
| 59 | 96 | ||
| 97 | // DefaultBool return the bool value if has no error | ||
| 98 | // otherwise return the defaultval | ||
| 99 | func (c *XMLConfigContainer) DefaultBool(key string, defaultval bool) bool { | ||
| 100 | if v, err := c.Bool(key); err != nil { | ||
| 101 | return defaultval | ||
| 102 | } else { | ||
| 103 | return v | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 60 | // Int returns the integer value for a given key. | 107 | // Int returns the integer value for a given key. |
| 61 | func (c *XMLConfigContainer) Int(key string) (int, error) { | 108 | func (c *XMLConfigContainer) Int(key string) (int, error) { |
| 62 | return strconv.Atoi(c.data[key].(string)) | 109 | return strconv.Atoi(c.data[key].(string)) |
| 63 | } | 110 | } |
| 64 | 111 | ||
| 112 | // DefaultInt returns the integer value for a given key. | ||
| 113 | // if err != nil return defaltval | ||
| 114 | func (c *XMLConfigContainer) DefaultInt(key string, defaultval int) int { | ||
| 115 | if v, err := c.Int(key); err != nil { | ||
| 116 | return defaultval | ||
| 117 | } else { | ||
| 118 | return v | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 65 | // Int64 returns the int64 value for a given key. | 122 | // Int64 returns the int64 value for a given key. |
| 66 | func (c *XMLConfigContainer) Int64(key string) (int64, error) { | 123 | func (c *XMLConfigContainer) Int64(key string) (int64, error) { |
| 67 | return strconv.ParseInt(c.data[key].(string), 10, 64) | 124 | return strconv.ParseInt(c.data[key].(string), 10, 64) |
| 68 | } | 125 | } |
| 69 | 126 | ||
| 127 | // DefaultInt64 returns the int64 value for a given key. | ||
| 128 | // if err != nil return defaltval | ||
| 129 | func (c *XMLConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | ||
| 130 | if v, err := c.Int64(key); err != nil { | ||
| 131 | return defaultval | ||
| 132 | } else { | ||
| 133 | return v | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 70 | // Float returns the float value for a given key. | 137 | // Float returns the float value for a given key. |
| 71 | func (c *XMLConfigContainer) Float(key string) (float64, error) { | 138 | func (c *XMLConfigContainer) Float(key string) (float64, error) { |
| 72 | return strconv.ParseFloat(c.data[key].(string), 64) | 139 | return strconv.ParseFloat(c.data[key].(string), 64) |
| 73 | } | 140 | } |
| 74 | 141 | ||
| 142 | // DefaultFloat returns the float64 value for a given key. | ||
| 143 | // if err != nil return defaltval | ||
| 144 | func (c *XMLConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | ||
| 145 | if v, err := c.Float(key); err != nil { | ||
| 146 | return defaultval | ||
| 147 | } else { | ||
| 148 | return v | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 75 | // String returns the string value for a given key. | 152 | // String returns the string value for a given key. |
| 76 | func (c *XMLConfigContainer) String(key string) string { | 153 | func (c *XMLConfigContainer) String(key string) string { |
| 77 | if v, ok := c.data[key].(string); ok { | 154 | if v, ok := c.data[key].(string); ok { |
| ... | @@ -80,11 +157,56 @@ func (c *XMLConfigContainer) String(key string) string { | ... | @@ -80,11 +157,56 @@ func (c *XMLConfigContainer) String(key string) string { |
| 80 | return "" | 157 | return "" |
| 81 | } | 158 | } |
| 82 | 159 | ||
| 160 | // DefaultString returns the string value for a given key. | ||
| 161 | // if err != nil return defaltval | ||
| 162 | func (c *XMLConfigContainer) DefaultString(key string, defaultval string) string { | ||
| 163 | if v := c.String(key); v == "" { | ||
| 164 | return defaultval | ||
| 165 | } else { | ||
| 166 | return v | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 83 | // Strings returns the []string value for a given key. | 170 | // Strings returns the []string value for a given key. |
| 84 | func (c *XMLConfigContainer) Strings(key string) []string { | 171 | func (c *XMLConfigContainer) Strings(key string) []string { |
| 85 | return strings.Split(c.String(key), ";") | 172 | return strings.Split(c.String(key), ";") |
| 86 | } | 173 | } |
| 87 | 174 | ||
| 175 | // DefaultStrings returns the []string value for a given key. | ||
| 176 | // if err != nil return defaltval | ||
| 177 | func (c *XMLConfigContainer) DefaultStrings(key string, defaultval []string) []string { | ||
| 178 | if v := c.Strings(key); len(v) == 0 { | ||
| 179 | return defaultval | ||
| 180 | } else { | ||
| 181 | return v | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | // GetSection returns map for the given section | ||
| 186 | func (c *XMLConfigContainer) GetSection(section string) (map[string]string, error) { | ||
| 187 | if v, ok := c.data[section]; ok { | ||
| 188 | return v.(map[string]string), nil | ||
| 189 | } else { | ||
| 190 | return nil, errors.New("not exist setction") | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | // SaveConfigFile save the config into file | ||
| 195 | func (c *XMLConfigContainer) SaveConfigFile(filename string) (err error) { | ||
| 196 | // Write configuration file by filename. | ||
| 197 | f, err := os.Create(filename) | ||
| 198 | if err != nil { | ||
| 199 | return err | ||
| 200 | } | ||
| 201 | defer f.Close() | ||
| 202 | b, err := xml.MarshalIndent(c.data, " ", " ") | ||
| 203 | if err != nil { | ||
| 204 | return err | ||
| 205 | } | ||
| 206 | _, err = f.Write(b) | ||
| 207 | return err | ||
| 208 | } | ||
| 209 | |||
| 88 | // WriteValue writes a new value for key. | 210 | // WriteValue writes a new value for key. |
| 89 | func (c *XMLConfigContainer) Set(key, val string) error { | 211 | func (c *XMLConfigContainer) Set(key, val string) error { |
| 90 | c.Lock() | 212 | c.Lock() | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package xml |
| 8 | 16 | ||
| 9 | import ( | 17 | import ( |
| 10 | "os" | 18 | "os" | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | // package yaml for config provider |
| 16 | // | ||
| 17 | // depend on github.com/beego/goyaml2 | ||
| 18 | // | ||
| 19 | // go install github.com/beego/goyaml2 | ||
| 20 | // | ||
| 21 | // Usage: | ||
| 22 | // import( | ||
| 23 | // _ "github.com/astaxie/beego/config/yaml" | ||
| 24 | // "github.com/astaxie/beego/config" | ||
| 25 | // ) | ||
| 26 | // | ||
| 27 | // cnf, err := config.NewConfig("yaml", "config.yaml") | ||
| 28 | // | ||
| 29 | // more docs http://beego.me/docs/module/config.md | ||
| 30 | package yaml | ||
| 8 | 31 | ||
| 9 | import ( | 32 | import ( |
| 10 | "bytes" | 33 | "bytes" |
| 11 | "encoding/json" | 34 | "encoding/json" |
| 12 | "errors" | 35 | "errors" |
| 36 | "fmt" | ||
| 13 | "io/ioutil" | 37 | "io/ioutil" |
| 14 | "log" | 38 | "log" |
| 15 | "os" | 39 | "os" |
| 40 | "path" | ||
| 16 | "strings" | 41 | "strings" |
| 17 | "sync" | 42 | "sync" |
| 43 | "time" | ||
| 18 | 44 | ||
| 19 | "github.com/astaxie/beego/config" | 45 | "github.com/astaxie/beego/config" |
| 20 | "github.com/beego/goyaml2" | 46 | "github.com/beego/goyaml2" |
| 21 | ) | 47 | ) |
| 22 | 48 | ||
| 23 | // YAMLConfig is a yaml config parser and implements Config interface. | 49 | // YAMLConfig is a yaml config parser and implements Config interface. |
| 24 | type YAMLConfig struct { | 50 | type YAMLConfig struct{} |
| 25 | } | ||
| 26 | 51 | ||
| 27 | // Parse returns a ConfigContainer with parsed yaml config map. | 52 | // Parse returns a ConfigContainer with parsed yaml config map. |
| 28 | func (yaml *YAMLConfig) Parse(filename string) (config.ConfigContainer, error) { | 53 | func (yaml *YAMLConfig) Parse(filename string) (y config.ConfigContainer, err error) { |
| 29 | y := &YAMLConfigContainer{ | ||
| 30 | data: make(map[string]interface{}), | ||
| 31 | } | ||
| 32 | cnf, err := ReadYmlReader(filename) | 54 | cnf, err := ReadYmlReader(filename) |
| 33 | if err != nil { | 55 | if err != nil { |
| 56 | return | ||
| 57 | } | ||
| 58 | y = &YAMLConfigContainer{ | ||
| 59 | data: cnf, | ||
| 60 | } | ||
| 61 | return | ||
| 62 | } | ||
| 63 | |||
| 64 | func (yaml *YAMLConfig) ParseData(data []byte) (config.ConfigContainer, error) { | ||
| 65 | // Save memory data to temporary file | ||
| 66 | tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) | ||
| 67 | os.MkdirAll(path.Dir(tmpName), os.ModePerm) | ||
| 68 | if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { | ||
| 34 | return nil, err | 69 | return nil, err |
| 35 | } | 70 | } |
| 36 | y.data = cnf | 71 | return yaml.Parse(tmpName) |
| 37 | return y, nil | ||
| 38 | } | 72 | } |
| 39 | 73 | ||
| 40 | // Read yaml file to map. | 74 | // Read yaml file to map. |
| 41 | // if json like, use json package, unless goyaml2 package. | 75 | // if json like, use json package, unless goyaml2 package. |
| 42 | func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { | 76 | func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { |
| 43 | err = nil | ||
| 44 | f, err := os.Open(path) | 77 | f, err := os.Open(path) |
| 45 | if err != nil { | 78 | if err != nil { |
| 46 | return | 79 | return |
| 47 | } | 80 | } |
| 48 | defer f.Close() | 81 | defer f.Close() |
| 49 | err = nil | 82 | |
| 50 | buf, err := ioutil.ReadAll(f) | 83 | buf, err := ioutil.ReadAll(f) |
| 51 | if err != nil || len(buf) < 3 { | 84 | if err != nil || len(buf) < 3 { |
| 52 | return | 85 | return |
| 53 | } | 86 | } |
| 54 | 87 | ||
| 55 | if string(buf[0:1]) == "{" { | 88 | if string(buf[0:1]) == "{" { |
| 56 | log.Println("Look lile a Json, try it") | 89 | log.Println("Look like a Json, try json umarshal") |
| 57 | err = json.Unmarshal(buf, &cnf) | 90 | err = json.Unmarshal(buf, &cnf) |
| 58 | if err == nil { | 91 | if err == nil { |
| 59 | log.Println("It is Json Map") | 92 | log.Println("It is Json Map") |
| ... | @@ -61,19 +94,19 @@ func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { | ... | @@ -61,19 +94,19 @@ func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { |
| 61 | } | 94 | } |
| 62 | } | 95 | } |
| 63 | 96 | ||
| 64 | _map, _err := goyaml2.Read(bytes.NewBuffer(buf)) | 97 | data, err := goyaml2.Read(bytes.NewBuffer(buf)) |
| 65 | if _err != nil { | 98 | if err != nil { |
| 66 | log.Println("Goyaml2 ERR>", string(buf), _err) | 99 | log.Println("Goyaml2 ERR>", string(buf), err) |
| 67 | //err = goyaml.Unmarshal(buf, &cnf) | ||
| 68 | err = _err | ||
| 69 | return | 100 | return |
| 70 | } | 101 | } |
| 71 | if _map == nil { | 102 | |
| 103 | if data == nil { | ||
| 72 | log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf)) | 104 | log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf)) |
| 105 | return | ||
| 73 | } | 106 | } |
| 74 | cnf, ok := _map.(map[string]interface{}) | 107 | cnf, ok := data.(map[string]interface{}) |
| 75 | if !ok { | 108 | if !ok { |
| 76 | log.Println("Not a Map? >> ", string(buf), _map) | 109 | log.Println("Not a Map? >> ", string(buf), data) |
| 77 | cnf = nil | 110 | cnf = nil |
| 78 | } | 111 | } |
| 79 | return | 112 | return |
| ... | @@ -93,6 +126,16 @@ func (c *YAMLConfigContainer) Bool(key string) (bool, error) { | ... | @@ -93,6 +126,16 @@ func (c *YAMLConfigContainer) Bool(key string) (bool, error) { |
| 93 | return false, errors.New("not bool value") | 126 | return false, errors.New("not bool value") |
| 94 | } | 127 | } |
| 95 | 128 | ||
| 129 | // DefaultBool return the bool value if has no error | ||
| 130 | // otherwise return the defaultval | ||
| 131 | func (c *YAMLConfigContainer) DefaultBool(key string, defaultval bool) bool { | ||
| 132 | if v, err := c.Bool(key); err != nil { | ||
| 133 | return defaultval | ||
| 134 | } else { | ||
| 135 | return v | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 96 | // Int returns the integer value for a given key. | 139 | // Int returns the integer value for a given key. |
| 97 | func (c *YAMLConfigContainer) Int(key string) (int, error) { | 140 | func (c *YAMLConfigContainer) Int(key string) (int, error) { |
| 98 | if v, ok := c.data[key].(int64); ok { | 141 | if v, ok := c.data[key].(int64); ok { |
| ... | @@ -101,6 +144,16 @@ func (c *YAMLConfigContainer) Int(key string) (int, error) { | ... | @@ -101,6 +144,16 @@ func (c *YAMLConfigContainer) Int(key string) (int, error) { |
| 101 | return 0, errors.New("not int value") | 144 | return 0, errors.New("not int value") |
| 102 | } | 145 | } |
| 103 | 146 | ||
| 147 | // DefaultInt returns the integer value for a given key. | ||
| 148 | // if err != nil return defaltval | ||
| 149 | func (c *YAMLConfigContainer) DefaultInt(key string, defaultval int) int { | ||
| 150 | if v, err := c.Int(key); err != nil { | ||
| 151 | return defaultval | ||
| 152 | } else { | ||
| 153 | return v | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 104 | // Int64 returns the int64 value for a given key. | 157 | // Int64 returns the int64 value for a given key. |
| 105 | func (c *YAMLConfigContainer) Int64(key string) (int64, error) { | 158 | func (c *YAMLConfigContainer) Int64(key string) (int64, error) { |
| 106 | if v, ok := c.data[key].(int64); ok { | 159 | if v, ok := c.data[key].(int64); ok { |
| ... | @@ -109,6 +162,16 @@ func (c *YAMLConfigContainer) Int64(key string) (int64, error) { | ... | @@ -109,6 +162,16 @@ func (c *YAMLConfigContainer) Int64(key string) (int64, error) { |
| 109 | return 0, errors.New("not bool value") | 162 | return 0, errors.New("not bool value") |
| 110 | } | 163 | } |
| 111 | 164 | ||
| 165 | // DefaultInt64 returns the int64 value for a given key. | ||
| 166 | // if err != nil return defaltval | ||
| 167 | func (c *YAMLConfigContainer) DefaultInt64(key string, defaultval int64) int64 { | ||
| 168 | if v, err := c.Int64(key); err != nil { | ||
| 169 | return defaultval | ||
| 170 | } else { | ||
| 171 | return v | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 112 | // Float returns the float value for a given key. | 175 | // Float returns the float value for a given key. |
| 113 | func (c *YAMLConfigContainer) Float(key string) (float64, error) { | 176 | func (c *YAMLConfigContainer) Float(key string) (float64, error) { |
| 114 | if v, ok := c.data[key].(float64); ok { | 177 | if v, ok := c.data[key].(float64); ok { |
| ... | @@ -117,6 +180,16 @@ func (c *YAMLConfigContainer) Float(key string) (float64, error) { | ... | @@ -117,6 +180,16 @@ func (c *YAMLConfigContainer) Float(key string) (float64, error) { |
| 117 | return 0.0, errors.New("not float64 value") | 180 | return 0.0, errors.New("not float64 value") |
| 118 | } | 181 | } |
| 119 | 182 | ||
| 183 | // DefaultFloat returns the float64 value for a given key. | ||
| 184 | // if err != nil return defaltval | ||
| 185 | func (c *YAMLConfigContainer) DefaultFloat(key string, defaultval float64) float64 { | ||
| 186 | if v, err := c.Float(key); err != nil { | ||
| 187 | return defaultval | ||
| 188 | } else { | ||
| 189 | return v | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 120 | // String returns the string value for a given key. | 193 | // String returns the string value for a given key. |
| 121 | func (c *YAMLConfigContainer) String(key string) string { | 194 | func (c *YAMLConfigContainer) String(key string) string { |
| 122 | if v, ok := c.data[key].(string); ok { | 195 | if v, ok := c.data[key].(string); ok { |
| ... | @@ -125,11 +198,52 @@ func (c *YAMLConfigContainer) String(key string) string { | ... | @@ -125,11 +198,52 @@ func (c *YAMLConfigContainer) String(key string) string { |
| 125 | return "" | 198 | return "" |
| 126 | } | 199 | } |
| 127 | 200 | ||
| 201 | // DefaultString returns the string value for a given key. | ||
| 202 | // if err != nil return defaltval | ||
| 203 | func (c *YAMLConfigContainer) DefaultString(key string, defaultval string) string { | ||
| 204 | if v := c.String(key); v == "" { | ||
| 205 | return defaultval | ||
| 206 | } else { | ||
| 207 | return v | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 128 | // Strings returns the []string value for a given key. | 211 | // Strings returns the []string value for a given key. |
| 129 | func (c *YAMLConfigContainer) Strings(key string) []string { | 212 | func (c *YAMLConfigContainer) Strings(key string) []string { |
| 130 | return strings.Split(c.String(key), ";") | 213 | return strings.Split(c.String(key), ";") |
| 131 | } | 214 | } |
| 132 | 215 | ||
| 216 | // DefaultStrings returns the []string value for a given key. | ||
| 217 | // if err != nil return defaltval | ||
| 218 | func (c *YAMLConfigContainer) DefaultStrings(key string, defaultval []string) []string { | ||
| 219 | if v := c.Strings(key); len(v) == 0 { | ||
| 220 | return defaultval | ||
| 221 | } else { | ||
| 222 | return v | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | // GetSection returns map for the given section | ||
| 227 | func (c *YAMLConfigContainer) GetSection(section string) (map[string]string, error) { | ||
| 228 | if v, ok := c.data[section]; ok { | ||
| 229 | return v.(map[string]string), nil | ||
| 230 | } else { | ||
| 231 | return nil, errors.New("not exist setction") | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | // SaveConfigFile save the config into file | ||
| 236 | func (c *YAMLConfigContainer) SaveConfigFile(filename string) (err error) { | ||
| 237 | // Write configuration file by filename. | ||
| 238 | f, err := os.Create(filename) | ||
| 239 | if err != nil { | ||
| 240 | return err | ||
| 241 | } | ||
| 242 | defer f.Close() | ||
| 243 | err = goyaml2.Write(f, c.data) | ||
| 244 | return err | ||
| 245 | } | ||
| 246 | |||
| 133 | // WriteValue writes a new value for key. | 247 | // WriteValue writes a new value for key. |
| 134 | func (c *YAMLConfigContainer) Set(key, val string) error { | 248 | func (c *YAMLConfigContainer) Set(key, val string) error { |
| 135 | c.Lock() | 249 | c.Lock() | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package config | 15 | package yaml |
| 8 | 16 | ||
| 9 | import ( | 17 | import ( |
| 10 | "os" | 18 | "os" | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | 6 | // | |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | // Usage: | ||
| 16 | // | ||
| 17 | // import "github.com/astaxie/beego/context" | ||
| 18 | // | ||
| 19 | // ctx := context.Context{Request:req,ResponseWriter:rw} | ||
| 20 | // | ||
| 21 | // more docs http://beego.me/docs/module/context.md | ||
| 7 | package context | 22 | package context |
| 8 | 23 | ||
| 9 | import ( | 24 | import ( |
| ... | @@ -17,6 +32,7 @@ import ( | ... | @@ -17,6 +32,7 @@ import ( |
| 17 | "time" | 32 | "time" |
| 18 | 33 | ||
| 19 | "github.com/astaxie/beego/middleware" | 34 | "github.com/astaxie/beego/middleware" |
| 35 | "github.com/astaxie/beego/utils" | ||
| 20 | ) | 36 | ) |
| 21 | 37 | ||
| 22 | // Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter. | 38 | // Http request context struct including BeegoInput, BeegoOutput, http.Request and http.ResponseWriter. |
| ... | @@ -26,20 +42,21 @@ type Context struct { | ... | @@ -26,20 +42,21 @@ type Context struct { |
| 26 | Output *BeegoOutput | 42 | Output *BeegoOutput |
| 27 | Request *http.Request | 43 | Request *http.Request |
| 28 | ResponseWriter http.ResponseWriter | 44 | ResponseWriter http.ResponseWriter |
| 45 | _xsrf_token string | ||
| 29 | } | 46 | } |
| 30 | 47 | ||
| 31 | // Redirect does redirection to localurl with http header status code. | 48 | // Redirect does redirection to localurl with http header status code. |
| 32 | // It sends http response header directly. | 49 | // It sends http response header directly. |
| 33 | func (ctx *Context) Redirect(status int, localurl string) { | 50 | func (ctx *Context) Redirect(status int, localurl string) { |
| 34 | ctx.Output.Header("Location", localurl) | 51 | ctx.Output.Header("Location", localurl) |
| 35 | ctx.Output.SetStatus(status) | 52 | ctx.ResponseWriter.WriteHeader(status) |
| 36 | } | 53 | } |
| 37 | 54 | ||
| 38 | // Abort stops this request. | 55 | // Abort stops this request. |
| 39 | // if middleware.ErrorMaps exists, panic body. | 56 | // if middleware.ErrorMaps exists, panic body. |
| 40 | // if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string. | 57 | // if middleware.HTTPExceptionMaps exists, panic HTTPException struct with status and body string. |
| 41 | func (ctx *Context) Abort(status int, body string) { | 58 | func (ctx *Context) Abort(status int, body string) { |
| 42 | ctx.Output.SetStatus(status) | 59 | ctx.ResponseWriter.WriteHeader(status) |
| 43 | // first panic from ErrorMaps, is is user defined error functions. | 60 | // first panic from ErrorMaps, is is user defined error functions. |
| 44 | if _, ok := middleware.ErrorMaps[body]; ok { | 61 | if _, ok := middleware.ErrorMaps[body]; ok { |
| 45 | panic(body) | 62 | panic(body) |
| ... | @@ -58,7 +75,7 @@ func (ctx *Context) Abort(status int, body string) { | ... | @@ -58,7 +75,7 @@ func (ctx *Context) Abort(status int, body string) { |
| 58 | // Write string to response body. | 75 | // Write string to response body. |
| 59 | // it sends response body. | 76 | // it sends response body. |
| 60 | func (ctx *Context) WriteString(content string) { | 77 | func (ctx *Context) WriteString(content string) { |
| 61 | ctx.Output.Body([]byte(content)) | 78 | ctx.ResponseWriter.Write([]byte(content)) |
| 62 | } | 79 | } |
| 63 | 80 | ||
| 64 | // Get cookie from request by a given key. | 81 | // Get cookie from request by a given key. |
| ... | @@ -110,3 +127,35 @@ func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interf | ... | @@ -110,3 +127,35 @@ func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interf |
| 110 | cookie := strings.Join([]string{vs, timestamp, sig}, "|") | 127 | cookie := strings.Join([]string{vs, timestamp, sig}, "|") |
| 111 | ctx.Output.Cookie(name, cookie, others...) | 128 | ctx.Output.Cookie(name, cookie, others...) |
| 112 | } | 129 | } |
| 130 | |||
| 131 | // XsrfToken creates a xsrf token string and returns. | ||
| 132 | func (ctx *Context) XsrfToken(key string, expire int64) string { | ||
| 133 | if ctx._xsrf_token == "" { | ||
| 134 | token, ok := ctx.GetSecureCookie(key, "_xsrf") | ||
| 135 | if !ok { | ||
| 136 | token = string(utils.RandomCreateBytes(32)) | ||
| 137 | ctx.SetSecureCookie(key, "_xsrf", token, expire) | ||
| 138 | } | ||
| 139 | ctx._xsrf_token = token | ||
| 140 | } | ||
| 141 | return ctx._xsrf_token | ||
| 142 | } | ||
| 143 | |||
| 144 | // CheckXsrfCookie checks xsrf token in this request is valid or not. | ||
| 145 | // the token can provided in request header "X-Xsrftoken" and "X-CsrfToken" | ||
| 146 | // or in form field value named as "_xsrf". | ||
| 147 | func (ctx *Context) CheckXsrfCookie() bool { | ||
| 148 | token := ctx.Input.Query("_xsrf") | ||
| 149 | if token == "" { | ||
| 150 | token = ctx.Request.Header.Get("X-Xsrftoken") | ||
| 151 | } | ||
| 152 | if token == "" { | ||
| 153 | token = ctx.Request.Header.Get("X-Csrftoken") | ||
| 154 | } | ||
| 155 | if token == "" { | ||
| 156 | ctx.Abort(403, "'_xsrf' argument missing from POST") | ||
| 157 | } else if ctx._xsrf_token != token { | ||
| 158 | ctx.Abort(403, "XSRF cookie does not match POST argument") | ||
| 159 | } | ||
| 160 | return true | ||
| 161 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package context | 15 | package context |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package context | 15 | package context |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package context | 15 | package context |
| 8 | 16 | ||
| ... | @@ -68,6 +76,14 @@ func (output *BeegoOutput) Body(content []byte) { | ... | @@ -68,6 +76,14 @@ func (output *BeegoOutput) Body(content []byte) { |
| 68 | } else { | 76 | } else { |
| 69 | output.Header("Content-Length", strconv.Itoa(len(content))) | 77 | output.Header("Content-Length", strconv.Itoa(len(content))) |
| 70 | } | 78 | } |
| 79 | |||
| 80 | // Write status code if it has been set manually | ||
| 81 | // Set it to 0 afterwards to prevent "multiple response.WriteHeader calls" | ||
| 82 | if output.Status != 0 { | ||
| 83 | output.Context.ResponseWriter.WriteHeader(output.Status) | ||
| 84 | output.Status = 0 | ||
| 85 | } | ||
| 86 | |||
| 71 | output_writer.Write(content) | 87 | output_writer.Write(content) |
| 72 | switch output_writer.(type) { | 88 | switch output_writer.(type) { |
| 73 | case *gzip.Writer: | 89 | case *gzip.Writer: |
| ... | @@ -267,7 +283,6 @@ func (output *BeegoOutput) ContentType(ext string) { | ... | @@ -267,7 +283,6 @@ func (output *BeegoOutput) ContentType(ext string) { |
| 267 | // SetStatus sets response status code. | 283 | // SetStatus sets response status code. |
| 268 | // It writes response header directly. | 284 | // It writes response header directly. |
| 269 | func (output *BeegoOutput) SetStatus(status int) { | 285 | func (output *BeegoOutput) SetStatus(status int) { |
| 270 | output.Context.ResponseWriter.WriteHeader(status) | ||
| 271 | output.Status = status | 286 | output.Status = status |
| 272 | } | 287 | } |
| 273 | 288 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ||
| ... | @@ -22,7 +30,6 @@ import ( | ... | @@ -22,7 +30,6 @@ import ( |
| 22 | 30 | ||
| 23 | "github.com/astaxie/beego/context" | 31 | "github.com/astaxie/beego/context" |
| 24 | "github.com/astaxie/beego/session" | 32 | "github.com/astaxie/beego/session" |
| 25 | "github.com/astaxie/beego/utils" | ||
| 26 | ) | 33 | ) |
| 27 | 34 | ||
| 28 | //commonly used mime-types | 35 | //commonly used mime-types |
| ... | @@ -270,6 +277,11 @@ func (c *Controller) Abort(code string) { | ... | @@ -270,6 +277,11 @@ func (c *Controller) Abort(code string) { |
| 270 | } | 277 | } |
| 271 | } | 278 | } |
| 272 | 279 | ||
| 280 | // CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body. | ||
| 281 | func (c *Controller) CustomAbort(status int, body string) { | ||
| 282 | c.Ctx.Abort(status, body) | ||
| 283 | } | ||
| 284 | |||
| 273 | // StopRun makes panic of USERSTOPRUN error and go to recover function if defined. | 285 | // StopRun makes panic of USERSTOPRUN error and go to recover function if defined. |
| 274 | func (c *Controller) StopRun() { | 286 | func (c *Controller) StopRun() { |
| 275 | panic(USERSTOPRUN) | 287 | panic(USERSTOPRUN) |
| ... | @@ -474,18 +486,13 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter | ... | @@ -474,18 +486,13 @@ func (c *Controller) SetSecureCookie(Secret, name, value string, others ...inter |
| 474 | // XsrfToken creates a xsrf token string and returns. | 486 | // XsrfToken creates a xsrf token string and returns. |
| 475 | func (c *Controller) XsrfToken() string { | 487 | func (c *Controller) XsrfToken() string { |
| 476 | if c._xsrf_token == "" { | 488 | if c._xsrf_token == "" { |
| 477 | token, ok := c.GetSecureCookie(XSRFKEY, "_xsrf") | 489 | var expire int64 |
| 478 | if !ok { | 490 | if c.XSRFExpire > 0 { |
| 479 | var expire int64 | 491 | expire = int64(c.XSRFExpire) |
| 480 | if c.XSRFExpire > 0 { | 492 | } else { |
| 481 | expire = int64(c.XSRFExpire) | 493 | expire = int64(XSRFExpire) |
| 482 | } else { | ||
| 483 | expire = int64(XSRFExpire) | ||
| 484 | } | ||
| 485 | token = string(utils.RandomCreateBytes(32)) | ||
| 486 | c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire) | ||
| 487 | } | 494 | } |
| 488 | c._xsrf_token = token | 495 | c._xsrf_token = c.Ctx.XsrfToken(XSRFKEY, expire) |
| 489 | } | 496 | } |
| 490 | return c._xsrf_token | 497 | return c._xsrf_token |
| 491 | } | 498 | } |
| ... | @@ -497,19 +504,7 @@ func (c *Controller) CheckXsrfCookie() bool { | ... | @@ -497,19 +504,7 @@ func (c *Controller) CheckXsrfCookie() bool { |
| 497 | if !c.EnableXSRF { | 504 | if !c.EnableXSRF { |
| 498 | return true | 505 | return true |
| 499 | } | 506 | } |
| 500 | token := c.GetString("_xsrf") | 507 | return c.Ctx.CheckXsrfCookie() |
| 501 | if token == "" { | ||
| 502 | token = c.Ctx.Request.Header.Get("X-Xsrftoken") | ||
| 503 | } | ||
| 504 | if token == "" { | ||
| 505 | token = c.Ctx.Request.Header.Get("X-Csrftoken") | ||
| 506 | } | ||
| 507 | if token == "" { | ||
| 508 | c.Ctx.Abort(403, "'_xsrf' argument missing from POST") | ||
| 509 | } else if c._xsrf_token != token { | ||
| 510 | c.Ctx.Abort(403, "XSRF cookie does not match POST argument") | ||
| 511 | } | ||
| 512 | return true | ||
| 513 | } | 508 | } |
| 514 | 509 | ||
| 515 | // XsrfFormHtml writes an input field contains xsrf token value. | 510 | // XsrfFormHtml writes an input field contains xsrf token value. | ... | ... |
| 1 | // Copyright 2014 beego Author. All Rights Reserved. | ||
| 2 | // | ||
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | // you may not use this file except in compliance with the License. | ||
| 5 | // You may obtain a copy of the License at | ||
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 1 | package beego | 15 | package beego |
| 2 | 16 | ||
| 3 | import ( | 17 | import ( | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Beego (http://beego.me/) |
| 2 | |||
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 3 | // @description beego is an open-source, high-performance web framework for the Go programming language. |
| 4 | |||
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 5 | // @link http://github.com/astaxie/beego for the canonical source repository |
| 6 | |||
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 7 | // @license http://github.com/astaxie/beego/blob/master/LICENSE |
| 8 | |||
| 5 | // @authors astaxie | 9 | // @authors astaxie |
| 6 | 10 | ||
| 7 | package main | 11 | package main | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 15 | // Usage: | ||
| 16 | // | ||
| 17 | // import "github.com/astaxie/beego/context" | ||
| 18 | // | ||
| 19 | // b := httplib.Post("http://beego.me/") | ||
| 20 | // b.Param("username","astaxie") | ||
| 21 | // b.Param("password","123456") | ||
| 22 | // b.PostFile("uploadfile1", "httplib.pdf") | ||
| 23 | // b.PostFile("uploadfile2", "httplib.txt") | ||
| 24 | // str, err := b.String() | ||
| 25 | // if err != nil { | ||
| 26 | // t.Fatal(err) | ||
| 27 | // } | ||
| 28 | // fmt.Println(str) | ||
| 29 | // | ||
| 30 | // more docs http://beego.me/docs/module/httplib.md | ||
| 7 | package httplib | 31 | package httplib |
| 8 | 32 | ||
| 9 | import ( | 33 | import ( |
| ... | @@ -52,41 +76,46 @@ func SetDefaultSetting(setting BeegoHttpSettings) { | ... | @@ -52,41 +76,46 @@ func SetDefaultSetting(setting BeegoHttpSettings) { |
| 52 | // Get returns *BeegoHttpRequest with GET method. | 76 | // Get returns *BeegoHttpRequest with GET method. |
| 53 | func Get(url string) *BeegoHttpRequest { | 77 | func Get(url string) *BeegoHttpRequest { |
| 54 | var req http.Request | 78 | var req http.Request |
| 79 | var resp http.Response | ||
| 55 | req.Method = "GET" | 80 | req.Method = "GET" |
| 56 | req.Header = http.Header{} | 81 | req.Header = http.Header{} |
| 57 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting} | 82 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil} |
| 58 | } | 83 | } |
| 59 | 84 | ||
| 60 | // Post returns *BeegoHttpRequest with POST method. | 85 | // Post returns *BeegoHttpRequest with POST method. |
| 61 | func Post(url string) *BeegoHttpRequest { | 86 | func Post(url string) *BeegoHttpRequest { |
| 62 | var req http.Request | 87 | var req http.Request |
| 88 | var resp http.Response | ||
| 63 | req.Method = "POST" | 89 | req.Method = "POST" |
| 64 | req.Header = http.Header{} | 90 | req.Header = http.Header{} |
| 65 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting} | 91 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil} |
| 66 | } | 92 | } |
| 67 | 93 | ||
| 68 | // Put returns *BeegoHttpRequest with PUT method. | 94 | // Put returns *BeegoHttpRequest with PUT method. |
| 69 | func Put(url string) *BeegoHttpRequest { | 95 | func Put(url string) *BeegoHttpRequest { |
| 70 | var req http.Request | 96 | var req http.Request |
| 97 | var resp http.Response | ||
| 71 | req.Method = "PUT" | 98 | req.Method = "PUT" |
| 72 | req.Header = http.Header{} | 99 | req.Header = http.Header{} |
| 73 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting} | 100 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil} |
| 74 | } | 101 | } |
| 75 | 102 | ||
| 76 | // Delete returns *BeegoHttpRequest DELETE GET method. | 103 | // Delete returns *BeegoHttpRequest DELETE GET method. |
| 77 | func Delete(url string) *BeegoHttpRequest { | 104 | func Delete(url string) *BeegoHttpRequest { |
| 78 | var req http.Request | 105 | var req http.Request |
| 106 | var resp http.Response | ||
| 79 | req.Method = "DELETE" | 107 | req.Method = "DELETE" |
| 80 | req.Header = http.Header{} | 108 | req.Header = http.Header{} |
| 81 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting} | 109 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil} |
| 82 | } | 110 | } |
| 83 | 111 | ||
| 84 | // Head returns *BeegoHttpRequest with HEAD method. | 112 | // Head returns *BeegoHttpRequest with HEAD method. |
| 85 | func Head(url string) *BeegoHttpRequest { | 113 | func Head(url string) *BeegoHttpRequest { |
| 86 | var req http.Request | 114 | var req http.Request |
| 115 | var resp http.Response | ||
| 87 | req.Method = "HEAD" | 116 | req.Method = "HEAD" |
| 88 | req.Header = http.Header{} | 117 | req.Header = http.Header{} |
| 89 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting} | 118 | return &BeegoHttpRequest{url, &req, map[string]string{}, map[string]string{}, defaultSetting, &resp, nil} |
| 90 | } | 119 | } |
| 91 | 120 | ||
| 92 | // BeegoHttpSettings | 121 | // BeegoHttpSettings |
| ... | @@ -108,6 +137,8 @@ type BeegoHttpRequest struct { | ... | @@ -108,6 +137,8 @@ type BeegoHttpRequest struct { |
| 108 | params map[string]string | 137 | params map[string]string |
| 109 | files map[string]string | 138 | files map[string]string |
| 110 | setting BeegoHttpSettings | 139 | setting BeegoHttpSettings |
| 140 | resp *http.Response | ||
| 141 | body []byte | ||
| 111 | } | 142 | } |
| 112 | 143 | ||
| 113 | // Change request settings | 144 | // Change request settings |
| ... | @@ -123,7 +154,7 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest { | ... | @@ -123,7 +154,7 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest { |
| 123 | } | 154 | } |
| 124 | 155 | ||
| 125 | // SetUserAgent sets User-Agent header field | 156 | // SetUserAgent sets User-Agent header field |
| 126 | func (b *BeegoHttpRequest) SetAgent(useragent string) *BeegoHttpRequest { | 157 | func (b *BeegoHttpRequest) SetUserAgent(useragent string) *BeegoHttpRequest { |
| 127 | b.setting.UserAgent = useragent | 158 | b.setting.UserAgent = useragent |
| 128 | return b | 159 | return b |
| 129 | } | 160 | } |
| ... | @@ -223,6 +254,9 @@ func (b *BeegoHttpRequest) Body(data interface{}) *BeegoHttpRequest { | ... | @@ -223,6 +254,9 @@ func (b *BeegoHttpRequest) Body(data interface{}) *BeegoHttpRequest { |
| 223 | } | 254 | } |
| 224 | 255 | ||
| 225 | func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { | 256 | func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { |
| 257 | if b.resp.StatusCode != 0 { | ||
| 258 | return b.resp, nil | ||
| 259 | } | ||
| 226 | var paramBody string | 260 | var paramBody string |
| 227 | if len(b.params) > 0 { | 261 | if len(b.params) > 0 { |
| 228 | var buf bytes.Buffer | 262 | var buf bytes.Buffer |
| ... | @@ -341,6 +375,7 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { | ... | @@ -341,6 +375,7 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { |
| 341 | if err != nil { | 375 | if err != nil { |
| 342 | return nil, err | 376 | return nil, err |
| 343 | } | 377 | } |
| 378 | b.resp = resp | ||
| 344 | return resp, nil | 379 | return resp, nil |
| 345 | } | 380 | } |
| 346 | 381 | ||
| ... | @@ -358,6 +393,9 @@ func (b *BeegoHttpRequest) String() (string, error) { | ... | @@ -358,6 +393,9 @@ func (b *BeegoHttpRequest) String() (string, error) { |
| 358 | // Bytes returns the body []byte in response. | 393 | // Bytes returns the body []byte in response. |
| 359 | // it calls Response inner. | 394 | // it calls Response inner. |
| 360 | func (b *BeegoHttpRequest) Bytes() ([]byte, error) { | 395 | func (b *BeegoHttpRequest) Bytes() ([]byte, error) { |
| 396 | if b.body != nil { | ||
| 397 | return b.body, nil | ||
| 398 | } | ||
| 361 | resp, err := b.getResponse() | 399 | resp, err := b.getResponse() |
| 362 | if err != nil { | 400 | if err != nil { |
| 363 | return nil, err | 401 | return nil, err |
| ... | @@ -370,6 +408,7 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) { | ... | @@ -370,6 +408,7 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) { |
| 370 | if err != nil { | 408 | if err != nil { |
| 371 | return nil, err | 409 | return nil, err |
| 372 | } | 410 | } |
| 411 | b.body = data | ||
| 373 | return data, nil | 412 | return data, nil |
| 374 | } | 413 | } |
| 375 | 414 | ||
| ... | @@ -391,10 +430,7 @@ func (b *BeegoHttpRequest) ToFile(filename string) error { | ... | @@ -391,10 +430,7 @@ func (b *BeegoHttpRequest) ToFile(filename string) error { |
| 391 | } | 430 | } |
| 392 | defer resp.Body.Close() | 431 | defer resp.Body.Close() |
| 393 | _, err = io.Copy(f, resp.Body) | 432 | _, err = io.Copy(f, resp.Body) |
| 394 | if err != nil { | 433 | return err |
| 395 | return err | ||
| 396 | } | ||
| 397 | return nil | ||
| 398 | } | 434 | } |
| 399 | 435 | ||
| 400 | // ToJson returns the map that marshals from the body bytes as json in response . | 436 | // ToJson returns the map that marshals from the body bytes as json in response . |
| ... | @@ -405,24 +441,18 @@ func (b *BeegoHttpRequest) ToJson(v interface{}) error { | ... | @@ -405,24 +441,18 @@ func (b *BeegoHttpRequest) ToJson(v interface{}) error { |
| 405 | return err | 441 | return err |
| 406 | } | 442 | } |
| 407 | err = json.Unmarshal(data, v) | 443 | err = json.Unmarshal(data, v) |
| 408 | if err != nil { | 444 | return err |
| 409 | return err | ||
| 410 | } | ||
| 411 | return nil | ||
| 412 | } | 445 | } |
| 413 | 446 | ||
| 414 | // ToXml returns the map that marshals from the body bytes as xml in response . | 447 | // ToXml returns the map that marshals from the body bytes as xml in response . |
| 415 | // it calls Response inner. | 448 | // it calls Response inner. |
| 416 | func (b *BeegoHttpRequest) ToXML(v interface{}) error { | 449 | func (b *BeegoHttpRequest) ToXml(v interface{}) error { |
| 417 | data, err := b.Bytes() | 450 | data, err := b.Bytes() |
| 418 | if err != nil { | 451 | if err != nil { |
| 419 | return err | 452 | return err |
| 420 | } | 453 | } |
| 421 | err = xml.Unmarshal(data, v) | 454 | err = xml.Unmarshal(data, v) |
| 422 | if err != nil { | 455 | return err |
| 423 | return err | ||
| 424 | } | ||
| 425 | return nil | ||
| 426 | } | 456 | } |
| 427 | 457 | ||
| 428 | // Response executes request client gets response mannually. | 458 | // Response executes request client gets response mannually. | ... | ... |
| 1 | // Beego (http://beego.me) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package httplib | 15 | package httplib |
| 8 | 16 | ||
| 9 | import ( | 17 | import ( |
| 10 | "fmt" | ||
| 11 | "io/ioutil" | 18 | "io/ioutil" |
| 19 | "os" | ||
| 20 | "strings" | ||
| 12 | "testing" | 21 | "testing" |
| 13 | ) | 22 | ) |
| 14 | 23 | ||
| 15 | func TestGetUrl(t *testing.T) { | 24 | func TestResponse(t *testing.T) { |
| 16 | resp, err := Get("http://beego.me").Debug(true).Response() | 25 | req := Get("http://httpbin.org/get") |
| 26 | resp, err := req.Response() | ||
| 17 | if err != nil { | 27 | if err != nil { |
| 18 | t.Fatal(err) | 28 | t.Fatal(err) |
| 19 | } | 29 | } |
| 20 | if resp.Body == nil { | 30 | t.Log(resp) |
| 21 | t.Fatal("body is nil") | 31 | } |
| 32 | |||
| 33 | func TestGet(t *testing.T) { | ||
| 34 | req := Get("http://httpbin.org/get") | ||
| 35 | b, err := req.Bytes() | ||
| 36 | if err != nil { | ||
| 37 | t.Fatal(err) | ||
| 22 | } | 38 | } |
| 23 | data, err := ioutil.ReadAll(resp.Body) | 39 | t.Log(b) |
| 24 | defer resp.Body.Close() | 40 | |
| 41 | s, err := req.String() | ||
| 25 | if err != nil { | 42 | if err != nil { |
| 26 | t.Fatal(err) | 43 | t.Fatal(err) |
| 27 | } | 44 | } |
| 28 | if len(data) == 0 { | 45 | t.Log(s) |
| 29 | t.Fatal("data is no") | 46 | |
| 47 | if string(b) != s { | ||
| 48 | t.Fatal("request data not match") | ||
| 30 | } | 49 | } |
| 50 | } | ||
| 51 | |||
| 52 | func TestSimplePost(t *testing.T) { | ||
| 53 | v := "smallfish" | ||
| 54 | req := Post("http://httpbin.org/post") | ||
| 55 | req.Param("username", v) | ||
| 31 | 56 | ||
| 32 | str, err := Get("http://beego.me").String() | 57 | str, err := req.String() |
| 33 | if err != nil { | 58 | if err != nil { |
| 34 | t.Fatal(err) | 59 | t.Fatal(err) |
| 35 | } | 60 | } |
| 36 | if len(str) == 0 { | 61 | t.Log(str) |
| 37 | t.Fatal("has no info") | 62 | |
| 63 | n := strings.Index(str, v) | ||
| 64 | if n == -1 { | ||
| 65 | t.Fatal(v + " not found in post") | ||
| 38 | } | 66 | } |
| 39 | } | 67 | } |
| 40 | 68 | ||
| 41 | func ExamplePost(t *testing.T) { | 69 | func TestPostFile(t *testing.T) { |
| 42 | b := Post("http://beego.me/").Debug(true) | 70 | v := "smallfish" |
| 43 | b.Param("username", "astaxie") | 71 | req := Post("http://httpbin.org/post") |
| 44 | b.Param("password", "hello") | 72 | req.Param("username", v) |
| 45 | b.PostFile("uploadfile", "httplib_test.go") | 73 | req.PostFile("uploadfile", "httplib_test.go") |
| 46 | str, err := b.String() | 74 | |
| 75 | str, err := req.String() | ||
| 47 | if err != nil { | 76 | if err != nil { |
| 48 | t.Fatal(err) | 77 | t.Fatal(err) |
| 49 | } | 78 | } |
| 50 | fmt.Println(str) | 79 | t.Log(str) |
| 80 | |||
| 81 | n := strings.Index(str, v) | ||
| 82 | if n == -1 { | ||
| 83 | t.Fatal(v + " not found in post") | ||
| 84 | } | ||
| 51 | } | 85 | } |
| 52 | 86 | ||
| 53 | func TestSimpleGetString(t *testing.T) { | 87 | func TestSimplePut(t *testing.T) { |
| 54 | fmt.Println("TestSimpleGetString==========================================") | 88 | str, err := Put("http://httpbin.org/put").String() |
| 55 | html, err := Get("http://httpbin.org/headers").SetAgent("beegoooooo").String() | 89 | if err != nil { |
| 90 | t.Fatal(err) | ||
| 91 | } | ||
| 92 | t.Log(str) | ||
| 93 | } | ||
| 94 | |||
| 95 | func TestSimpleDelete(t *testing.T) { | ||
| 96 | str, err := Delete("http://httpbin.org/delete").String() | ||
| 97 | if err != nil { | ||
| 98 | t.Fatal(err) | ||
| 99 | } | ||
| 100 | t.Log(str) | ||
| 101 | } | ||
| 102 | |||
| 103 | func TestWithCookie(t *testing.T) { | ||
| 104 | v := "smallfish" | ||
| 105 | str, err := Get("http://httpbin.org/cookies/set?k1=" + v).SetEnableCookie(true).String() | ||
| 106 | if err != nil { | ||
| 107 | t.Fatal(err) | ||
| 108 | } | ||
| 109 | t.Log(str) | ||
| 110 | |||
| 111 | str, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String() | ||
| 56 | if err != nil { | 112 | if err != nil { |
| 57 | t.Fatal(err) | 113 | t.Fatal(err) |
| 58 | } | 114 | } |
| 59 | fmt.Println(html) | 115 | t.Log(str) |
| 60 | fmt.Println("TestSimpleGetString==========================================") | 116 | |
| 117 | n := strings.Index(str, v) | ||
| 118 | if n == -1 { | ||
| 119 | t.Fatal(v + " not found in cookie") | ||
| 120 | } | ||
| 61 | } | 121 | } |
| 62 | 122 | ||
| 63 | func TestSimpleGetStringWithDefaultCookie(t *testing.T) { | 123 | func TestWithUserAgent(t *testing.T) { |
| 64 | fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================") | 124 | v := "beego" |
| 65 | html, err := Get("http://httpbin.org/cookies/set?k1=v1").SetEnableCookie(true).String() | 125 | str, err := Get("http://httpbin.org/headers").SetUserAgent(v).String() |
| 66 | if err != nil { | 126 | if err != nil { |
| 67 | t.Fatal(err) | 127 | t.Fatal(err) |
| 68 | } | 128 | } |
| 69 | fmt.Println(html) | 129 | t.Log(str) |
| 70 | html, err = Get("http://httpbin.org/cookies").SetEnableCookie(true).String() | 130 | |
| 131 | n := strings.Index(str, v) | ||
| 132 | if n == -1 { | ||
| 133 | t.Fatal(v + " not found in user-agent") | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | func TestWithSetting(t *testing.T) { | ||
| 138 | v := "beego" | ||
| 139 | var setting BeegoHttpSettings | ||
| 140 | setting.EnableCookie = true | ||
| 141 | setting.UserAgent = v | ||
| 142 | setting.Transport = nil | ||
| 143 | SetDefaultSetting(setting) | ||
| 144 | |||
| 145 | str, err := Get("http://httpbin.org/get").String() | ||
| 71 | if err != nil { | 146 | if err != nil { |
| 72 | t.Fatal(err) | 147 | t.Fatal(err) |
| 73 | } | 148 | } |
| 74 | fmt.Println(html) | 149 | t.Log(str) |
| 75 | fmt.Println("TestSimpleGetStringWithDefaultCookie==========================================") | 150 | |
| 151 | n := strings.Index(str, v) | ||
| 152 | if n == -1 { | ||
| 153 | t.Fatal(v + " not found in user-agent") | ||
| 154 | } | ||
| 76 | } | 155 | } |
| 77 | 156 | ||
| 78 | func TestDefaultSetting(t *testing.T) { | 157 | func TestToJson(t *testing.T) { |
| 79 | fmt.Println("TestDefaultSetting==========================================") | 158 | req := Get("http://httpbin.org/ip") |
| 80 | var def BeegoHttpSettings | 159 | resp, err := req.Response() |
| 81 | def.EnableCookie = true | ||
| 82 | //def.ShowDebug = true | ||
| 83 | def.UserAgent = "UserAgent" | ||
| 84 | //def.ConnectTimeout = 60*time.Second | ||
| 85 | //def.ReadWriteTimeout = 60*time.Second | ||
| 86 | def.Transport = nil //http.DefaultTransport | ||
| 87 | SetDefaultSetting(def) | ||
| 88 | |||
| 89 | html, err := Get("http://httpbin.org/headers").String() | ||
| 90 | if err != nil { | 160 | if err != nil { |
| 91 | t.Fatal(err) | 161 | t.Fatal(err) |
| 92 | } | 162 | } |
| 93 | fmt.Println(html) | 163 | t.Log(resp) |
| 94 | html, err = Get("http://httpbin.org/headers").String() | 164 | |
| 165 | // httpbin will return http remote addr | ||
| 166 | type Ip struct { | ||
| 167 | Origin string `json:"origin"` | ||
| 168 | } | ||
| 169 | var ip Ip | ||
| 170 | err = req.ToJson(&ip) | ||
| 95 | if err != nil { | 171 | if err != nil { |
| 96 | t.Fatal(err) | 172 | t.Fatal(err) |
| 97 | } | 173 | } |
| 98 | fmt.Println(html) | 174 | t.Log(ip.Origin) |
| 99 | fmt.Println("TestDefaultSetting==========================================") | 175 | |
| 176 | if n := strings.Count(ip.Origin, "."); n != 3 { | ||
| 177 | t.Fatal("response is not valid ip") | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | func TestToFile(t *testing.T) { | ||
| 182 | f := "beego_testfile" | ||
| 183 | req := Get("http://httpbin.org/ip") | ||
| 184 | err := req.ToFile(f) | ||
| 185 | if err != nil { | ||
| 186 | t.Fatal(err) | ||
| 187 | } | ||
| 188 | defer os.Remove(f) | ||
| 189 | b, err := ioutil.ReadFile(f) | ||
| 190 | if n := strings.Index(string(b), "origin"); n == -1 { | ||
| 191 | t.Fatal(err) | ||
| 192 | } | ||
| 100 | } | 193 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ||
| ... | @@ -14,12 +22,14 @@ import ( | ... | @@ -14,12 +22,14 @@ import ( |
| 14 | 22 | ||
| 15 | // Log levels to control the logging output. | 23 | // Log levels to control the logging output. |
| 16 | const ( | 24 | const ( |
| 17 | LevelTrace = iota | 25 | LevelEmergency = iota |
| 18 | LevelDebug | 26 | LevelAlert |
| 19 | LevelInfo | ||
| 20 | LevelWarning | ||
| 21 | LevelError | ||
| 22 | LevelCritical | 27 | LevelCritical |
| 28 | LevelError | ||
| 29 | LevelWarning | ||
| 30 | LevelNotice | ||
| 31 | LevelInformational | ||
| 32 | LevelDebug | ||
| 23 | ) | 33 | ) |
| 24 | 34 | ||
| 25 | // SetLogLevel sets the global log level used by the simple | 35 | // SetLogLevel sets the global log level used by the simple |
| ... | @@ -45,34 +55,57 @@ func SetLogger(adaptername string, config string) error { | ... | @@ -45,34 +55,57 @@ func SetLogger(adaptername string, config string) error { |
| 45 | return nil | 55 | return nil |
| 46 | } | 56 | } |
| 47 | 57 | ||
| 48 | // Trace logs a message at trace level. | 58 | func Emergency(v ...interface{}) { |
| 49 | func Trace(v ...interface{}) { | 59 | BeeLogger.Emergency(generateFmtStr(len(v)), v...) |
| 50 | BeeLogger.Trace(generateFmtStr(len(v)), v...) | ||
| 51 | } | 60 | } |
| 52 | 61 | ||
| 53 | // Debug logs a message at debug level. | 62 | func Alert(v ...interface{}) { |
| 54 | func Debug(v ...interface{}) { | 63 | BeeLogger.Alert(generateFmtStr(len(v)), v...) |
| 55 | BeeLogger.Debug(generateFmtStr(len(v)), v...) | ||
| 56 | } | 64 | } |
| 57 | 65 | ||
| 58 | // Info logs a message at info level. | 66 | // Critical logs a message at critical level. |
| 59 | func Info(v ...interface{}) { | 67 | func Critical(v ...interface{}) { |
| 60 | BeeLogger.Info(generateFmtStr(len(v)), v...) | 68 | BeeLogger.Critical(generateFmtStr(len(v)), v...) |
| 69 | } | ||
| 70 | |||
| 71 | // Error logs a message at error level. | ||
| 72 | func Error(v ...interface{}) { | ||
| 73 | BeeLogger.Error(generateFmtStr(len(v)), v...) | ||
| 61 | } | 74 | } |
| 62 | 75 | ||
| 63 | // Warning logs a message at warning level. | 76 | // Warning logs a message at warning level. |
| 77 | func Warning(v ...interface{}) { | ||
| 78 | BeeLogger.Warning(generateFmtStr(len(v)), v...) | ||
| 79 | } | ||
| 80 | |||
| 81 | // Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0. | ||
| 64 | func Warn(v ...interface{}) { | 82 | func Warn(v ...interface{}) { |
| 65 | BeeLogger.Warn(generateFmtStr(len(v)), v...) | 83 | Warning(v...) |
| 66 | } | 84 | } |
| 67 | 85 | ||
| 68 | // Error logs a message at error level. | 86 | func Notice(v ...interface{}) { |
| 69 | func Error(v ...interface{}) { | 87 | BeeLogger.Notice(generateFmtStr(len(v)), v...) |
| 70 | BeeLogger.Error(generateFmtStr(len(v)), v...) | ||
| 71 | } | 88 | } |
| 72 | 89 | ||
| 73 | // Critical logs a message at critical level. | 90 | // Info logs a message at info level. |
| 74 | func Critical(v ...interface{}) { | 91 | func Informational(v ...interface{}) { |
| 75 | BeeLogger.Critical(generateFmtStr(len(v)), v...) | 92 | BeeLogger.Informational(generateFmtStr(len(v)), v...) |
| 93 | } | ||
| 94 | |||
| 95 | // Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0. | ||
| 96 | func Info(v ...interface{}) { | ||
| 97 | Informational(v...) | ||
| 98 | } | ||
| 99 | |||
| 100 | // Debug logs a message at debug level. | ||
| 101 | func Debug(v ...interface{}) { | ||
| 102 | BeeLogger.Debug(generateFmtStr(len(v)), v...) | ||
| 103 | } | ||
| 104 | |||
| 105 | // Trace logs a message at trace level. | ||
| 106 | // Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0. | ||
| 107 | func Trace(v ...interface{}) { | ||
| 108 | BeeLogger.Trace(generateFmtStr(len(v)), v...) | ||
| 76 | } | 109 | } |
| 77 | 110 | ||
| 78 | func generateFmtStr(n int) string { | 111 | func generateFmtStr(n int) string { | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -45,7 +53,7 @@ func (c *ConnWriter) Init(jsonconfig string) error { | ... | @@ -45,7 +53,7 @@ func (c *ConnWriter) Init(jsonconfig string) error { |
| 45 | // write message in connection. | 53 | // write message in connection. |
| 46 | // if connection is down, try to re-connect. | 54 | // if connection is down, try to re-connect. |
| 47 | func (c *ConnWriter) WriteMsg(msg string, level int) error { | 55 | func (c *ConnWriter) WriteMsg(msg string, level int) error { |
| 48 | if level < c.Level { | 56 | if level > c.Level { |
| 49 | return nil | 57 | return nil |
| 50 | } | 58 | } |
| 51 | if c.neddedConnectOnMsg() { | 59 | if c.neddedConnectOnMsg() { | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -13,5 +21,5 @@ import ( | ... | @@ -13,5 +21,5 @@ import ( |
| 13 | func TestConn(t *testing.T) { | 21 | func TestConn(t *testing.T) { |
| 14 | log := NewLogger(1000) | 22 | log := NewLogger(1000) |
| 15 | log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`) | 23 | log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`) |
| 16 | log.Info("info") | 24 | log.Informational("informational") |
| 17 | } | 25 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -24,12 +32,14 @@ func NewBrush(color string) Brush { | ... | @@ -24,12 +32,14 @@ func NewBrush(color string) Brush { |
| 24 | } | 32 | } |
| 25 | 33 | ||
| 26 | var colors = []Brush{ | 34 | var colors = []Brush{ |
| 27 | NewBrush("1;36"), // Trace cyan | 35 | NewBrush("1;37"), // Emergency white |
| 28 | NewBrush("1;34"), // Debug blue | 36 | NewBrush("1;36"), // Alert cyan |
| 29 | NewBrush("1;32"), // Info green | 37 | NewBrush("1;35"), // Critical magenta |
| 30 | NewBrush("1;33"), // Warn yellow | ||
| 31 | NewBrush("1;31"), // Error red | 38 | NewBrush("1;31"), // Error red |
| 32 | NewBrush("1;35"), // Critical purple | 39 | NewBrush("1;33"), // Warning yellow |
| 40 | NewBrush("1;32"), // Notice green | ||
| 41 | NewBrush("1;34"), // Informational blue | ||
| 42 | NewBrush("1;34"), // Debug blue | ||
| 33 | } | 43 | } |
| 34 | 44 | ||
| 35 | // ConsoleWriter implements LoggerInterface and writes messages to terminal. | 45 | // ConsoleWriter implements LoggerInterface and writes messages to terminal. |
| ... | @@ -42,7 +52,7 @@ type ConsoleWriter struct { | ... | @@ -42,7 +52,7 @@ type ConsoleWriter struct { |
| 42 | func NewConsole() LoggerInterface { | 52 | func NewConsole() LoggerInterface { |
| 43 | cw := new(ConsoleWriter) | 53 | cw := new(ConsoleWriter) |
| 44 | cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime) | 54 | cw.lg = log.New(os.Stdout, "", log.Ldate|log.Ltime) |
| 45 | cw.Level = LevelTrace | 55 | cw.Level = LevelDebug |
| 46 | return cw | 56 | return cw |
| 47 | } | 57 | } |
| 48 | 58 | ||
| ... | @@ -61,7 +71,7 @@ func (c *ConsoleWriter) Init(jsonconfig string) error { | ... | @@ -61,7 +71,7 @@ func (c *ConsoleWriter) Init(jsonconfig string) error { |
| 61 | 71 | ||
| 62 | // write message in console. | 72 | // write message in console. |
| 63 | func (c *ConsoleWriter) WriteMsg(msg string, level int) error { | 73 | func (c *ConsoleWriter) WriteMsg(msg string, level int) error { |
| 64 | if level < c.Level { | 74 | if level > c.Level { |
| 65 | return nil | 75 | return nil |
| 66 | } | 76 | } |
| 67 | if goos := runtime.GOOS; goos == "windows" { | 77 | if goos := runtime.GOOS; goos == "windows" { | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -10,22 +18,29 @@ import ( | ... | @@ -10,22 +18,29 @@ import ( |
| 10 | "testing" | 18 | "testing" |
| 11 | ) | 19 | ) |
| 12 | 20 | ||
| 21 | // Try each log level in decreasing order of priority. | ||
| 22 | func testConsoleCalls(bl *BeeLogger) { | ||
| 23 | bl.Emergency("emergency") | ||
| 24 | bl.Alert("alert") | ||
| 25 | bl.Critical("critical") | ||
| 26 | bl.Error("error") | ||
| 27 | bl.Warning("warning") | ||
| 28 | bl.Notice("notice") | ||
| 29 | bl.Informational("informational") | ||
| 30 | bl.Debug("debug") | ||
| 31 | } | ||
| 32 | |||
| 33 | // Test console logging by visually comparing the lines being output with and | ||
| 34 | // without a log level specification. | ||
| 13 | func TestConsole(t *testing.T) { | 35 | func TestConsole(t *testing.T) { |
| 14 | log := NewLogger(10000) | 36 | log1 := NewLogger(10000) |
| 15 | log.EnableFuncCallDepth(true) | 37 | log1.EnableFuncCallDepth(true) |
| 16 | log.SetLogger("console", "") | 38 | log1.SetLogger("console", "") |
| 17 | log.Trace("trace") | 39 | testConsoleCalls(log1) |
| 18 | log.Info("info") | 40 | |
| 19 | log.Warn("warning") | ||
| 20 | log.Debug("debug") | ||
| 21 | log.Critical("critical") | ||
| 22 | log2 := NewLogger(100) | 41 | log2 := NewLogger(100) |
| 23 | log2.SetLogger("console", `{"level":1}`) | 42 | log2.SetLogger("console", `{"level":3}`) |
| 24 | log.Trace("trace") | 43 | testConsoleCalls(log2) |
| 25 | log.Info("info") | ||
| 26 | log.Warn("warning") | ||
| 27 | log.Debug("debug") | ||
| 28 | log.Critical("critical") | ||
| 29 | } | 44 | } |
| 30 | 45 | ||
| 31 | func BenchmarkConsole(b *testing.B) { | 46 | func BenchmarkConsole(b *testing.B) { |
| ... | @@ -33,6 +48,6 @@ func BenchmarkConsole(b *testing.B) { | ... | @@ -33,6 +48,6 @@ func BenchmarkConsole(b *testing.B) { |
| 33 | log.EnableFuncCallDepth(true) | 48 | log.EnableFuncCallDepth(true) |
| 34 | log.SetLogger("console", "") | 49 | log.SetLogger("console", "") |
| 35 | for i := 0; i < b.N; i++ { | 50 | for i := 0; i < b.N; i++ { |
| 36 | log.Trace("trace") | 51 | log.Debug("debug") |
| 37 | } | 52 | } |
| 38 | } | 53 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -138,7 +146,7 @@ func (w *FileLogWriter) docheck(size int) { | ... | @@ -138,7 +146,7 @@ func (w *FileLogWriter) docheck(size int) { |
| 138 | 146 | ||
| 139 | // write logger message into file. | 147 | // write logger message into file. |
| 140 | func (w *FileLogWriter) WriteMsg(msg string, level int) error { | 148 | func (w *FileLogWriter) WriteMsg(msg string, level int) error { |
| 141 | if level < w.Level { | 149 | if level > w.Level { |
| 142 | return nil | 150 | return nil |
| 143 | } | 151 | } |
| 144 | n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] " | 152 | n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] " | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -10,6 +18,7 @@ import ( | ... | @@ -10,6 +18,7 @@ import ( |
| 10 | "bufio" | 18 | "bufio" |
| 11 | "fmt" | 19 | "fmt" |
| 12 | "os" | 20 | "os" |
| 21 | "strconv" | ||
| 13 | "testing" | 22 | "testing" |
| 14 | "time" | 23 | "time" |
| 15 | ) | 24 | ) |
| ... | @@ -17,12 +26,14 @@ import ( | ... | @@ -17,12 +26,14 @@ import ( |
| 17 | func TestFile(t *testing.T) { | 26 | func TestFile(t *testing.T) { |
| 18 | log := NewLogger(10000) | 27 | log := NewLogger(10000) |
| 19 | log.SetLogger("file", `{"filename":"test.log"}`) | 28 | log.SetLogger("file", `{"filename":"test.log"}`) |
| 20 | log.Trace("test") | ||
| 21 | log.Info("info") | ||
| 22 | log.Debug("debug") | 29 | log.Debug("debug") |
| 23 | log.Warn("warning") | 30 | log.Informational("info") |
| 31 | log.Notice("notice") | ||
| 32 | log.Warning("warning") | ||
| 24 | log.Error("error") | 33 | log.Error("error") |
| 34 | log.Alert("alert") | ||
| 25 | log.Critical("critical") | 35 | log.Critical("critical") |
| 36 | log.Emergency("emergency") | ||
| 26 | time.Sleep(time.Second * 4) | 37 | time.Sleep(time.Second * 4) |
| 27 | f, err := os.Open("test.log") | 38 | f, err := os.Open("test.log") |
| 28 | if err != nil { | 39 | if err != nil { |
| ... | @@ -39,21 +50,24 @@ func TestFile(t *testing.T) { | ... | @@ -39,21 +50,24 @@ func TestFile(t *testing.T) { |
| 39 | linenum++ | 50 | linenum++ |
| 40 | } | 51 | } |
| 41 | } | 52 | } |
| 42 | if linenum != 6 { | 53 | var expected = LevelDebug + 1 |
| 43 | t.Fatal(linenum, "not line 6") | 54 | if linenum != expected { |
| 55 | t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines") | ||
| 44 | } | 56 | } |
| 45 | os.Remove("test.log") | 57 | os.Remove("test.log") |
| 46 | } | 58 | } |
| 47 | 59 | ||
| 48 | func TestFile2(t *testing.T) { | 60 | func TestFile2(t *testing.T) { |
| 49 | log := NewLogger(10000) | 61 | log := NewLogger(10000) |
| 50 | log.SetLogger("file", `{"filename":"test2.log","level":2}`) | 62 | log.SetLogger("file", fmt.Sprintf(`{"filename":"test2.log","level":%d}`, LevelError)) |
| 51 | log.Trace("test") | ||
| 52 | log.Info("info") | ||
| 53 | log.Debug("debug") | 63 | log.Debug("debug") |
| 54 | log.Warn("warning") | 64 | log.Info("info") |
| 65 | log.Notice("notice") | ||
| 66 | log.Warning("warning") | ||
| 55 | log.Error("error") | 67 | log.Error("error") |
| 68 | log.Alert("alert") | ||
| 56 | log.Critical("critical") | 69 | log.Critical("critical") |
| 70 | log.Emergency("emergency") | ||
| 57 | time.Sleep(time.Second * 4) | 71 | time.Sleep(time.Second * 4) |
| 58 | f, err := os.Open("test2.log") | 72 | f, err := os.Open("test2.log") |
| 59 | if err != nil { | 73 | if err != nil { |
| ... | @@ -70,8 +84,9 @@ func TestFile2(t *testing.T) { | ... | @@ -70,8 +84,9 @@ func TestFile2(t *testing.T) { |
| 70 | linenum++ | 84 | linenum++ |
| 71 | } | 85 | } |
| 72 | } | 86 | } |
| 73 | if linenum != 4 { | 87 | var expected = LevelError + 1 |
| 74 | t.Fatal(linenum, "not line 4") | 88 | if linenum != expected { |
| 89 | t.Fatal(linenum, "not "+strconv.Itoa(expected)+" lines") | ||
| 75 | } | 90 | } |
| 76 | os.Remove("test2.log") | 91 | os.Remove("test2.log") |
| 77 | } | 92 | } |
| ... | @@ -79,17 +94,19 @@ func TestFile2(t *testing.T) { | ... | @@ -79,17 +94,19 @@ func TestFile2(t *testing.T) { |
| 79 | func TestFileRotate(t *testing.T) { | 94 | func TestFileRotate(t *testing.T) { |
| 80 | log := NewLogger(10000) | 95 | log := NewLogger(10000) |
| 81 | log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`) | 96 | log.SetLogger("file", `{"filename":"test3.log","maxlines":4}`) |
| 82 | log.Trace("test") | ||
| 83 | log.Info("info") | ||
| 84 | log.Debug("debug") | 97 | log.Debug("debug") |
| 85 | log.Warn("warning") | 98 | log.Info("info") |
| 99 | log.Notice("notice") | ||
| 100 | log.Warning("warning") | ||
| 86 | log.Error("error") | 101 | log.Error("error") |
| 102 | log.Alert("alert") | ||
| 87 | log.Critical("critical") | 103 | log.Critical("critical") |
| 104 | log.Emergency("emergency") | ||
| 88 | time.Sleep(time.Second * 4) | 105 | time.Sleep(time.Second * 4) |
| 89 | rotatename := "test3.log" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) | 106 | rotatename := "test3.log" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) |
| 90 | b, err := exists(rotatename) | 107 | b, err := exists(rotatename) |
| 91 | if !b || err != nil { | 108 | if !b || err != nil { |
| 92 | t.Fatal("rotate not gen") | 109 | t.Fatal("rotate not generated") |
| 93 | } | 110 | } |
| 94 | os.Remove(rotatename) | 111 | os.Remove(rotatename) |
| 95 | os.Remove("test3.log") | 112 | os.Remove("test3.log") |
| ... | @@ -110,7 +127,7 @@ func BenchmarkFile(b *testing.B) { | ... | @@ -110,7 +127,7 @@ func BenchmarkFile(b *testing.B) { |
| 110 | log := NewLogger(100000) | 127 | log := NewLogger(100000) |
| 111 | log.SetLogger("file", `{"filename":"test4.log"}`) | 128 | log.SetLogger("file", `{"filename":"test4.log"}`) |
| 112 | for i := 0; i < b.N; i++ { | 129 | for i := 0; i < b.N; i++ { |
| 113 | log.Trace("trace") | 130 | log.Debug("debug") |
| 114 | } | 131 | } |
| 115 | os.Remove("test4.log") | 132 | os.Remove("test4.log") |
| 116 | } | 133 | } | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 15 | // Usage: | ||
| 16 | // | ||
| 17 | // import "github.com/astaxie/beego/logs" | ||
| 18 | // | ||
| 19 | // log := NewLogger(10000) | ||
| 20 | // log.SetLogger("console", "") | ||
| 21 | // | ||
| 22 | // > the first params stand for how many channel | ||
| 23 | // | ||
| 24 | // Use it like this: | ||
| 25 | // | ||
| 26 | // log.Trace("trace") | ||
| 27 | // log.Info("info") | ||
| 28 | // log.Warn("warning") | ||
| 29 | // log.Debug("debug") | ||
| 30 | // log.Critical("critical") | ||
| 31 | // | ||
| 32 | // more docs http://beego.me/docs/module/logs.md | ||
| 7 | package logs | 33 | package logs |
| 8 | 34 | ||
| 9 | import ( | 35 | import ( |
| ... | @@ -13,14 +39,25 @@ import ( | ... | @@ -13,14 +39,25 @@ import ( |
| 13 | "sync" | 39 | "sync" |
| 14 | ) | 40 | ) |
| 15 | 41 | ||
| 42 | // RFC5424 log message levels. | ||
| 16 | const ( | 43 | const ( |
| 17 | // log message levels | 44 | LevelEmergency = iota |
| 18 | LevelTrace = iota | 45 | LevelAlert |
| 19 | LevelDebug | ||
| 20 | LevelInfo | ||
| 21 | LevelWarn | ||
| 22 | LevelError | ||
| 23 | LevelCritical | 46 | LevelCritical |
| 47 | LevelError | ||
| 48 | LevelWarning | ||
| 49 | LevelNotice | ||
| 50 | LevelInformational | ||
| 51 | LevelDebug | ||
| 52 | ) | ||
| 53 | |||
| 54 | // Legacy loglevel constants to ensure backwards compatibility. | ||
| 55 | // | ||
| 56 | // Deprecated: will be removed in 1.5.0. | ||
| 57 | const ( | ||
| 58 | LevelInfo = LevelInformational | ||
| 59 | LevelTrace = LevelDebug | ||
| 60 | LevelWarn = LevelWarning | ||
| 24 | ) | 61 | ) |
| 25 | 62 | ||
| 26 | type loggerType func() LoggerInterface | 63 | type loggerType func() LoggerInterface |
| ... | @@ -69,6 +106,7 @@ type logMsg struct { | ... | @@ -69,6 +106,7 @@ type logMsg struct { |
| 69 | // if the buffering chan is full, logger adapters write to file or other way. | 106 | // if the buffering chan is full, logger adapters write to file or other way. |
| 70 | func NewLogger(channellen int64) *BeeLogger { | 107 | func NewLogger(channellen int64) *BeeLogger { |
| 71 | bl := new(BeeLogger) | 108 | bl := new(BeeLogger) |
| 109 | bl.level = LevelDebug | ||
| 72 | bl.loggerFuncCallDepth = 2 | 110 | bl.loggerFuncCallDepth = 2 |
| 73 | bl.msg = make(chan *logMsg, channellen) | 111 | bl.msg = make(chan *logMsg, channellen) |
| 74 | bl.outputs = make(map[string]LoggerInterface) | 112 | bl.outputs = make(map[string]LoggerInterface) |
| ... | @@ -110,7 +148,7 @@ func (bl *BeeLogger) DelLogger(adaptername string) error { | ... | @@ -110,7 +148,7 @@ func (bl *BeeLogger) DelLogger(adaptername string) error { |
| 110 | } | 148 | } |
| 111 | 149 | ||
| 112 | func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { | 150 | func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { |
| 113 | if bl.level > loglevel { | 151 | if loglevel > bl.level { |
| 114 | return nil | 152 | return nil |
| 115 | } | 153 | } |
| 116 | lm := new(logMsg) | 154 | lm := new(logMsg) |
| ... | @@ -130,8 +168,10 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { | ... | @@ -130,8 +168,10 @@ func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { |
| 130 | return nil | 168 | return nil |
| 131 | } | 169 | } |
| 132 | 170 | ||
| 133 | // set log message level. | 171 | // Set log message level. |
| 134 | // if message level (such as LevelTrace) is less than logger level (such as LevelWarn), ignore message. | 172 | // |
| 173 | // If message level (such as LevelDebug) is higher than logger level (such as LevelWarning), | ||
| 174 | // log providers will not even be sent the message. | ||
| 135 | func (bl *BeeLogger) SetLevel(l int) { | 175 | func (bl *BeeLogger) SetLevel(l int) { |
| 136 | bl.level = l | 176 | bl.level = l |
| 137 | } | 177 | } |
| ... | @@ -147,7 +187,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { | ... | @@ -147,7 +187,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { |
| 147 | } | 187 | } |
| 148 | 188 | ||
| 149 | // start logger chan reading. | 189 | // start logger chan reading. |
| 150 | // when chan is full, write logs. | 190 | // when chan is not empty, write logs. |
| 151 | func (bl *BeeLogger) startLogger() { | 191 | func (bl *BeeLogger) startLogger() { |
| 152 | for { | 192 | for { |
| 153 | select { | 193 | select { |
| ... | @@ -159,40 +199,73 @@ func (bl *BeeLogger) startLogger() { | ... | @@ -159,40 +199,73 @@ func (bl *BeeLogger) startLogger() { |
| 159 | } | 199 | } |
| 160 | } | 200 | } |
| 161 | 201 | ||
| 162 | // log trace level message. | 202 | // Log EMERGENCY level message. |
| 163 | func (bl *BeeLogger) Trace(format string, v ...interface{}) { | 203 | func (bl *BeeLogger) Emergency(format string, v ...interface{}) { |
| 164 | msg := fmt.Sprintf("[T] "+format, v...) | 204 | msg := fmt.Sprintf("[D] "+format, v...) |
| 165 | bl.writerMsg(LevelTrace, msg) | 205 | bl.writerMsg(LevelEmergency, msg) |
| 166 | } | 206 | } |
| 167 | 207 | ||
| 168 | // log debug level message. | 208 | // Log ALERT level message. |
| 169 | func (bl *BeeLogger) Debug(format string, v ...interface{}) { | 209 | func (bl *BeeLogger) Alert(format string, v ...interface{}) { |
| 170 | msg := fmt.Sprintf("[D] "+format, v...) | 210 | msg := fmt.Sprintf("[D] "+format, v...) |
| 171 | bl.writerMsg(LevelDebug, msg) | 211 | bl.writerMsg(LevelAlert, msg) |
| 172 | } | 212 | } |
| 173 | 213 | ||
| 174 | // log info level message. | 214 | // Log CRITICAL level message. |
| 175 | func (bl *BeeLogger) Info(format string, v ...interface{}) { | 215 | func (bl *BeeLogger) Critical(format string, v ...interface{}) { |
| 216 | msg := fmt.Sprintf("[C] "+format, v...) | ||
| 217 | bl.writerMsg(LevelCritical, msg) | ||
| 218 | } | ||
| 219 | |||
| 220 | // Log ERROR level message. | ||
| 221 | func (bl *BeeLogger) Error(format string, v ...interface{}) { | ||
| 222 | msg := fmt.Sprintf("[E] "+format, v...) | ||
| 223 | bl.writerMsg(LevelError, msg) | ||
| 224 | } | ||
| 225 | |||
| 226 | // Log WARNING level message. | ||
| 227 | func (bl *BeeLogger) Warning(format string, v ...interface{}) { | ||
| 228 | msg := fmt.Sprintf("[W] "+format, v...) | ||
| 229 | bl.writerMsg(LevelWarning, msg) | ||
| 230 | } | ||
| 231 | |||
| 232 | // Log NOTICE level message. | ||
| 233 | func (bl *BeeLogger) Notice(format string, v ...interface{}) { | ||
| 234 | msg := fmt.Sprintf("[W] "+format, v...) | ||
| 235 | bl.writerMsg(LevelNotice, msg) | ||
| 236 | } | ||
| 237 | |||
| 238 | // Log INFORMATIONAL level message. | ||
| 239 | func (bl *BeeLogger) Informational(format string, v ...interface{}) { | ||
| 176 | msg := fmt.Sprintf("[I] "+format, v...) | 240 | msg := fmt.Sprintf("[I] "+format, v...) |
| 177 | bl.writerMsg(LevelInfo, msg) | 241 | bl.writerMsg(LevelInformational, msg) |
| 178 | } | 242 | } |
| 179 | 243 | ||
| 180 | // log warn level message. | 244 | // Log DEBUG level message. |
| 245 | func (bl *BeeLogger) Debug(format string, v ...interface{}) { | ||
| 246 | msg := fmt.Sprintf("[D] "+format, v...) | ||
| 247 | bl.writerMsg(LevelDebug, msg) | ||
| 248 | } | ||
| 249 | |||
| 250 | // Log WARN level message. | ||
| 251 | // | ||
| 252 | // Deprecated: compatibility alias for Warning(), Will be removed in 1.5.0. | ||
| 181 | func (bl *BeeLogger) Warn(format string, v ...interface{}) { | 253 | func (bl *BeeLogger) Warn(format string, v ...interface{}) { |
| 182 | msg := fmt.Sprintf("[W] "+format, v...) | 254 | bl.Warning(format, v...) |
| 183 | bl.writerMsg(LevelWarn, msg) | ||
| 184 | } | 255 | } |
| 185 | 256 | ||
| 186 | // log error level message. | 257 | // Log INFO level message. |
| 187 | func (bl *BeeLogger) Error(format string, v ...interface{}) { | 258 | // |
| 188 | msg := fmt.Sprintf("[E] "+format, v...) | 259 | // Deprecated: compatibility alias for Informational(), Will be removed in 1.5.0. |
| 189 | bl.writerMsg(LevelError, msg) | 260 | func (bl *BeeLogger) Info(format string, v ...interface{}) { |
| 261 | bl.Informational(format, v...) | ||
| 190 | } | 262 | } |
| 191 | 263 | ||
| 192 | // log critical level message. | 264 | // Log TRACE level message. |
| 193 | func (bl *BeeLogger) Critical(format string, v ...interface{}) { | 265 | // |
| 194 | msg := fmt.Sprintf("[C] "+format, v...) | 266 | // Deprecated: compatibility alias for Debug(), Will be removed in 1.5.0. |
| 195 | bl.writerMsg(LevelCritical, msg) | 267 | func (bl *BeeLogger) Trace(format string, v ...interface{}) { |
| 268 | bl.Debug(format, v...) | ||
| 196 | } | 269 | } |
| 197 | 270 | ||
| 198 | // flush all chan data. | 271 | // flush all chan data. | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ||
| ... | @@ -51,22 +59,30 @@ func (s *SmtpWriter) Init(jsonconfig string) error { | ... | @@ -51,22 +59,30 @@ func (s *SmtpWriter) Init(jsonconfig string) error { |
| 51 | return nil | 59 | return nil |
| 52 | } | 60 | } |
| 53 | 61 | ||
| 62 | func (s *SmtpWriter) GetSmtpAuth(host string) smtp.Auth { | ||
| 63 | if len(strings.Trim(s.Username, " ")) == 0 && len(strings.Trim(s.Password, " ")) == 0 { | ||
| 64 | return nil | ||
| 65 | } | ||
| 66 | return smtp.PlainAuth( | ||
| 67 | "", | ||
| 68 | s.Username, | ||
| 69 | s.Password, | ||
| 70 | host, | ||
| 71 | ) | ||
| 72 | } | ||
| 73 | |||
| 54 | // write message in smtp writer. | 74 | // write message in smtp writer. |
| 55 | // it will send an email with subject and only this message. | 75 | // it will send an email with subject and only this message. |
| 56 | func (s *SmtpWriter) WriteMsg(msg string, level int) error { | 76 | func (s *SmtpWriter) WriteMsg(msg string, level int) error { |
| 57 | if level < s.Level { | 77 | if level > s.Level { |
| 58 | return nil | 78 | return nil |
| 59 | } | 79 | } |
| 60 | 80 | ||
| 61 | hp := strings.Split(s.Host, ":") | 81 | hp := strings.Split(s.Host, ":") |
| 62 | 82 | ||
| 63 | // Set up authentication information. | 83 | // Set up authentication information. |
| 64 | auth := smtp.PlainAuth( | 84 | auth := s.GetSmtpAuth(hp[0]) |
| 65 | "", | 85 | |
| 66 | s.Username, | ||
| 67 | s.Password, | ||
| 68 | hp[0], | ||
| 69 | ) | ||
| 70 | // Connect to the server, authenticate, set the sender and recipient, | 86 | // Connect to the server, authenticate, set the sender and recipient, |
| 71 | // and send the email all in one step. | 87 | // and send the email all in one step. |
| 72 | content_type := "Content-Type: text/plain" + "; charset=UTF-8" | 88 | content_type := "Content-Type: text/plain" + "; charset=UTF-8" | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package logs | 15 | package logs |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package beego | 15 | package beego |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package middleware | 15 | package middleware |
| 8 | 16 | ||
| ... | @@ -311,6 +319,7 @@ func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg strin | ... | @@ -311,6 +319,7 @@ func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg strin |
| 311 | if err != nil { | 319 | if err != nil { |
| 312 | isint = 500 | 320 | isint = 500 |
| 313 | } | 321 | } |
| 322 | w.Header().Set("Content-Type", "text/html; charset=utf-8") | ||
| 314 | w.WriteHeader(isint) | 323 | w.WriteHeader(isint) |
| 315 | h(w, r) | 324 | h(w, r) |
| 316 | return | 325 | return | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 6 | 14 | ||
| 7 | package middleware | 15 | package middleware |
| 8 | 16 | ... | ... |
| 1 | // Beego (http://beego.me/) | 1 | // Copyright 2014 beego Author. All Rights Reserved. |
| 2 | // @description beego is an open-source, high-performance web framework for the Go programming language. | 2 | // |
| 3 | // @link http://github.com/astaxie/beego for the canonical source repository | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | 4 | // you may not use this file except in compliance with the License. |
| 5 | // @authors astaxie | 5 | // You may obtain a copy of the License at |
| 6 | 6 | // | |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | // Usage: | ||
| 16 | // | ||
| 17 | // import "github.com/astaxie/beego/middleware" | ||
| 18 | // | ||
| 19 | // I18N = middleware.NewLocale("conf/i18n.conf", beego.AppConfig.String("language")) | ||
| 20 | // | ||
| 21 | // more docs: http://beego.me/docs/module/i18n.md | ||
| 7 | package middleware | 22 | package middleware |
| 8 | 23 | ||
| 9 | //import ( | 24 | import ( |
| 10 | // "github.com/astaxie/beego/config" | 25 | "encoding/json" |
| 11 | // "os" | 26 | "io/ioutil" |
| 12 | // "path" | 27 | "os" |
| 13 | //) | 28 | ) |
| 14 | 29 | ||
| 15 | //type Translation struct { | 30 | type Translation struct { |
| 16 | // filetype string | 31 | filepath string |
| 17 | // CurrentLocal string | 32 | CurrentLocal string |
| 18 | // Locales map[string]map[string]string | 33 | Locales map[string]map[string]string |
| 19 | //} | 34 | } |
| 20 | 35 | ||
| 21 | //func NewLocale(filetype string) *Translation { | 36 | func NewLocale(filepath string, defaultlocal string) *Translation { |
| 22 | // return &Translation{ | 37 | i18n := make(map[string]map[string]string) |
| 23 | // filetype: filetype, | 38 | file, err := os.Open(filepath) |
| 24 | // CurrentLocal: "zh", | 39 | if err != nil { |
| 25 | // Locales: make(map[string]map[string]string), | 40 | panic("open " + filepath + " err :" + err.Error()) |
| 26 | // } | 41 | } |
| 27 | //} | 42 | data, err := ioutil.ReadAll(file) |
| 28 | 43 | if err != nil { | |
| 29 | //func (t *Translation) loadTranslations(dirPath string) error { | 44 | panic("read " + filepath + " err :" + err.Error()) |
| 30 | // dir, err := os.Open(dirPath) | 45 | } |
| 31 | // if err != nil { | 46 | err = json.Unmarshal(data, &i18n) |
| 32 | // return err | 47 | if err != nil { |
| 33 | // } | 48 | panic("json.Unmarshal " + filepath + " err :" + err.Error()) |
| 34 | // defer dir.Close() | 49 | } |
| 35 | 50 | return &Translation{ | |
| 36 | // names, err := dir.Readdirnames(-1) | 51 | filepath: filepath, |
| 37 | // if err != nil { | 52 | CurrentLocal: defaultlocal, |
| 38 | // return err | 53 | Locales: i18n, |
| 39 | // } | 54 | } |
| 40 | 55 | } | |
| 41 | // for _, name := range names { | 56 | |
| 42 | // fullPath := path.Join(dirPath, name) | 57 | func (t *Translation) SetLocale(local string) { |
| 43 | 58 | t.CurrentLocal = local | |
| 44 | // fi, err := os.Stat(fullPath) | 59 | } |
| 45 | // if err != nil { | 60 | |
| 46 | // return err | 61 | func (t *Translation) Translate(key string, local string) string { |
| 47 | // } | 62 | if local == "" { |
| 48 | 63 | local = t.CurrentLocal | |
| 49 | // if fi.IsDir() { | 64 | } |
| 50 | // continue | 65 | if ct, ok := t.Locales[key]; ok { |
| 51 | // } else { | 66 | if v, o := ct[local]; o { |
| 52 | // if err := t.loadTranslation(fullPath, name); err != nil { | 67 | return v |
| 53 | // return err | 68 | } |
| 54 | // } | 69 | } |
| 55 | // } | 70 | return key |
| 56 | // } | 71 | } |
| 57 | |||
| 58 | // return nil | ||
| 59 | //} | ||
| 60 | |||
| 61 | //func (t *Translation) loadTranslation(fullPath, locale string) error { | ||
| 62 | |||
| 63 | // sourceKey2Trans, ok := t.Locales[locale] | ||
| 64 | // if !ok { | ||
| 65 | // sourceKey2Trans = make(map[string]string) | ||
| 66 | |||
| 67 | // t.Locales[locale] = sourceKey2Trans | ||
| 68 | // } | ||
| 69 | |||
| 70 | // for _, m := range trf.Messages { | ||
| 71 | // if m.Translation != "" { | ||
| 72 | // sourceKey2Trans[sourceKey(m.Source, m.Context)] = m.Translation | ||
| 73 | // } | ||
| 74 | // } | ||
| 75 | |||
| 76 | // return nil | ||
| 77 | //} | ||
| 78 | |||
| 79 | //func (t *Translation) SetLocale(local string) { | ||
| 80 | // t.CurrentLocal = local | ||
| 81 | //} | ||
| 82 | |||
| 83 | //func (t *Translation) Translate(key string) string { | ||
| 84 | // if ct, ok := t.Locales[t.CurrentLocal]; ok { | ||
| 85 | // if v, o := ct[key]; o { | ||
| 86 | // return v | ||
| 87 | // } | ||
| 88 | // } | ||
| 89 | // return key | ||
| 90 | //} | ... | ... |
migration/migration.go
0 → 100644
| 1 | // Copyright 2014 beego Author. All Rights Reserved. | ||
| 2 | // | ||
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | // you may not use this file except in compliance with the License. | ||
| 5 | // You may obtain a copy of the License at | ||
| 6 | // | ||
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | // | ||
| 9 | // Unless required by applicable law or agreed to in writing, software | ||
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | // See the License for the specific language governing permissions and | ||
| 13 | // limitations under the License. | ||
| 14 | |||
| 15 | // migration package for migration | ||
| 16 | // | ||
| 17 | // The table structure is as follow: | ||
| 18 | // | ||
| 19 | // CREATE TABLE `migrations` ( | ||
| 20 | // `id_migration` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'surrogate key', | ||
| 21 | // `name` varchar(255) DEFAULT NULL COMMENT 'migration name, unique', | ||
| 22 | // `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'date migrated or rolled back', | ||
| 23 | // `statements` longtext COMMENT 'SQL statements for this migration', | ||
| 24 | // `rollback_statements` longtext, | ||
| 25 | // `status` enum('update','rollback') DEFAULT NULL COMMENT 'update indicates it is a normal migration while rollback means this migration is rolled back', | ||
| 26 | // PRIMARY KEY (`id_migration`) | ||
| 27 | // ) ENGINE=InnoDB DEFAULT CHARSET=utf8; | ||
| 28 | package migration | ||
| 29 | |||
| 30 | import ( | ||
| 31 | "errors" | ||
| 32 | "sort" | ||
| 33 | "strings" | ||
| 34 | "time" | ||
| 35 | |||
| 36 | "github.com/astaxie/beego" | ||
| 37 | "github.com/astaxie/beego/orm" | ||
| 38 | ) | ||
| 39 | |||
| 40 | // const the data format for the bee generate migration datatype | ||
| 41 | const ( | ||
| 42 | M_DATE_FORMAT = "20060102_150405" | ||
| 43 | M_DB_DATE_FORMAT = "2006-01-02 15:04:05" | ||
| 44 | ) | ||
| 45 | |||
| 46 | // Migrationer is an interface for all Migration struct | ||
| 47 | type Migrationer interface { | ||
| 48 | Up() | ||
| 49 | Down() | ||
| 50 | Reset() | ||
| 51 | Exec(name, status string) error | ||
| 52 | GetCreated() int64 | ||
| 53 | } | ||
| 54 | |||
| 55 | var ( | ||
| 56 | migrationMap map[string]Migrationer | ||
| 57 | ) | ||
| 58 | |||
| 59 | func init() { | ||
| 60 | migrationMap = make(map[string]Migrationer) | ||
| 61 | } | ||
| 62 | |||
| 63 | // the basic type which will implement the basic type | ||
| 64 | type Migration struct { | ||
| 65 | sqls []string | ||
| 66 | Created string | ||
| 67 | } | ||
| 68 | |||
| 69 | // implement in the Inheritance struct for upgrade | ||
| 70 | func (m *Migration) Up() { | ||
| 71 | |||
| 72 | } | ||
| 73 | |||
| 74 | // implement in the Inheritance struct for down | ||
| 75 | func (m *Migration) Down() { | ||
| 76 | |||
| 77 | } | ||
| 78 | |||
| 79 | // add sql want to execute | ||
| 80 | func (m *Migration) Sql(sql string) { | ||
| 81 | m.sqls = append(m.sqls, sql) | ||
| 82 | } | ||
| 83 | |||
| 84 | // Reset the sqls | ||
| 85 | func (m *Migration) Reset() { | ||
| 86 | m.sqls = make([]string, 0) | ||
| 87 | } | ||
| 88 | |||
| 89 | // execute the sql already add in the sql | ||
| 90 | func (m *Migration) Exec(name, status string) error { | ||
| 91 | o := orm.NewOrm() | ||
| 92 | for _, s := range m.sqls { | ||
| 93 | beego.Info("exec sql:", s) | ||
| 94 | r := o.Raw(s) | ||
| 95 | _, err := r.Exec() | ||
| 96 | if err != nil { | ||
| 97 | return err | ||
| 98 | } | ||
| 99 | } | ||
| 100 | return m.addOrUpdateRecord(name, status) | ||
| 101 | } | ||
| 102 | |||
| 103 | func (m *Migration) addOrUpdateRecord(name, status string) error { | ||
| 104 | o := orm.NewOrm() | ||
| 105 | if status == "down" { | ||
| 106 | status = "rollback" | ||
| 107 | p, err := o.Raw("update migrations set `status` = ?, `rollback_statements` = ?, `created_at` = ? where name = ?").Prepare() | ||
| 108 | if err != nil { | ||
| 109 | return nil | ||
| 110 | } | ||
| 111 | _, err = p.Exec(status, strings.Join(m.sqls, "; "), time.Now().Format(M_DB_DATE_FORMAT), name) | ||
| 112 | return err | ||
| 113 | } else { | ||
| 114 | status = "update" | ||
| 115 | p, err := o.Raw("insert into migrations(`name`, `created_at`, `statements`, `status`) values(?,?,?,?)").Prepare() | ||
| 116 | if err != nil { | ||
| 117 | return err | ||
| 118 | } | ||
| 119 | _, err = p.Exec(name, time.Now().Format(M_DB_DATE_FORMAT), strings.Join(m.sqls, "; "), status) | ||
| 120 | return err | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | // get the unixtime from the Created | ||
| 125 | func (m *Migration) GetCreated() int64 { | ||
| 126 | t, err := time.Parse(M_DATE_FORMAT, m.Created) | ||
| 127 | if err != nil { | ||
| 128 | return 0 | ||
| 129 | } | ||
| 130 | return t.Unix() | ||
| 131 | } | ||
| 132 | |||
| 133 | // register the Migration in the map | ||
| 134 | func Register(name string, m Migrationer) error { | ||
| 135 | if _, ok := migrationMap[name]; ok { | ||
| 136 | return errors.New("already exist name:" + name) | ||
| 137 | } | ||
| 138 | migrationMap[name] = m | ||
| 139 | return nil | ||
| 140 | } | ||
| 141 | |||
| 142 | // upgrate the migration from lasttime | ||
| 143 | func Upgrade(lasttime int64) error { | ||
| 144 | sm := sortMap(migrationMap) | ||
| 145 | i := 0 | ||
| 146 | for _, v := range sm { | ||
| 147 | if v.created > lasttime { | ||
| 148 | beego.Info("start upgrade", v.name) | ||
| 149 | v.m.Reset() | ||
| 150 | v.m.Up() | ||
| 151 | err := v.m.Exec(v.name, "up") | ||
| 152 | if err != nil { | ||
| 153 | beego.Error("execute error:", err) | ||
| 154 | time.Sleep(2 * time.Second) | ||
| 155 | return err | ||
| 156 | } | ||
| 157 | beego.Info("end upgrade:", v.name) | ||
| 158 | i++ | ||
| 159 | } | ||
| 160 | } | ||
| 161 | beego.Info("total success upgrade:", i, " migration") | ||
| 162 | time.Sleep(2 * time.Second) | ||
| 163 | return nil | ||
| 164 | } | ||
| 165 | |||
| 166 | //rollback the migration by the name | ||
| 167 | func Rollback(name string) error { | ||
| 168 | if v, ok := migrationMap[name]; ok { | ||
| 169 | beego.Info("start rollback") | ||
| 170 | v.Reset() | ||
| 171 | v.Down() | ||
| 172 | err := v.Exec(name, "down") | ||
| 173 | if err != nil { | ||
| 174 | beego.Error("execute error:", err) | ||
| 175 | time.Sleep(2 * time.Second) | ||
| 176 | return err | ||
| 177 | } | ||
| 178 | beego.Info("end rollback") | ||
| 179 | time.Sleep(2 * time.Second) | ||
| 180 | return nil | ||
| 181 | } else { | ||
| 182 | beego.Error("not exist the migrationMap name:" + name) | ||
| 183 | time.Sleep(2 * time.Second) | ||
| 184 | return errors.New("not exist the migrationMap name:" + name) | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | // reset all migration | ||
| 189 | // run all migration's down function | ||
| 190 | func Reset() error { | ||
| 191 | sm := sortMap(migrationMap) | ||
| 192 | i := 0 | ||
| 193 | for j := len(sm) - 1; j >= 0; j-- { | ||
| 194 | v := sm[j] | ||
| 195 | if isRollBack(v.name) { | ||
| 196 | beego.Info("skip the", v.name) | ||
| 197 | time.Sleep(1 * time.Second) | ||
| 198 | continue | ||
| 199 | } | ||
| 200 | beego.Info("start reset:", v.name) | ||
| 201 | v.m.Reset() | ||
| 202 | v.m.Down() | ||
| 203 | err := v.m.Exec(v.name, "down") | ||
| 204 | if err != nil { | ||
| 205 | beego.Error("execute error:", err) | ||
| 206 | time.Sleep(2 * time.Second) | ||
| 207 | return err | ||
| 208 | } | ||
| 209 | i++ | ||
| 210 | beego.Info("end reset:", v.name) | ||
| 211 | } | ||
| 212 | beego.Info("total success reset:", i, " migration") | ||
| 213 | time.Sleep(2 * time.Second) | ||
| 214 | return nil | ||
| 215 | } | ||
| 216 | |||
| 217 | // first Reset, then Upgrade | ||
| 218 | func Refresh() error { | ||
| 219 | err := Reset() | ||
| 220 | if err != nil { | ||
| 221 | beego.Error("execute error:", err) | ||
| 222 | time.Sleep(2 * time.Second) | ||
| 223 | return err | ||
| 224 | } | ||
| 225 | err = Upgrade(0) | ||
| 226 | return err | ||
| 227 | } | ||
| 228 | |||
| 229 | type dataSlice []data | ||
| 230 | |||
| 231 | type data struct { | ||
| 232 | created int64 | ||
| 233 | name string | ||
| 234 | m Migrationer | ||
| 235 | } | ||
| 236 | |||
| 237 | // Len is part of sort.Interface. | ||
| 238 | func (d dataSlice) Len() int { | ||
| 239 | return len(d) | ||
| 240 | } | ||
| 241 | |||
| 242 | // Swap is part of sort.Interface. | ||
| 243 | func (d dataSlice) Swap(i, j int) { | ||
| 244 | d[i], d[j] = d[j], d[i] | ||
| 245 | } | ||
| 246 | |||
| 247 | // Less is part of sort.Interface. We use count as the value to sort by | ||
| 248 | func (d dataSlice) Less(i, j int) bool { | ||
| 249 | return d[i].created < d[j].created | ||
| 250 | } | ||
| 251 | |||
| 252 | func sortMap(m map[string]Migrationer) dataSlice { | ||
| 253 | s := make(dataSlice, 0, len(m)) | ||
| 254 | for k, v := range m { | ||
| 255 | d := data{} | ||
| 256 | d.created = v.GetCreated() | ||
| 257 | d.name = k | ||
| 258 | d.m = v | ||
| 259 | s = append(s, d) | ||
| 260 | } | ||
| 261 | sort.Sort(s) | ||
| 262 | return s | ||
| 263 | } | ||
| 264 | |||
| 265 | func isRollBack(name string) bool { | ||
| 266 | o := orm.NewOrm() | ||
| 267 | var maps []orm.Params | ||
| 268 | num, err := o.Raw("select * from migrations where `name` = ? order by id_migration desc", name).Values(&maps) | ||
| 269 | if err != nil { | ||
| 270 | beego.Info("get name has error", err) | ||
| 271 | return false | ||
| 272 | } | ||
| 273 | if num <= 0 { | ||
| 274 | return false | ||
| 275 | } | ||
| 276 | if maps[0]["status"] == "rollback" { | ||
| 277 | return true | ||
| 278 | } | ||
| 279 | return false | ||
| 280 | } |
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
orm/docs/zh/Cmd.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/CustomFields.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Models.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Models.sql
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Object.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Orm.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Query.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/README.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Raw.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Test.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
orm/docs/zh/Transaction.md
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
plugins/cors/cors.go
0 → 100644
This diff is collapsed.
Click to expand it.
plugins/cors/cors_test.go
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
testing/assertions.go
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment