Skip to content

Commit

Permalink
Merge branch 'release/0.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
takama committed Oct 22, 2016
2 parents 539d2db + 619cdaf commit 3b69d03
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 43 deletions.
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ Hello world

- Serve dynamic route with parameter:
```go
package main

import (
"github.com/takama/router"
)

func main() {
r := router.New()
r.GET("/hello/:name", func(c *router.Control) {
Expand All @@ -69,6 +75,12 @@ Hello John

- Checks JSON Content-Type automatically:
```go
package main

import (
"github.com/takama/router"
)

// Data is helper to construct JSON
type Data map[string]interface{}

Expand Down Expand Up @@ -109,6 +121,12 @@ Content-Length: 102

- Use timer to calculate duration of request handling:
```go
package main

import (
"github.com/takama/router"
)

// Data is helper to construct JSON
type Data map[string]interface{}

Expand Down Expand Up @@ -157,6 +175,12 @@ Content-Length: 143

- Custom handler with "Access-Control-Allow" options and compact JSON:
```go
package main

import (
"github.com/takama/router"
)

// Data is helper to construct JSON
type Data map[string]interface{}

Expand Down Expand Up @@ -203,6 +227,59 @@ Content-Length: 28
{"debug":true,"error":false}
```

- Use google json style `https://google.github.io/styleguide/jsoncstyleguide.xml`:
```go
package main

import (
"net/http"

"github.com/takama/router"
)

func main() {
r := router.New()
r.GET("/api/v1/people/:action/:id", func(c *router.Control) {

// Do something

c.Method("people." + c.Get(":action"))
c.SetParams(map[string]string{"userId": c.Get(":id")})
c.SetError(http.StatusNotFound, "UserId not found")
c.AddError(router.Error{Message: "Group or User not found"})
c.Code(http.StatusNotFound).Body(nil)
})
// Listen and serve on 0.0.0.0:8888
r.Listen(":8888")
}
```

- Check it:
```sh
curl -i http://localhost:8888/api/v1/people/get/@me

HTTP/1.1 404 Not Found
Content-Type: application/json
Date: Sat, 22 Oct 2016 14:50:00 GMT
Content-Length: 220

{
"method": "people.get",
"params": {
"userId": "@me"
},
"error": {
"code": 404,
"message": "UserId not found",
"errors": [
{
"message": "Group or User not found"
}
]
}
}
```

## Author

[Igor Dolzhikov](https://github.com/takama)
Expand Down
137 changes: 119 additions & 18 deletions control.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,44 +36,78 @@ type Control struct {
// Code of HTTP status
code int

// CompactJSON propery defines JSON output format (default is not compact)
// compactJSON propery defines JSON output format (default is not compact)
compactJSON bool

// Params is set of parameters
Params []Param
// if used, json header shows meta data
useMetaData bool

// header with metadata
header Header

// errors
errorHeader ErrorHeader

// params is set of key/value parameters
params []Param

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

// Param is a URL parameter which represents as key and value.
type Param struct {
Key string
Value string
Key string `json:"key,omitempty"`
Value string `json:"value,omitempty"`
}

// Header is used to prepare a JSON header with duration triggered by UserTimer() method
// Header is used to prepare a JSON header with meta data
type Header struct {
Duration time.Duration `json:"duration"`
Took string `json:"took"`
Data interface{} `json:"data"`
Duration time.Duration `json:"duration,omitempty"`
Took string `json:"took,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
Context string `json:"context,omitempty"`
ID string `json:"id,omitempty"`
Method string `json:"method,omitempty"`
Params interface{} `json:"params,omitempty"`
Data interface{} `json:"data,omitempty"`
Error interface{} `json:"error,omitempty"`
}

// ErrorHeader contains error code, message and array of specified error reports
type ErrorHeader struct {
Code uint16 `json:"code,omitempty"`
Message string `json:"message,omitempty"`
Errors []Error `json:"errors,omitempty"`
}

// Error report format
type Error struct {
Domain string `json:"domain,omitempty"`
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"`
Location string `json:"location,omitempty"`
LocationType string `json:"locationType,omitempty"`
ExtendedHelp string `json:"extendedHelp,omitempty"`
SendReport string `json:"sendReport,omitempty"`
}

// Get returns the first value associated with the given name.
// If there are no values associated with the key, an empty string is returned.
func (c *Control) Get(name string) string {
for idx := range c.Params {
if c.Params[idx].Key == name {
return c.Params[idx].Value
for idx := range c.params {
if c.params[idx].Key == name {
return c.params[idx].Value
}
}

return c.Request.URL.Query().Get(name)
}

// Set adds new parameters which represents as set of key/value.
func (c *Control) Set(params []Param) {
c.Params = append(c.Params, params...)
func (c *Control) Set(params ...Param) *Control {
c.params = append(c.params, params...)
return c
}

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

// CompactJSON change JSON output format (default mode is false)
func (c *Control) CompactJSON(mode bool) {
func (c *Control) CompactJSON(mode bool) *Control {
c.compactJSON = mode
return c
}

// UseMetaData shows meta data in JSON Header
func (c *Control) UseMetaData() *Control {
c.useMetaData = true
return c
}

// APIVersion add API version meta data
func (c *Control) APIVersion(version string) *Control {
c.useMetaData = true
c.header.APIVersion = version
return c
}

// Context add context meta data
func (c *Control) Context(context string) *Control {
c.useMetaData = true
c.header.Context = context
return c
}

// ID add id meta data
func (c *Control) ID(id string) *Control {
c.useMetaData = true
c.header.ID = id
return c
}

// Method add method meta data
func (c *Control) Method(method string) *Control {
c.useMetaData = true
c.header.Method = method
return c
}

// SetParams add params meta data in alternative format
func (c *Control) SetParams(params interface{}) *Control {
c.useMetaData = true
c.header.Params = params
return c
}

func (c *Control) SetError(code uint16, message string) *Control {
c.useMetaData = true
c.errorHeader.Code = code
c.errorHeader.Message = message
return c
}

func (c *Control) AddError(errors ...Error) *Control {
c.useMetaData = true
c.errorHeader.Errors = append(c.errorHeader.Errors, errors...)
return c
}

// UseTimer allow caalculate elapsed time of request handling
func (c *Control) UseTimer() {
c.useMetaData = true
c.timer = time.Now()
}

Expand All @@ -106,9 +196,20 @@ func (c *Control) Body(data interface{}) {
c.Writer.Header().Add("Content-type", MIMETEXT)
}
} else {
if !c.timer.IsZero() {
took := time.Now()
data = &Header{Duration: took.Sub(c.timer), Took: took.Sub(c.timer).String(), Data: data}
if c.useMetaData {
c.header.Data = data
if !c.timer.IsZero() {
took := time.Now()
c.header.Duration = took.Sub(c.timer)
c.header.Took = took.Sub(c.timer).String()
}
if c.header.Params == nil && len(c.params) > 0 {
c.header.Params = c.params
}
if c.errorHeader.Code != 0 || c.errorHeader.Message != "" || len(c.errorHeader.Errors) > 0 {
c.header.Error = c.errorHeader
}
data = c.header
}
var err error
if c.compactJSON {
Expand Down
Loading

0 comments on commit 3b69d03

Please sign in to comment.