Skip to content

Commit

Permalink
New adapter for the echo framework
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwdata authored and sharpner committed Oct 30, 2017
1 parent be68f56 commit e7b6938
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ install:
# optional dependencies
- go get -u github.com/gin-gonic/gin
- go get -u github.com/gorilla/mux
- go get -u github.com/labstack/echo/...

script:
- ginkgo -r -cover --randomizeAllSpecs --randomizeSuites --failOnPending --trace --race --progress
- ginkgo -tags=gorillamux -r --randomizeSuites --failOnPending --trace --race
- ginkgo -tags=gingonic -r --randomizeSuites --failOnPending --trace --race
- ginkgo -tags=echo -r --randomizeSuites --failOnPending --trace --race
- rm examples/examples.coverprofile
- bash scripts/fmtpolice
- gover
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ Get the according adapter using:

```go get -tags=gingonic github.com/manyminds/api2go```

Currently the supported tags are: `gingonic` or `gorillamux`.
Currently the supported tags are: `gingonic`,`gorillamux`, or `echo`.

After that you can bootstrap api2go the following way:
```go
Expand Down
30 changes: 30 additions & 0 deletions echo_router_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// +build echo,!gingonic,!gorillamux

package api2go

import (
"log"
"net/http"

"github.com/labstack/echo"
"github.com/manyminds/api2go/routing"
)

func customHTTPErrorHandler(err error, c echo.Context) {
if he, ok := err.(*echo.HTTPError); ok {
if he == echo.ErrMethodNotAllowed {
handleError(NewHTTPError(he, "Method Not Allowed", http.StatusMethodNotAllowed), c.Response(), c.Request(), defaultContentTypHeader)
}
}
}

func newTestRouter() routing.Routeable {
e := echo.New()
// not found handler, this needs to be fixed as well: see: https://github.com/manyminds/api2go/issues/301
e.HTTPErrorHandler = customHTTPErrorHandler
return routing.Echo(e)
}

func init() {
log.Println("Testing with echo router")
}
2 changes: 1 addition & 1 deletion gingonic_router_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build gingonic,!gorillamux
// +build gingonic,!gorillamux,!echo

package api2go

Expand Down
2 changes: 1 addition & 1 deletion gorillamux_router_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !gingonic,gorillamux
// +build !gingonic,!echo,gorillamux

package api2go

Expand Down
2 changes: 1 addition & 1 deletion httprouter_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !gingonic,!gorillamux
// +build !gingonic,!gorillamux,!echo

package api2go

Expand Down
37 changes: 37 additions & 0 deletions routing/echo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// +build echo,!gorillamux,!gingonic

package routing

import (
"net/http"

"github.com/labstack/echo"
)

type echoRouter struct {
echo *echo.Echo
}

func (e echoRouter) Handler() http.Handler {
return e.echo
}

func (e echoRouter) Handle(protocol, route string, handler HandlerFunc) {
echoHandlerFunc := func(c echo.Context) error {
params := map[string]string{}

for i, p := range c.ParamNames() {
params[p] = c.ParamValues()[i]
}

handler(c.Response(), c.Request(), params)

return nil
}
e.echo.Add(protocol, route, echoHandlerFunc)
}

// Echo created a new api2go router to use with the echo framework
func Echo(e *echo.Echo) Routeable {
return &echoRouter{echo: e}
}
146 changes: 146 additions & 0 deletions routing/echo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// +build echo,!gingonic,!gorillamux

package routing_test

import (
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"strings"

"github.com/labstack/echo"
"github.com/manyminds/api2go"
"github.com/manyminds/api2go/examples/model"
"github.com/manyminds/api2go/examples/resource"
"github.com/manyminds/api2go/examples/storage"
"github.com/manyminds/api2go/routing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("api2go with echo router adapter", func() {
var (
router routing.Routeable
e *echo.Echo
api *api2go.API
rec *httptest.ResponseRecorder
)

BeforeSuite(func() {
e = echo.New()
router = routing.Echo(e)
api = api2go.NewAPIWithRouting(
"api",
api2go.NewStaticResolver("/"),
router,
)

userStorage := storage.NewUserStorage()
chocStorage := storage.NewChocolateStorage()
api.AddResource(model.User{}, resource.UserResource{ChocStorage: chocStorage, UserStorage: userStorage})
api.AddResource(model.Chocolate{}, resource.ChocolateResource{ChocStorage: chocStorage, UserStorage: userStorage})
})

BeforeEach(func() {
log.SetOutput(ioutil.Discard)
rec = httptest.NewRecorder()
})

Context("CRUD Tests", func() {
It("will create a new user", func() {
reqBody := strings.NewReader(`{"data": {"attributes": {"user-name": "Sansa Stark"}, "id": "1", "type": "users"}}`)
req, err := http.NewRequest("POST", "/api/users", reqBody)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusCreated))
})

It("will find her", func() {
expectedUser := `
{
"data":
{
"attributes":{
"user-name":"Sansa Stark"
},
"id":"1",
"relationships":{
"sweets":{
"data":[],"links":{"related":"/api/users/1/sweets","self":"/api/users/1/relationships/sweets"}
}
},"type":"users"
},
"meta":
{
"author":"The api2go examples crew","license":"wtfpl","license-url":"http://www.wtfpl.net"
}
}`

req, err := http.NewRequest("GET", "/api/users/1", nil)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusOK))
Expect(string(rec.Body.Bytes())).To(MatchJSON((expectedUser)))
})

It("can call handle", func() {
handler := api.Handler()
_, ok := handler.(http.Handler)
Expect(ok).To(Equal(true))
})

It("update the username", func() {
reqBody := strings.NewReader(`{"data": {"id": "1", "attributes": {"user-name": "Alayne"}, "type" : "users"}}`)
req, err := http.NewRequest("PATCH", "/api/users/1", reqBody)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusNoContent))
})

It("will find her once again", func() {
expectedUser := `
{
"data":
{
"attributes":{
"user-name":"Alayne"
},
"id":"1",
"relationships":{
"sweets":{
"data":[],"links":{"related":"/api/users/1/sweets","self":"/api/users/1/relationships/sweets"}
}
},"type":"users"
},
"meta":
{
"author":"The api2go examples crew","license":"wtfpl","license-url":"http://www.wtfpl.net"
}
}`

req, err := http.NewRequest("GET", "/api/users/1", nil)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusOK))
Expect(string(rec.Body.Bytes())).To(MatchJSON((expectedUser)))
})

It("will delete her", func() {
req, err := http.NewRequest("DELETE", "/api/users/1", nil)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusNoContent))
})

It("won't find her anymore", func() {
expected := `{"errors":[{"status":"404","title":"http error (404) User for id 1 not found and 0 more errors, User for id 1 not found"}]}`
req, err := http.NewRequest("GET", "/api/users/1", nil)
Expect(err).To(BeNil())
e.ServeHTTP(rec, req)
Expect(rec.Code).To(Equal(http.StatusNotFound))
Expect(string(rec.Body.Bytes())).To(MatchJSON(expected))
})
})
})
2 changes: 1 addition & 1 deletion routing/gingonic.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build gingonic,!gorillamux
// +build gingonic,!gorillamux,!echo

package routing

Expand Down
2 changes: 1 addition & 1 deletion routing/gingonic_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build gingonic,!gorillamux
// +build gingonic,!gorillamux,!echo

package routing_test

Expand Down
2 changes: 1 addition & 1 deletion routing/gorillamux.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build gorillamux,!gingonic
// +build gorillamux,!gingonic,!echo

package routing

Expand Down
2 changes: 1 addition & 1 deletion routing/gorillamux_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build gorillamux,!gingonic
// +build gorillamux,!gingonic,!echo

package routing_test

Expand Down

0 comments on commit e7b6938

Please sign in to comment.