Skip to content

Commit

Permalink
fix(api): use ajg/form decoder only for Parameters field
Browse files Browse the repository at this point in the history
  • Loading branch information
nettoclaudio committed Jun 17, 2020
1 parent c92d1ac commit 0118126
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 139 deletions.
30 changes: 0 additions & 30 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@ package api
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"

"github.com/ajg/form"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/tsuru/rpaas-operator/config"
Expand Down Expand Up @@ -161,7 +158,6 @@ func errorMiddleware(next echo.HandlerFunc) echo.HandlerFunc {

func newEcho() *echo.Echo {
e := echo.New()
e.Binder = new(requestBinder)
e.HideBanner = true

e.Use(middleware.Recover())
Expand Down Expand Up @@ -224,29 +220,3 @@ func newEcho() *echo.Echo {

return e
}

type requestBinder struct{}

func (b *requestBinder) Bind(i interface{}, c echo.Context) error {
req := c.Request()

ctype := req.Header.Get(echo.HeaderContentType)
if !strings.HasPrefix(ctype, echo.MIMEApplicationForm) {
c.Response().Header().Set("Accept", echo.MIMEApplicationForm)
return echo.ErrUnsupportedMediaType
}

if err := newDecoder(req.Body).Decode(i); err != nil {
return fmt.Errorf("cannot decode the parameters: %w", err)
}
defer req.Body.Close()

return nil
}

func newDecoder(r io.Reader) *form.Decoder {
decoder := form.NewDecoder(r)
decoder.IgnoreCase(true)
decoder.IgnoreUnknownKeys(true)
return decoder
}
96 changes: 0 additions & 96 deletions api/api_test.go

This file was deleted.

42 changes: 40 additions & 2 deletions api/service_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@
package api

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"

"github.com/ajg/form"
"github.com/labstack/echo/v4"
"github.com/tsuru/rpaas-operator/internal/pkg/rpaas"
)

func serviceCreate(c echo.Context) error {
var args rpaas.CreateArgs
args := rpaas.CreateArgs{
// NOTE: using a different decoder for Parameters since the `r.PostForm()`
// method does not understand the format used by github.com/ajf.form.
Parameters: decodeFormParameters(c.Request()),
}
if err := c.Bind(&args); err != nil {
return err
}
Expand Down Expand Up @@ -49,7 +57,11 @@ func serviceDelete(c echo.Context) error {
}

func serviceUpdate(c echo.Context) error {
var args rpaas.UpdateInstanceArgs
args := rpaas.UpdateInstanceArgs{
// NOTE: using a different decoder for Parameters since the `r.PostForm()`
// method does not understand the format used by github.com/ajf.form.
Parameters: decodeFormParameters(c.Request()),
}
if err := c.Bind(&args); err != nil {
return err
}
Expand Down Expand Up @@ -191,3 +203,29 @@ func serviceStatus(c echo.Context) error {

return c.NoContent(http.StatusNoContent)
}

func decodeFormParameters(r *http.Request) map[string]interface{} {
if r == nil {
return nil
}

body := r.Body
defer body.Close()

var buffer bytes.Buffer
reader := io.TeeReader(body, &buffer)

var obj struct {
Parameters map[string]interface{} `form:"parameters"`
}
newFormDecoder(reader).Decode(&obj)
r.Body = ioutil.NopCloser(&buffer)
return obj.Parameters
}

func newFormDecoder(r io.Reader) *form.Decoder {
decoder := form.NewDecoder(r)
decoder.IgnoreCase(true)
decoder.IgnoreUnknownKeys(true)
return decoder
}
15 changes: 4 additions & 11 deletions api/service_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func Test_serviceCreate(t *testing.T) {
},
{
name: "passing all create parameters on body",
requestBody: "name=my-instance&description=some%20description&plan=my-plan&team=my-team&tags.0=tsuru&tags.1=rpaas&parameters.flavors.0=orange&parameters.flavors.1=strawberry&parameters.flavors.2=blueberry",
requestBody: "name=my-instance&description=some%20description&plan=my-plan&team=my-team&tags=tsuru&tags=rpaas&parameters.flavors=orange,strawberry,blueberry",
expectedCode: http.StatusCreated,
manager: &fake.RpaasManager{
FakeCreateInstance: func(args rpaas.CreateArgs) error {
Expand All @@ -55,11 +55,7 @@ func Test_serviceCreate(t *testing.T) {
Team: "my-team",
Tags: []string{"tsuru", "rpaas"},
Parameters: map[string]interface{}{
"flavors": map[string]interface{}{
"0": "orange",
"1": "strawberry",
"2": "blueberry",
},
"flavors": "orange,strawberry,blueberry",
},
}
assert.Equal(t, expected, args)
Expand Down Expand Up @@ -152,7 +148,7 @@ func Test_serviceUpdate(t *testing.T) {
{
name: "passing all update parameters on body",
instance: "other-instance",
requestBody: "description=some%20description&plan=huge&team=team-one&tags.0=tag1&tags.1=tag2&parameters.flavors.0=orange&parameters.flavors.1=mango",
requestBody: "description=some%20description&plan=huge&team=team-one&tags=tag1&tags=tag2&parameters.flavors=orange,mango",
expectedCode: http.StatusOK,
manager: &fake.RpaasManager{
FakeUpdateInstance: func(instanceName string, args rpaas.UpdateInstanceArgs) error {
Expand All @@ -163,10 +159,7 @@ func Test_serviceUpdate(t *testing.T) {
Tags: []string{"tag1", "tag2"},
Team: "team-one",
Parameters: map[string]interface{}{
"flavors": map[string]interface{}{
"0": "orange",
"1": "mango",
},
"flavors": "orange,mango",
},
}, args)
assert.Equal(t, []string{"orange", "mango"}, args.Flavors())
Expand Down
6 changes: 6 additions & 0 deletions internal/pkg/rpaas/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ func getFlavors(params map[string]interface{}, tags []string) (flavors []string)
return legacyGetFlavors(tags)
}

flavorsString, ok := p.(string)
if ok {
flavors = strings.Split(flavorsString, ",")
return
}

flavorsParams, ok := p.(map[string]interface{})
if !ok {
return
Expand Down

0 comments on commit 0118126

Please sign in to comment.