Skip to content

feat(libRequest): add optional JSON body binding modes - #59

Merged
hmmftg merged 2 commits into
mainfrom
feat/optional-json-body
Oct 3, 2026
Merged

hmmftg merged 2 commits into
mainfrom
feat/optional-json-body

Conversation

@hmmftg

@hmmftg hmmftg commented Oct 3, 2026

Copy link
Copy Markdown
Owner

Problem

libRequest.parseRequest treats every body parse failure as fatal (ERROR_IN_GET_REQUEST_BODY → 400). For endpoints where the body is optional — e.g. POST /api/card/:cardNumber/harim, which takes all required input from the path and only reads cvv2/expiry when present — a POST with Content-Length: 0 is rejected even though the contract allows it. Clients that send no body (e.g. Swagger UI when no requestBody is defined) get an unexpected 400.

Design

  • New sentinel webFramework.ErrEmptyBody, returned by RequestParser.GetBody implementations when the body is absent or zero-length (wrappable; callers use errors.Is). Empty body is now distinguishable from a successful bind.
  • Two new libRequest.Type values, appended at the end of the const block so existing iota values — which are JSON-serialized and persisted — are unchanged:
    • JSONOptional — binds JSON when present; empty body yields the zero-valued request.
    • JSONWithURIOptional — same optional body semantics; URI binding stays mandatory.
  • requestTypeEnum.go regenerated via enumer (v1.7.2).
  • Parsers: libGin maps io.EOF → sentinel; libFiber returns it when len(Body()) == 0; libNetHttp returns it for absent/empty bodies (previously returned nil); FakeParser gains a BodyError field and honors the sentinel; TestingParser honors it for nil/empty fixtures.
  • TestingParser.setTarget no longer panics: it previously called Set on an unaddressable reflect.Value; now uses Elem() with kind/assignability guards.

Backwards compatibility

  • JSON and JSONWithURI still fail on empty bodies with ERROR_IN_GET_REQUEST_BODY — only the new modes tolerate the sentinel.
  • One intentional alignment: libNetHttp previously accepted empty bodies under required JSON; it now matches Gin/Fiber and rejects them.
  • Struct validation (libValidate.ValidateStruct) still runs for optional modes on the zero-valued request — optional body fields need omitempty/non-required tags.
  • Malformed bodies still return 400 in all modes.

Usage

handlers.HandlerParameters[Req, Resp]{
    Body: libRequest.JSONWithURIOptional, // body optional; URI params still bound
}

Testing

  • Table-driven tests: optional modes with empty body (success), valid body (bound + validated), malformed body (400), missing required URI param (400), plus regression coverage that JSON/JSONWithURI still reject empty bodies.
  • Per-parser ErrEmptyBody assertions for Gin, Fiber, and net/http.
  • go build ./..., go test ./..., go vet ./... all green.

Hamid MalekMohammadi and others added 2 commits October 3, 2026 12:44
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…in TestingParser

Extend TestingParser.GetBody to return webFramework.ErrEmptyBody for empty
string and empty byte slice fixtures, matching the nil body behavior. Add
table-driven test cases for both empty string and empty []byte. Replace
if-nil check with type switch to handle string/[]byte length checks before
setTarget. Preserve existing precedence: BodyError takes priority over
empty-body detection.
@hmmftg
hmmftg merged commit d841dea into main Oct 3, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant