Skip to content

Commit

Permalink
Merge pull request #49 from krakend/client_errors
Browse files Browse the repository at this point in the history
the table getter supports client errors from lura
  • Loading branch information
kpacha committed Sep 19, 2024
2 parents ee5978e + e02dc60 commit 3a2f876
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 29 deletions.
7 changes: 3 additions & 4 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package lua

import (
"io/ioutil"
"os"
"testing"

Expand Down Expand Up @@ -30,7 +29,7 @@ func TestParse(t *testing.T) {
t.Errorf("unexpected error: %v", err)
return
}
b, _ := ioutil.ReadFile(source)
b, _ := os.ReadFile(source)
if src, ok := cfg.Get(source); !ok || src != string(b) {
t.Errorf("wrong content %s", string(b))
}
Expand All @@ -46,7 +45,7 @@ func TestParse(t *testing.T) {
}

func TestParse_live(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "test_parse_live")
tmpfile, err := os.CreateTemp("", "test_parse_live")
if err != nil {
t.Error(err)
return
Expand Down Expand Up @@ -85,7 +84,7 @@ func TestParse_live(t *testing.T) {
t.Errorf("wrong content %s", src)
}

if err := ioutil.WriteFile(source, []byte(finalContent), 0644); err != nil {
if err := os.WriteFile(source, []byte(finalContent), 0644); err != nil {
t.Error(err)
return
}
Expand Down
133 changes: 128 additions & 5 deletions proxy/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/luraproject/lura/v2/encoding"
"github.com/luraproject/lura/v2/logging"
"github.com/luraproject/lura/v2/proxy"
"github.com/luraproject/lura/v2/transport/http/client"
)

func TestProxyFactory_error(t *testing.T) {
Expand Down Expand Up @@ -219,7 +220,7 @@ func TestProxyFactory(t *testing.T) {
}

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(ctx context.Context, req *proxy.Request) (*proxy.Response, error) {
return func(_ context.Context, req *proxy.Request) (*proxy.Response, error) {
if req.Method != "POST" {
t.Errorf("unexpected method %s", req.Method)
}
Expand Down Expand Up @@ -415,7 +416,7 @@ func Test_Issue7(t *testing.T) {
json.Unmarshal([]byte(response), &r)

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(ctx context.Context, req *proxy.Request) (*proxy.Response, error) {
return func(_ context.Context, _ *proxy.Request) (*proxy.Response, error) {
return &proxy.Response{
Data: r,
Metadata: proxy.Metadata{
Expand Down Expand Up @@ -487,7 +488,7 @@ func Test_jsonNumber(t *testing.T) {
encoding.JSONDecoder(strings.NewReader(response), &r)

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(ctx context.Context, req *proxy.Request) (*proxy.Response, error) {
return func(_ context.Context, _ *proxy.Request) (*proxy.Response, error) {
return &proxy.Response{
Data: r,
Metadata: proxy.Metadata{
Expand Down Expand Up @@ -563,7 +564,7 @@ func Test_keyValConverter(t *testing.T) {
}

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(ctx context.Context, req *proxy.Request) (*proxy.Response, error) {
return func(_ context.Context, _ *proxy.Request) (*proxy.Response, error) {
return &proxy.Response{
Data: r,
Metadata: proxy.Metadata{
Expand Down Expand Up @@ -643,7 +644,7 @@ func Test_listGrowsWhenUpperIndexOutOfBound(t *testing.T) {
r := map[string]interface{}{}

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(ctx context.Context, req *proxy.Request) (*proxy.Response, error) {
return func(_ context.Context, _ *proxy.Request) (*proxy.Response, error) {
return &proxy.Response{
Data: r,
Metadata: proxy.Metadata{
Expand Down Expand Up @@ -713,3 +714,125 @@ responseData:set("grow_list", growingList)
return
}
}

func Test_tableGetSupportsClientErrors(t *testing.T) {
errA := client.HTTPResponseError{
Code: 418,
Msg: "I'm a teapot",
Enc: "text/plain",
}
errB := client.NamedHTTPResponseError{
HTTPResponseError: client.HTTPResponseError{
Code: 481,
Msg: "I'm not a teapot",
Enc: "text/plain",
},
}

dummyProxyFactory := proxy.FactoryFunc(func(_ *config.EndpointConfig) (proxy.Proxy, error) {
return func(_ context.Context, _ *proxy.Request) (*proxy.Response, error) {
return &proxy.Response{
Data: map[string]interface{}{
"error_backend_alias_a": errA,
"error_backend_alias_b": errB,
},
Metadata: proxy.Metadata{
Headers: map[string][]string{},
},
}, nil
}, nil
})

prxy, err := ProxyFactory(logging.NoOp, dummyProxyFactory).New(&config.EndpointConfig{
Endpoint: "/",
ExtraConfig: config.ExtraConfig{
ProxyNamespace: map[string]interface{}{
"post": `
local resp = response.load()
local responseData = resp:data()
local errorA = responseData:get('error_backend_alias_a')
responseData:set("code_a", errorA:get('http_status_code'))
responseData:set("body_a", errorA:get('http_body'))
responseData:set("encoding_a", errorA:get('http_body_encoding'))
local errorB = responseData:get('error_backend_alias_b')
responseData:set("code_b", errorB:get('http_status_code'))
responseData:set("body_b", errorB:get('http_body'))
responseData:set("encoding_b", errorB:get('http_body_encoding'))
responseData:set("name_b", errorB:get('name'))
`,
},
},
})

if err != nil {
t.Error(err)
}

URL, _ := url.Parse("https://some.host.tld/path/to/resource?and=querystring")

resp, err := prxy(context.Background(), &proxy.Request{
Method: "GET",
Path: "/some-path",
Params: map[string]string{"Id": "42"},
Headers: map[string][]string{},
URL: URL,
Body: io.NopCloser(strings.NewReader("initial req content")),
})
if err != nil {
t.Error(err)
}

bodyA, ok := resp.Data["body_a"].(string)
if !ok {
t.Errorf("cannot get 'body_a' %#v", resp.Data)
return
}
if bodyA != errA.Msg {
t.Errorf("unexpected body a. have %s, want %s", bodyA, errA.Msg)
}

bodyB, ok := resp.Data["body_b"].(string)
if !ok {
t.Errorf("cannot get 'body_b' %#v", resp.Data)
return
}
if bodyB != errB.Msg {
t.Errorf("unexpected body b. have %s, want %s", bodyB, errB.Msg)
}

codeA, ok := resp.Data["code_a"].(float64)
if !ok {
t.Errorf("cannot get 'code_a' %#v", resp.Data)
return
}
if int(codeA) != errA.Code {
t.Errorf("unexpected code a. have %d, want %d", int(codeA), errA.Code)
}

codeB, ok := resp.Data["code_b"].(float64)
if !ok {
t.Errorf("cannot get 'code_b' %#v", resp.Data)
return
}
if int(codeB) != errB.Code {
t.Errorf("unexpected code b. have %d, want %d", int(codeB), errB.Code)
}

encA, ok := resp.Data["encoding_a"].(string)
if !ok {
t.Errorf("cannot get 'encoding_a' %#v", resp.Data)
return
}
if encA != errA.Enc {
t.Errorf("unexpected encoding a. have %s, want %s", encA, errA.Enc)
}

encB, ok := resp.Data["encoding_b"].(string)
if !ok {
t.Errorf("cannot get 'encoding_b' %#v", resp.Data)
return
}
if encB != errB.Enc {
t.Errorf("unexpected encoding b. have %s, want %s", encB, errB.Enc)
}
}
31 changes: 15 additions & 16 deletions proxy/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/krakendio/binder"
"github.com/luraproject/lura/v2/proxy"
"github.com/luraproject/lura/v2/transport/http/client"
lua "github.com/yuin/gopher-lua"
)

Expand Down Expand Up @@ -215,6 +216,12 @@ func tableGet(c *binder.Context) error {
c.Push().Data(&luaList{data: t}, "luaList")
case map[string]interface{}:
c.Push().Data(&luaTable{data: t}, "luaTable")
case client.HTTPResponseError:
c.Push().Data(&luaTable{data: clientErrorToMap(t)}, "luaTable")
case client.NamedHTTPResponseError:
d := clientErrorToMap(t.HTTPResponseError)
d["name"] = t.Name()
c.Push().Data(&luaTable{data: d}, "luaTable")
default:
return fmt.Errorf("unknown type (%T) %v", t, t)
}
Expand Down Expand Up @@ -388,26 +395,10 @@ type luaTable struct {
data map[string]interface{}
}

func (l *luaTable) get(k string) interface{} {
return l.data[k]
}

func (l *luaTable) set(k string, v interface{}) {
l.data[k] = v
}

type luaList struct {
data []interface{}
}

func (l *luaList) get(k int) interface{} {
return l.data[k]
}

func (l *luaList) set(k int, v interface{}) {
l.data[k] = v
}

func parseToTable(k, v lua.LValue, acc map[string]interface{}) {

switch v.Type() {
Expand Down Expand Up @@ -442,3 +433,11 @@ func parseToTable(k, v lua.LValue, acc map[string]interface{}) {
acc[k.String()] = res
}
}

func clientErrorToMap(err client.HTTPResponseError) map[string]interface{} {
return map[string]interface{}{
"http_status_code": err.StatusCode(),
"http_body": err.Error(),
"http_body_encoding": err.Encoding(),
}
}
4 changes: 2 additions & 2 deletions router/gin/lua_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gin

import (
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -58,7 +58,7 @@ func TestHandlerFactory(t *testing.T) {
if e := c.Query("extra"); e != "foo" {
t.Errorf("unexpected querystring extra: '%s'", e)
}
b, err := ioutil.ReadAll(c.Request.Body)
b, err := io.ReadAll(c.Request.Body)
if err != nil {
t.Error(err)
return
Expand Down
4 changes: 2 additions & 2 deletions router/mux/lua_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mux

import (
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -52,7 +52,7 @@ func TestHandlerFactory(t *testing.T) {
// if id := c.Param("id"); id != "42" {
// t.Errorf("unexpected param id: %s", id)
// }
b, err := ioutil.ReadAll(r.Body)
b, err := io.ReadAll(r.Body)
if err != nil {
t.Error(err)
return
Expand Down

0 comments on commit 3a2f876

Please sign in to comment.