75d28d49 by astaxie

Merge pull request #965 from shuoli84/develop

Fix subdomain, add test, space and comment fix
2 parents 76bb4827 572508dd
...@@ -17,13 +17,10 @@ package config ...@@ -17,13 +17,10 @@ package config
17 import ( 17 import (
18 "encoding/json" 18 "encoding/json"
19 "errors" 19 "errors"
20 "fmt"
21 "io/ioutil" 20 "io/ioutil"
22 "os" 21 "os"
23 "path"
24 "strings" 22 "strings"
25 "sync" 23 "sync"
26 "time"
27 ) 24 )
28 25
29 // JsonConfig is a json config parser and implements Config interface. 26 // JsonConfig is a json config parser and implements Config interface.
...@@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { ...@@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
41 if err != nil { 38 if err != nil {
42 return nil, err 39 return nil, err
43 } 40 }
41
42 return js.ParseData(content)
43 }
44
45 // ParseData returns a ConfigContainer with json string
46 func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) {
44 x := &JsonConfigContainer{ 47 x := &JsonConfigContainer{
45 data: make(map[string]interface{}), 48 data: make(map[string]interface{}),
46 } 49 }
47 err = json.Unmarshal(content, &x.data) 50 err := json.Unmarshal(data, &x.data)
48 if err != nil { 51 if err != nil {
49 var wrappingArray []interface{} 52 var wrappingArray []interface{}
50 err2 := json.Unmarshal(content, &wrappingArray) 53 err2 := json.Unmarshal(data, &wrappingArray)
51 if err2 != nil { 54 if err2 != nil {
52 return nil, err 55 return nil, err
53 } 56 }
...@@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { ...@@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
56 return x, nil 59 return x, nil
57 } 60 }
58 61
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
69 // A Config represents the json configuration. 62 // A Config represents the json configuration.
70 // Only when get value, support key as section:name type. 63 // Only when get value, support key as section:name type.
71 type JsonConfigContainer struct { 64 type JsonConfigContainer struct {
...@@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) { ...@@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) {
88 // DefaultBool return the bool value if has no error 81 // DefaultBool return the bool value if has no error
89 // otherwise return the defaultval 82 // otherwise return the defaultval
90 func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { 83 func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool {
91 if v, err := c.Bool(key); err != nil { 84 if v, err := c.Bool(key); err == nil {
92 return defaultval
93 } else {
94 return v 85 return v
95 } 86 }
87 return defaultval
96 } 88 }
97 89
98 // Int returns the integer value for a given key. 90 // Int returns the integer value for a given key.
...@@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) { ...@@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) {
110 // DefaultInt returns the integer value for a given key. 102 // DefaultInt returns the integer value for a given key.
111 // if err != nil return defaltval 103 // if err != nil return defaltval
112 func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { 104 func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int {
113 if v, err := c.Int(key); err != nil { 105 if v, err := c.Int(key); err == nil {
114 return defaultval
115 } else {
116 return v 106 return v
117 } 107 }
108 return defaultval
118 } 109 }
119 110
120 // Int64 returns the int64 value for a given key. 111 // Int64 returns the int64 value for a given key.
...@@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) { ...@@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) {
132 // DefaultInt64 returns the int64 value for a given key. 123 // DefaultInt64 returns the int64 value for a given key.
133 // if err != nil return defaltval 124 // if err != nil return defaltval
134 func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { 125 func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
135 if v, err := c.Int64(key); err != nil { 126 if v, err := c.Int64(key); err == nil {
136 return defaultval
137 } else {
138 return v 127 return v
139 } 128 }
129 return defaultval
140 } 130 }
141 131
142 // Float returns the float value for a given key. 132 // Float returns the float value for a given key.
...@@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) { ...@@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) {
154 // DefaultFloat returns the float64 value for a given key. 144 // DefaultFloat returns the float64 value for a given key.
155 // if err != nil return defaltval 145 // if err != nil return defaltval
156 func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { 146 func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
157 if v, err := c.Float(key); err != nil { 147 if v, err := c.Float(key); err == nil {
158 return defaultval
159 } else {
160 return v 148 return v
161 } 149 }
150 return defaultval
162 } 151 }
163 152
164 // String returns the string value for a given key. 153 // String returns the string value for a given key.
...@@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string { ...@@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string {
175 // DefaultString returns the string value for a given key. 164 // DefaultString returns the string value for a given key.
176 // if err != nil return defaltval 165 // if err != nil return defaltval
177 func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { 166 func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string {
178 if v := c.String(key); v == "" { 167 // TODO FIXME should not use "" to replace non existance
179 return defaultval 168 if v := c.String(key); v != "" {
180 } else {
181 return v 169 return v
182 } 170 }
171 return defaultval
183 } 172 }
184 173
185 // Strings returns the []string value for a given key. 174 // Strings returns the []string value for a given key.
186 func (c *JsonConfigContainer) Strings(key string) []string { 175 func (c *JsonConfigContainer) Strings(key string) []string {
176 stringVal := c.String(key)
177 if stringVal == "" {
178 return []string{}
179 }
187 return strings.Split(c.String(key), ";") 180 return strings.Split(c.String(key), ";")
188 } 181 }
189 182
190 // DefaultStrings returns the []string value for a given key. 183 // DefaultStrings returns the []string value for a given key.
191 // if err != nil return defaltval 184 // if err != nil return defaltval
192 func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { 185 func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string {
193 if v := c.Strings(key); len(v) == 0 { 186 if v := c.Strings(key); len(v) > 0 {
194 return defaultval
195 } else {
196 return v 187 return v
197 } 188 }
189 return defaultval
198 } 190 }
199 191
200 // GetSection returns map for the given section 192 // GetSection returns map for the given section
201 func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { 193 func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) {
202 if v, ok := c.data[section]; ok { 194 if v, ok := c.data[section]; ok {
203 return v.(map[string]string), nil 195 return v.(map[string]string), nil
204 } else {
205 return nil, errors.New("not exist setction")
206 } 196 }
197 return nil, errors.New("nonexist section " + section)
207 } 198 }
208 199
209 // SaveConfigFile save the config into file 200 // SaveConfigFile save the config into file
...@@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { ...@@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) {
222 return err 213 return err
223 } 214 }
224 215
225 // WriteValue writes a new value for key. 216 // Set writes a new value for key.
226 func (c *JsonConfigContainer) Set(key, val string) error { 217 func (c *JsonConfigContainer) Set(key, val string) error {
227 c.Lock() 218 c.Lock()
228 defer c.Unlock() 219 defer c.Unlock()
...@@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { ...@@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
241 232
242 // section.key or key 233 // section.key or key
243 func (c *JsonConfigContainer) getData(key string) interface{} { 234 func (c *JsonConfigContainer) getData(key string) interface{} {
244 c.RLock()
245 defer c.RUnlock()
246 if len(key) == 0 { 235 if len(key) == 0 {
247 return nil 236 return nil
248 } 237 }
249 sectionKey := strings.Split(key, "::") 238
250 if len(sectionKey) >= 2 { 239 c.RLock()
251 curValue, ok := c.data[sectionKey[0]] 240 defer c.RUnlock()
241
242 sectionKeys := strings.Split(key, "::")
243 if len(sectionKeys) >= 2 {
244 curValue, ok := c.data[sectionKeys[0]]
252 if !ok { 245 if !ok {
253 return nil 246 return nil
254 } 247 }
255 for _, key := range sectionKey[1:] { 248 for _, key := range sectionKeys[1:] {
256 if v, ok := curValue.(map[string]interface{}); ok { 249 if v, ok := curValue.(map[string]interface{}); ok {
257 if curValue, ok = v[key]; !ok { 250 if curValue, ok = v[key]; !ok {
258 return nil 251 return nil
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
21 21
22 var jsoncontext = `{ 22 var jsoncontext = `{
23 "appname": "beeapi", 23 "appname": "beeapi",
24 "testnames": "foo;bar",
24 "httpport": 8080, 25 "httpport": 8080,
25 "mysqlport": 3600, 26 "mysqlport": 3600,
26 "PI": 3.1415976, 27 "PI": 3.1415976,
...@@ -28,8 +29,8 @@ var jsoncontext = `{ ...@@ -28,8 +29,8 @@ var jsoncontext = `{
28 "autorender": false, 29 "autorender": false,
29 "copyrequestbody": true, 30 "copyrequestbody": true,
30 "database": { 31 "database": {
31 "host": "host", 32 "host": "host",
32 "port": "port", 33 "port": "port",
33 "database": "database", 34 "database": "database",
34 "username": "username", 35 "username": "username",
35 "password": "password", 36 "password": "password",
...@@ -122,6 +123,12 @@ func TestJson(t *testing.T) { ...@@ -122,6 +123,12 @@ func TestJson(t *testing.T) {
122 if jsonconf.String("runmode") != "dev" { 123 if jsonconf.String("runmode") != "dev" {
123 t.Fatal("runmode not equal to dev") 124 t.Fatal("runmode not equal to dev")
124 } 125 }
126 if v := jsonconf.Strings("unknown"); len(v) > 0 {
127 t.Fatal("unknown strings, the length should be 0")
128 }
129 if v := jsonconf.Strings("testnames"); len(v) != 2 {
130 t.Fatal("testnames length should be 2")
131 }
125 if v, err := jsonconf.Bool("autorender"); err != nil || v != false { 132 if v, err := jsonconf.Bool("autorender"); err != nil || v != false {
126 t.Error(v) 133 t.Error(v)
127 t.Fatal(err) 134 t.Fatal(err)
...@@ -179,4 +186,8 @@ func TestJson(t *testing.T) { ...@@ -179,4 +186,8 @@ func TestJson(t *testing.T) {
179 if _, err := jsonconf.Bool("unknown"); err == nil { 186 if _, err := jsonconf.Bool("unknown"); err == nil {
180 t.Error("unknown keys should return an error when expecting a Bool") 187 t.Error("unknown keys should return an error when expecting a Bool")
181 } 188 }
189
190 if !jsonconf.DefaultBool("unknow", true) {
191 t.Error("unknown keys with default value wrong")
192 }
182 } 193 }
......
...@@ -27,7 +27,7 @@ import ( ...@@ -27,7 +27,7 @@ import (
27 "github.com/astaxie/beego/session" 27 "github.com/astaxie/beego/session"
28 ) 28 )
29 29
30 // BeegoInput operates the http request header ,data ,cookie and body. 30 // BeegoInput operates the http request header, data, cookie and body.
31 // it also contains router params and current session. 31 // it also contains router params and current session.
32 type BeegoInput struct { 32 type BeegoInput struct {
33 CruSession session.SessionStore 33 CruSession session.SessionStore
...@@ -153,12 +153,12 @@ func (input *BeegoInput) IsSecure() bool { ...@@ -153,12 +153,12 @@ func (input *BeegoInput) IsSecure() bool {
153 return input.Scheme() == "https" 153 return input.Scheme() == "https"
154 } 154 }
155 155
156 // IsSecure returns boolean of this request is in webSocket. 156 // IsWebsocket returns boolean of this request is in webSocket.
157 func (input *BeegoInput) IsWebsocket() bool { 157 func (input *BeegoInput) IsWebsocket() bool {
158 return input.Header("Upgrade") == "websocket" 158 return input.Header("Upgrade") == "websocket"
159 } 159 }
160 160
161 // IsSecure returns boolean of whether file uploads in this request or not.. 161 // IsUpload returns boolean of whether file uploads in this request or not..
162 func (input *BeegoInput) IsUpload() bool { 162 func (input *BeegoInput) IsUpload() bool {
163 return strings.Contains(input.Header("Content-Type"), "multipart/form-data") 163 return strings.Contains(input.Header("Content-Type"), "multipart/form-data")
164 } 164 }
...@@ -189,16 +189,24 @@ func (input *BeegoInput) Proxy() []string { ...@@ -189,16 +189,24 @@ func (input *BeegoInput) Proxy() []string {
189 return []string{} 189 return []string{}
190 } 190 }
191 191
192 // Referer returns http referer header.
193 func (input *BeegoInput) Referer() string {
194 return input.Header("Referer")
195 }
196
192 // Refer returns http referer header. 197 // Refer returns http referer header.
193 func (input *BeegoInput) Refer() string { 198 func (input *BeegoInput) Refer() string {
194 return input.Header("Referer") 199 return input.Referer()
195 } 200 }
196 201
197 // SubDomains returns sub domain string. 202 // SubDomains returns sub domain string.
198 // if aa.bb.domain.com, returns aa.bb . 203 // if aa.bb.domain.com, returns aa.bb .
199 func (input *BeegoInput) SubDomains() string { 204 func (input *BeegoInput) SubDomains() string {
200 parts := strings.Split(input.Host(), ".") 205 parts := strings.Split(input.Host(), ".")
201 return strings.Join(parts[:len(parts)-2], ".") 206 if len(parts) >= 3 {
207 return strings.Join(parts[:len(parts)-2], ".")
208 }
209 return ""
202 } 210 }
203 211
204 // Port returns request client port. 212 // Port returns request client port.
...@@ -237,6 +245,7 @@ func (input *BeegoInput) Query(key string) string { ...@@ -237,6 +245,7 @@ func (input *BeegoInput) Query(key string) string {
237 } 245 }
238 246
239 // Header returns request header item string by a given string. 247 // Header returns request header item string by a given string.
248 // if non-existed, return empty string.
240 func (input *BeegoInput) Header(key string) string { 249 func (input *BeegoInput) Header(key string) string {
241 return input.Request.Header.Get(key) 250 return input.Request.Header.Get(key)
242 } 251 }
...@@ -252,11 +261,12 @@ func (input *BeegoInput) Cookie(key string) string { ...@@ -252,11 +261,12 @@ func (input *BeegoInput) Cookie(key string) string {
252 } 261 }
253 262
254 // Session returns current session item value by a given key. 263 // Session returns current session item value by a given key.
264 // if non-existed, return empty string.
255 func (input *BeegoInput) Session(key interface{}) interface{} { 265 func (input *BeegoInput) Session(key interface{}) interface{} {
256 return input.CruSession.Get(key) 266 return input.CruSession.Get(key)
257 } 267 }
258 268
259 // Body returns the raw request body data as bytes. 269 // CopyBody returns the raw request body data as bytes.
260 func (input *BeegoInput) CopyBody() []byte { 270 func (input *BeegoInput) CopyBody() []byte {
261 requestbody, _ := ioutil.ReadAll(input.Request.Body) 271 requestbody, _ := ioutil.ReadAll(input.Request.Body)
262 input.Request.Body.Close() 272 input.Request.Body.Close()
......
...@@ -70,3 +70,45 @@ func TestParse(t *testing.T) { ...@@ -70,3 +70,45 @@ func TestParse(t *testing.T) {
70 } 70 }
71 fmt.Println(user) 71 fmt.Println(user)
72 } 72 }
73
74 func TestSubDomain(t *testing.T) {
75 r, _ := http.NewRequest("GET", "http://www.example.com/?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie", nil)
76 beegoInput := NewInput(r)
77
78 subdomain := beegoInput.SubDomains()
79 if subdomain != "www" {
80 t.Fatal("Subdomain parse error, got" + subdomain)
81 }
82
83 r, _ = http.NewRequest("GET", "http://localhost/", nil)
84 beegoInput.Request = r
85 if beegoInput.SubDomains() != "" {
86 t.Fatal("Subdomain parse error, should be empty, got " + beegoInput.SubDomains())
87 }
88
89 r, _ = http.NewRequest("GET", "http://aa.bb.example.com/", nil)
90 beegoInput.Request = r
91 if beegoInput.SubDomains() != "aa.bb" {
92 t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
93 }
94
95 /* TODO Fix this
96 r, _ = http.NewRequest("GET", "http://127.0.0.1/", nil)
97 beegoInput.Request = r
98 if beegoInput.SubDomains() != "" {
99 t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
100 }
101 */
102
103 r, _ = http.NewRequest("GET", "http://example.com/", nil)
104 beegoInput.Request = r
105 if beegoInput.SubDomains() != "" {
106 t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
107 }
108
109 r, _ = http.NewRequest("GET", "http://aa.bb.cc.dd.example.com/", nil)
110 beegoInput.Request = r
111 if beegoInput.SubDomains() != "aa.bb.cc.dd" {
112 t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains())
113 }
114 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!