diff --git a/pkg/handlers/handlers.go b/pkg/handlers/handlers.go index b225669..1a8f0e8 100644 --- a/pkg/handlers/handlers.go +++ b/pkg/handlers/handlers.go @@ -3,6 +3,7 @@ package handlers import ( "fmt" "net/http" + "net/url" "github.com/labstack/echo/v4" "github.com/mikestefanello/pagoda/pkg/htmx" @@ -30,10 +31,19 @@ func GetHandlers() []Handler { return handlers } -// redirect redirects to a given route name with optional route parameters -func redirect(ctx echo.Context, route string, routeParams ...any) error { - url := ctx.Echo().Reverse(route, routeParams...) +// redirect redirects to a given route by name with optional route parameters +func redirect(ctx echo.Context, routeName string, routeParams ...any) error { + return doRedirect(ctx, ctx.Echo().Reverse(routeName, routeParams...)) +} +// redirectWithQuery redirects to a given route by name with query parameters and optional route parameters +func redirectWithQuery(ctx echo.Context, query url.Values, routeName string, routeParams ...any) error { + dest := fmt.Sprintf("%s?%s", ctx.Echo().Reverse(routeName, routeParams...), query.Encode()) + return doRedirect(ctx, dest) +} + +// doRedirect performs a redirect to a given URL +func doRedirect(ctx echo.Context, url string) error { if htmx.GetRequest(ctx).Boosted { htmx.Response{ Redirect: url, diff --git a/pkg/handlers/handlers_test.go b/pkg/handlers/handlers_test.go index 3ef6408..01f71dc 100644 --- a/pkg/handlers/handlers_test.go +++ b/pkg/handlers/handlers_test.go @@ -3,6 +3,7 @@ package handlers import ( "errors" "net/http" + "net/url" "testing" "github.com/labstack/echo/v4" @@ -27,7 +28,7 @@ func TestRedirect(t *testing.T) { return nil }).Name = "redirect-test" - t.Run("normal", func(t *testing.T) { + t.Run("no query", func(t *testing.T) { ctx, _ := tests.NewContext(c.Web, "/abc") err := redirect(ctx, "redirect-test", "one", "two") require.NoError(t, err) @@ -35,13 +36,36 @@ func TestRedirect(t *testing.T) { assert.Equal(t, http.StatusFound, ctx.Response().Status) }) - t.Run("htmx boosted", func(t *testing.T) { + t.Run("no query htmx", func(t *testing.T) { ctx, _ := tests.NewContext(c.Web, "/abc") ctx.Request().Header.Set(htmx.HeaderBoosted, "true") err := redirect(ctx, "redirect-test", "one", "two") require.NoError(t, err) assert.Equal(t, "/path/one/and/two", ctx.Response().Header().Get(htmx.HeaderRedirect)) }) + + t.Run("query", func(t *testing.T) { + ctx, _ := tests.NewContext(c.Web, "/abc") + q := url.Values{} + q.Add("a", "1") + q.Add("b", "2") + err := redirectWithQuery(ctx, q, "redirect-test", "one", "two") + require.NoError(t, err) + assert.Equal(t, "/path/one/and/two?a=1&b=2", ctx.Response().Header().Get(echo.HeaderLocation)) + assert.Equal(t, http.StatusFound, ctx.Response().Status) + }) + + t.Run("query htmx", func(t *testing.T) { + ctx, _ := tests.NewContext(c.Web, "/abc") + ctx.Request().Header.Set(htmx.HeaderBoosted, "true") + q := url.Values{} + q.Add("a", "1") + q.Add("b", "2") + err := redirectWithQuery(ctx, q, "redirect-test", "one", "two") + require.NoError(t, err) + assert.Equal(t, "/path/one/and/two?a=1&b=2", ctx.Response().Header().Get(htmx.HeaderRedirect)) + assert.Equal(t, http.StatusFound, ctx.Response().Status) + }) } func TestFail(t *testing.T) {