Skip to content

Commit 7afeea8

Browse files
mromaszewiczclaude
andauthored
Add missing required parameter detection (#135)
Closes: #134 The exploded form path bound struct-typed query params (e.g. types.Date, time.Time) via bindParamsToExplodedObject and returned nil when no fields were present, dropping the required check that the slice and primitive cases already perform. A missing required date param therefore passed silently instead of returning a RequiredParameterError. Honor required in the reflect.Struct case of both BindQueryParameterWithOptions and BindRawQueryParameter, and add regression tests for the absent-required case. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2755f15 commit 7afeea8

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

bindparam.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,14 @@ func BindQueryParameterWithOptions(style string, explode bool, required bool, pa
475475
var fieldsPresent bool
476476
fieldsPresent, err = bindParamsToExplodedObject(paramName, queryParams, output)
477477
// If no fields were set, and there is no error, we will not fall
478-
// through to assign the destination.
478+
// through to assign the destination. An absent required
479+
// parameter is an error, matching the slice and primitive cases
480+
// above; this also covers scalar struct types such as
481+
// types.Date and time.Time.
479482
if !fieldsPresent {
483+
if required {
484+
return &RequiredParameterError{ParamName: paramName}
485+
}
480486
return nil
481487
}
482488
default:
@@ -707,7 +713,13 @@ func BindRawQueryParameter(style string, explode bool, required bool, paramName
707713
case reflect.Struct:
708714
var fieldsPresent bool
709715
fieldsPresent, err = bindParamsToExplodedObject(paramName, queryParams, output)
716+
// An absent required parameter is an error, matching the slice
717+
// and primitive cases above; this also covers scalar struct
718+
// types such as types.Date and time.Time.
710719
if !fieldsPresent {
720+
if required {
721+
return &RequiredParameterError{ParamName: paramName}
722+
}
711723
return nil
712724
}
713725
default:

bindparam_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,26 @@ func TestBindQueryParameter(t *testing.T) {
544544
assert.Nil(t, date)
545545
})
546546

547+
// Regression test for https://github.com/oapi-codegen/runtime/issues/134:
548+
// an absent *required* date (a struct-typed param) must report a
549+
// RequiredParameterError, not pass silently. The exploded form path
550+
// previously returned nil here, dropping the required check.
551+
t.Run("date_form_explode_required_missing", func(t *testing.T) {
552+
var date types.Date
553+
queryParams := url.Values{}
554+
err := BindQueryParameter("form", true, true, "date", queryParams, &date)
555+
var requiredErr *RequiredParameterError
556+
assert.ErrorAs(t, err, &requiredErr)
557+
})
558+
559+
t.Run("date_form_no_explode_required_missing", func(t *testing.T) {
560+
var date types.Date
561+
queryParams := url.Values{}
562+
err := BindQueryParameter("form", false, true, "date", queryParams, &date)
563+
var requiredErr *RequiredParameterError
564+
assert.ErrorAs(t, err, &requiredErr)
565+
})
566+
547567
t.Run("date_form_no_explode_required", func(t *testing.T) {
548568
expectedDate := types.Date{Time: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)}
549569
var date types.Date

0 commit comments

Comments
 (0)