From 7ca7bd94096ec85503b64b630cc3c0e486648a1c Mon Sep 17 00:00:00 2001 From: Ggicci Date: Sun, 29 Oct 2023 14:31:47 -0400 Subject: [PATCH] fix: decode with default directive only works the first time Fixed #77 --- default.go | 5 ++--- default_test.go | 28 ++++++++++++++++++++++++++++ extractor.go | 7 +++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/default.go b/default.go index 4661c14..6a8bd5e 100644 --- a/default.go +++ b/default.go @@ -12,7 +12,7 @@ func defaultValueSetter(ctx *DirectiveRuntime) error { // Transform: // 1. ctx.Argv -> input values - // 2. ["default"] -> ctx.Argv + // 2. ["default"] -> keys extractor := &extractor{ Form: multipart.Form{ Value: map[string][]string{ @@ -20,6 +20,5 @@ func defaultValueSetter(ctx *DirectiveRuntime) error { }, }, } - ctx.Directive.Argv = []string{"default"} - return extractor.Execute(ctx) + return extractor.Execute(ctx, "default") } diff --git a/default_test.go b/default_test.go index 92e9bfb..072c04a 100644 --- a/default_test.go +++ b/default_test.go @@ -73,3 +73,31 @@ func TestDirectiveDefault_PatchField(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expected, got) } + +// FIX: https://github.com/ggicci/httpin/issues/77 +// Decode parameter struct with default values only works the first time +func TestDirectiveDeafult_Decode_twice(t *testing.T) { + type ThingWithDefaultValues struct { + Id uint `in:"query=id;required"` + Page int `in:"query=page;default=1"` + PerPage int `in:"query=page_size;default=127"` + } + + r, _ := http.NewRequest("GET", "/?id=123", nil) + expected := &ThingWithDefaultValues{ + Id: 123, + Page: 1, + PerPage: 127, + } + + // First decode works as expected + xxx := ThingWithDefaultValues{} + err := Decode(r, &xxx) + assert.NoError(t, err) + assert.Equal(t, expected, &xxx) + + // Second decode generates eror + err = Decode(r, &xxx) + assert.NoError(t, err) + assert.Equal(t, expected, &xxx) +} diff --git a/extractor.go b/extractor.go index 6d06953..ada7e64 100644 --- a/extractor.go +++ b/extractor.go @@ -29,8 +29,11 @@ func newExtractor(r *http.Request) *extractor { } } -func (e *extractor) Execute(ctx *DirectiveRuntime) error { - for _, key := range ctx.Directive.Argv { +func (e *extractor) Execute(ctx *DirectiveRuntime, keys ...string) error { + if len(keys) == 0 { + keys = ctx.Directive.Argv + } + for _, key := range keys { if e.KeyNormalizer != nil { key = e.KeyNormalizer(key) }