From 3f15064decad4e3f95aed5261d1129eb66cca99a Mon Sep 17 00:00:00 2001 From: Dmitry Kolesnikov Date: Fri, 18 Aug 2023 20:06:20 +0300 Subject: [PATCH] bind interface{ Arrow() Arrow } --- http/types.go | 16 ++++++++++++++++ http/types_test.go | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/http/types.go b/http/types.go index 01d0244..28cdb17 100644 --- a/http/types.go +++ b/http/types.go @@ -49,6 +49,22 @@ func Join(arrows ...Arrow) Arrow { } } +// Bind composes HTTP arrows to high-order function +// In contrast with Join, input is arrow builders +// (a ⟼ b, b ⟼ c, c ⟼ d) ⤇ a ⟼ d +func Bind(arrows ...interface{ Arrow() Arrow }) Arrow { + return func(cat *Context) error { + for _, arrow := range arrows { + f := arrow.Arrow() + if err := f(cat); err != nil { + return err + } + } + + return nil + } +} + // GET composes HTTP arrows to high-order function for HTTP GET request // (a ⟼ b, b ⟼ c, c ⟼ d) ⤇ a ⟼ d func GET(arrows ...Arrow) Arrow { return method(http.MethodGet, arrows) } diff --git a/http/types_test.go b/http/types_test.go index d3ce858..0d13067 100644 --- a/http/types_test.go +++ b/http/types_test.go @@ -67,8 +67,13 @@ func TestJoin(t *testing.T) { defer ts.Close() req := µ.GET( - ø.URI("%s/ok", ø.Authority(ts.URL)), + ø.URI("%s/opts", ø.Authority(ts.URL)), + µ.Join( + ø.Param("a", "1"), + ø.Param("b", "2"), + ), ƒ.Code(µ.StatusOK), + ƒ.Match(`{"opts": "a=1&b=2"}`), ) cat := µ.New() err := cat.IO(context.Background(), req) @@ -100,6 +105,31 @@ func TestJoinCats(t *testing.T) { ) } +type opt struct{ key, val string } + +func (opt opt) Arrow() µ.Arrow { return ø.Param(opt.key, opt.val) } + +func TestBind(t *testing.T) { + ts := mock() + defer ts.Close() + + req := µ.GET( + ø.URI("%s/opts", ø.Authority(ts.URL)), + µ.Bind( + opt{"a", "1"}, + opt{"b", "2"}, + ), + ƒ.Code(µ.StatusOK), + ƒ.Match(`{"opts": "a=1&b=2"}`), + ) + cat := µ.New() + err := cat.IO(context.Background(), req) + + it.Then(t).Should( + it.Nil(err), + ) +} + func TestIOWithContext(t *testing.T) { ts := mock() defer ts.Close() @@ -189,6 +219,9 @@ func mock() *httptest.Server { w.Write([]byte("site=example.com")) case r.URL.Path == "/ok": w.WriteHeader(http.StatusOK) + case r.URL.Path == "/opts": + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(`{"opts": "` + r.URL.RawQuery + `"}`)) default: w.WriteHeader(http.StatusBadRequest) }