From 791e2cca1b81af85078324f4e20d701e66594ea3 Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Wed, 27 Sep 2023 22:44:32 +0700 Subject: [PATCH] fix build part handle query from base (#111) --- context_test.go | 2 +- path.go | 18 +++++++++++------- path_test.go | 13 ++++++++----- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/context_test.go b/context_test.go index c6cb1b8..79baeba 100644 --- a/context_test.go +++ b/context_test.go @@ -307,7 +307,7 @@ func TestContext(t *testing.T) { assert.NoError(t, ctx.Redirect("https://google.com")) assert.Equal(t, w.Code, http.StatusFound) - assert.Equal(t, w.Header().Get("Location"), "https://google.com") + assert.Equal(t, w.Header().Get("Location"), "https://google.com/") }) t.Run("Redirect to internal url path", func(t *testing.T) { diff --git a/path.go b/path.go index 600e920..c06efaa 100644 --- a/path.go +++ b/path.go @@ -50,8 +50,14 @@ func mergeValueWithMapAny(s url.Values, m map[string]any) { } func buildPath(base string, params ...any) string { + baseURL, err := url.Parse(base) + if err != nil { + panicf("parse url error; %v", err) + } + xs := make([]string, 0, len(params)) ps := make(url.Values) + mergeValues(ps, baseURL.Query()) for _, p := range params { switch v := p.(type) { case url.Values: @@ -66,12 +72,10 @@ func buildPath(base string, params ...any) string { xs = append(xs, strings.TrimPrefix(fmt.Sprint(p), "/")) } } - if base == "" || (len(xs) > 0 && !strings.HasSuffix(base, "/")) { - base += "/" - } - qs := ps.Encode() - if len(qs) > 0 { - qs = "?" + qs + if baseURL.Path == "" || (len(xs) > 0 && !strings.HasSuffix(baseURL.Path, "/")) { + baseURL.Path += "/" } - return base + path.Join(xs...) + qs + baseURL.Path += path.Join(xs...) + baseURL.RawQuery = ps.Encode() + return baseURL.String() } diff --git a/path_test.go b/path_test.go index 93e48fd..de88398 100644 --- a/path_test.go +++ b/path_test.go @@ -18,16 +18,17 @@ func TestBuildPath(t *testing.T) { {"/", "/"}, {"/p", "/p"}, {"/p/123", "/p/123"}, - {"https://google.com", "https://google.com"}, + {"https://google.com", "https://google.com/"}, {"https://google.com/test", "https://google.com/test"}, + {"https://google.com/test/", "https://google.com/test/"}, {"https://google.com/test?p=1", "https://google.com/test?p=1"}, {"http://google.com/test?p=1", "http://google.com/test?p=1"}, - {"//a?p=1", "//a?p=1"}, + {"//a?p=1", "//a/?p=1"}, {"app:///a?p=1", "app:///a?p=1"}, } for _, c := range cases { - assert.Equal(t, buildPath(c.Input), c.Output) + assert.Equal(t, c.Output, buildPath(c.Input)) } } @@ -43,6 +44,7 @@ func TestBuildPathParams(t *testing.T) { {"/", []any{"/"}, "/"}, {"/a", []any{}, "/a"}, {"/a", []any{"/b"}, "/a/b"}, + {"/a?x=1", []any{"/b"}, "/a/b?x=1"}, {"/a/", []any{"/b/", "/c/"}, "/a/b/c"}, {"/a", []any{url.Values{"id": []string{"10"}}}, "/a?id=10"}, {"/a", []any{"/b", url.Values{"id": []string{"10"}}}, "/a/b?id=10"}, @@ -50,10 +52,11 @@ func TestBuildPathParams(t *testing.T) { {"/a", []any{"/b/", map[string]string{"id": "10"}}, "/a/b?id=10"}, {"/a", []any{"/b/", map[string]any{"id": 10}}, "/a/b?id=10"}, {"/a", []any{"/b", &Param{Name: "id", Value: 3456}}, "/a/b?id=3456"}, + {"/a?x=1", []any{"/b", &Param{Name: "id", Value: 3456}}, "/a/b?id=3456&x=1"}, } for _, c := range cases { - assert.Equal(t, buildPath(c.Base, c.Params...), c.Output) + assert.Equal(t, c.Output, buildPath(c.Base, c.Params...)) } } @@ -79,6 +82,6 @@ func TestSafeRedirectPath(t *testing.T) { } for _, c := range cases { - assert.Equal(t, SafeRedirectPath(c.Input), c.Output) + assert.Equal(t, c.Output, SafeRedirectPath(c.Input)) } }