Skip to content

Commit 3b69d03

Browse files
committed
Merge branch 'release/0.4.0'
2 parents 539d2db + 619cdaf commit 3b69d03

File tree

5 files changed

+327
-43
lines changed

5 files changed

+327
-43
lines changed

README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Hello world
4444

4545
- Serve dynamic route with parameter:
4646
```go
47+
package main
48+
49+
import (
50+
"github.com/takama/router"
51+
)
52+
4753
func main() {
4854
r := router.New()
4955
r.GET("/hello/:name", func(c *router.Control) {
@@ -69,6 +75,12 @@ Hello John
6975

7076
- Checks JSON Content-Type automatically:
7177
```go
78+
package main
79+
80+
import (
81+
"github.com/takama/router"
82+
)
83+
7284
// Data is helper to construct JSON
7385
type Data map[string]interface{}
7486

@@ -109,6 +121,12 @@ Content-Length: 102
109121

110122
- Use timer to calculate duration of request handling:
111123
```go
124+
package main
125+
126+
import (
127+
"github.com/takama/router"
128+
)
129+
112130
// Data is helper to construct JSON
113131
type Data map[string]interface{}
114132

@@ -157,6 +175,12 @@ Content-Length: 143
157175

158176
- Custom handler with "Access-Control-Allow" options and compact JSON:
159177
```go
178+
package main
179+
180+
import (
181+
"github.com/takama/router"
182+
)
183+
160184
// Data is helper to construct JSON
161185
type Data map[string]interface{}
162186

@@ -203,6 +227,59 @@ Content-Length: 28
203227
{"debug":true,"error":false}
204228
```
205229

230+
- Use google json style `https://google.github.io/styleguide/jsoncstyleguide.xml`:
231+
```go
232+
package main
233+
234+
import (
235+
"net/http"
236+
237+
"github.com/takama/router"
238+
)
239+
240+
func main() {
241+
r := router.New()
242+
r.GET("/api/v1/people/:action/:id", func(c *router.Control) {
243+
244+
// Do something
245+
246+
c.Method("people." + c.Get(":action"))
247+
c.SetParams(map[string]string{"userId": c.Get(":id")})
248+
c.SetError(http.StatusNotFound, "UserId not found")
249+
c.AddError(router.Error{Message: "Group or User not found"})
250+
c.Code(http.StatusNotFound).Body(nil)
251+
})
252+
// Listen and serve on 0.0.0.0:8888
253+
r.Listen(":8888")
254+
}
255+
```
256+
257+
- Check it:
258+
```sh
259+
curl -i http://localhost:8888/api/v1/people/get/@me
260+
261+
HTTP/1.1 404 Not Found
262+
Content-Type: application/json
263+
Date: Sat, 22 Oct 2016 14:50:00 GMT
264+
Content-Length: 220
265+
266+
{
267+
"method": "people.get",
268+
"params": {
269+
"userId": "@me"
270+
},
271+
"error": {
272+
"code": 404,
273+
"message": "UserId not found",
274+
"errors": [
275+
{
276+
"message": "Group or User not found"
277+
}
278+
]
279+
}
280+
}
281+
```
282+
206283
## Author
207284

208285
[Igor Dolzhikov](https://github.com/takama)

control.go

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,44 +36,78 @@ type Control struct {
3636
// Code of HTTP status
3737
code int
3838

39-
// CompactJSON propery defines JSON output format (default is not compact)
39+
// compactJSON propery defines JSON output format (default is not compact)
4040
compactJSON bool
4141

42-
// Params is set of parameters
43-
Params []Param
42+
// if used, json header shows meta data
43+
useMetaData bool
44+
45+
// header with metadata
46+
header Header
47+
48+
// errors
49+
errorHeader ErrorHeader
50+
51+
// params is set of key/value parameters
52+
params []Param
4453

4554
// timer used to calculate a elapsed time for handler and writing it in a response
4655
timer time.Time
4756
}
4857

4958
// Param is a URL parameter which represents as key and value.
5059
type Param struct {
51-
Key string
52-
Value string
60+
Key string `json:"key,omitempty"`
61+
Value string `json:"value,omitempty"`
5362
}
5463

55-
// Header is used to prepare a JSON header with duration triggered by UserTimer() method
64+
// Header is used to prepare a JSON header with meta data
5665
type Header struct {
57-
Duration time.Duration `json:"duration"`
58-
Took string `json:"took"`
59-
Data interface{} `json:"data"`
66+
Duration time.Duration `json:"duration,omitempty"`
67+
Took string `json:"took,omitempty"`
68+
APIVersion string `json:"apiVersion,omitempty"`
69+
Context string `json:"context,omitempty"`
70+
ID string `json:"id,omitempty"`
71+
Method string `json:"method,omitempty"`
72+
Params interface{} `json:"params,omitempty"`
73+
Data interface{} `json:"data,omitempty"`
74+
Error interface{} `json:"error,omitempty"`
75+
}
76+
77+
// ErrorHeader contains error code, message and array of specified error reports
78+
type ErrorHeader struct {
79+
Code uint16 `json:"code,omitempty"`
80+
Message string `json:"message,omitempty"`
81+
Errors []Error `json:"errors,omitempty"`
82+
}
83+
84+
// Error report format
85+
type Error struct {
86+
Domain string `json:"domain,omitempty"`
87+
Reason string `json:"reason,omitempty"`
88+
Message string `json:"message,omitempty"`
89+
Location string `json:"location,omitempty"`
90+
LocationType string `json:"locationType,omitempty"`
91+
ExtendedHelp string `json:"extendedHelp,omitempty"`
92+
SendReport string `json:"sendReport,omitempty"`
6093
}
6194

6295
// Get returns the first value associated with the given name.
6396
// If there are no values associated with the key, an empty string is returned.
6497
func (c *Control) Get(name string) string {
65-
for idx := range c.Params {
66-
if c.Params[idx].Key == name {
67-
return c.Params[idx].Value
98+
for idx := range c.params {
99+
if c.params[idx].Key == name {
100+
return c.params[idx].Value
68101
}
69102
}
70103

71104
return c.Request.URL.Query().Get(name)
72105
}
73106

74107
// Set adds new parameters which represents as set of key/value.
75-
func (c *Control) Set(params []Param) {
76-
c.Params = append(c.Params, params...)
108+
func (c *Control) Set(params ...Param) *Control {
109+
c.params = append(c.params, params...)
110+
return c
77111
}
78112

79113
// Code assigns http status code, which returns on http request
@@ -85,12 +119,68 @@ func (c *Control) Code(code int) *Control {
85119
}
86120

87121
// CompactJSON change JSON output format (default mode is false)
88-
func (c *Control) CompactJSON(mode bool) {
122+
func (c *Control) CompactJSON(mode bool) *Control {
89123
c.compactJSON = mode
124+
return c
125+
}
126+
127+
// UseMetaData shows meta data in JSON Header
128+
func (c *Control) UseMetaData() *Control {
129+
c.useMetaData = true
130+
return c
131+
}
132+
133+
// APIVersion add API version meta data
134+
func (c *Control) APIVersion(version string) *Control {
135+
c.useMetaData = true
136+
c.header.APIVersion = version
137+
return c
138+
}
139+
140+
// Context add context meta data
141+
func (c *Control) Context(context string) *Control {
142+
c.useMetaData = true
143+
c.header.Context = context
144+
return c
145+
}
146+
147+
// ID add id meta data
148+
func (c *Control) ID(id string) *Control {
149+
c.useMetaData = true
150+
c.header.ID = id
151+
return c
152+
}
153+
154+
// Method add method meta data
155+
func (c *Control) Method(method string) *Control {
156+
c.useMetaData = true
157+
c.header.Method = method
158+
return c
159+
}
160+
161+
// SetParams add params meta data in alternative format
162+
func (c *Control) SetParams(params interface{}) *Control {
163+
c.useMetaData = true
164+
c.header.Params = params
165+
return c
166+
}
167+
168+
func (c *Control) SetError(code uint16, message string) *Control {
169+
c.useMetaData = true
170+
c.errorHeader.Code = code
171+
c.errorHeader.Message = message
172+
return c
173+
}
174+
175+
func (c *Control) AddError(errors ...Error) *Control {
176+
c.useMetaData = true
177+
c.errorHeader.Errors = append(c.errorHeader.Errors, errors...)
178+
return c
90179
}
91180

92181
// UseTimer allow caalculate elapsed time of request handling
93182
func (c *Control) UseTimer() {
183+
c.useMetaData = true
94184
c.timer = time.Now()
95185
}
96186

@@ -106,9 +196,20 @@ func (c *Control) Body(data interface{}) {
106196
c.Writer.Header().Add("Content-type", MIMETEXT)
107197
}
108198
} else {
109-
if !c.timer.IsZero() {
110-
took := time.Now()
111-
data = &Header{Duration: took.Sub(c.timer), Took: took.Sub(c.timer).String(), Data: data}
199+
if c.useMetaData {
200+
c.header.Data = data
201+
if !c.timer.IsZero() {
202+
took := time.Now()
203+
c.header.Duration = took.Sub(c.timer)
204+
c.header.Took = took.Sub(c.timer).String()
205+
}
206+
if c.header.Params == nil && len(c.params) > 0 {
207+
c.header.Params = c.params
208+
}
209+
if c.errorHeader.Code != 0 || c.errorHeader.Message != "" || len(c.errorHeader.Errors) > 0 {
210+
c.header.Error = c.errorHeader
211+
}
212+
data = c.header
112213
}
113214
var err error
114215
if c.compactJSON {

0 commit comments

Comments
 (0)