🔥 feat: Added support for custom binding precedence#4544
Conversation
|
Thanks for opening this pull request! 🎉 Please check out our contributing guidelines. If you need help or want to chat with us, join us on Discord https://gofiber.io/discord |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Walkthrough
ChangesCustom binding precedence
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant RequestType
participant BindAll
participant BindingSources
RequestType->>BindAll: binding_source precedence tag
BindAll->>BindingSources: invoke sources in configured order
BindingSources-->>BindAll: populated destination fields
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@aryan262 Sounds like a cool feature, but we definitely need documentation; otherwise, no one will know about it and therefore no one will use it. |
|
@ReneWerner87 I am new to this repo, how should I add documentation for this PR ? |
|
here is the location of the docs files and this is the result https://docs.gofiber.io/ |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4544 +/- ##
==========================================
+ Coverage 93.19% 93.24% +0.05%
==========================================
Files 140 140
Lines 14567 14625 +58
==========================================
+ Hits 13575 13637 +62
+ Misses 619 615 -4
Partials 373 373
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@aryan262 The linter workflow is failing. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
docs/api/bind.md (1)
74-98: 📐 Maintainability & Code Quality | 🔵 TrivialRun
make markdownbefore merge. This repository has amarkdowntarget that checks all**/*.mdfiles, includingdocs/api/bind.md.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/api/bind.md` around lines 74 - 98, Run the repository’s markdown formatting or validation step with make markdown after updating the bind documentation, and resolve any reported formatting issues in docs/api/bind.md before merging.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/api/bind.md`:
- Line 97: Update the Fiber precedence-cache note in Bind.All documentation to
remove the claim of zero-allocation efficiency. State only that precedence
resolution is cached per reflect.Type to reduce repeated parsing overhead.
---
Nitpick comments:
In `@docs/api/bind.md`:
- Around line 74-98: Run the repository’s markdown formatting or validation step
with make markdown after updating the bind documentation, and resolve any
reported formatting issues in docs/api/bind.md before merging.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
|
@gaby can you check now if it's failing. I'll check |
|
Error: bind_test.go:2952:1: File is not properly formatted (gofmt) |
|
@gaby I think it was because of an extra line expected in that file. Fixed it |
gaby
left a comment
There was a problem hiding this comment.
Thanks for picking up the binding_source TODO — the feature is legitimately useful and the per-reflect.Type caching is the right design: tag parsing never runs on the hot path after the first request per type, All() already guarantees a pointer-to-struct before getBindingPrecedence runs (so NumField() can't panic), and the cached slice is never mutated after store, so sharing it is safe.
That said, requesting changes for a few correctness/usability gaps before this merges:
Main issues (details inline):
- Invalid tag tokens are silently dropped — a typo silently changes which sources get bound, and an all-invalid tag silently falls back to the default order. This should fail loudly.
- Undocumented/untested semantics — omitted sources are never bound, duplicates bind twice, and first-tag-wins is field-order dependent when multiple fields carry the tag.
- Docs example leaks the marker field —
c.JSON(req)will emit"BindingSource":{}; needsjson:"-"at minimum. - Lint/style — the C-style
forloop will trip themodernizelinter, and the docs note should use a:::infoadmonition like the rest of the file. - Benchmarks — the PR checks the Benchmarks box but adds none; every existing
All()call now pays async.Map.Load, so it'd be good to show the default path didn't regress and add one for the custom path.
None of these are structural — the core approach can stay as-is. 👍
Generated by Claude Code
gaby
left a comment
There was a problem hiding this comment.
Re-reviewed at 0370b26 — this update addresses all of the previous round's feedback: invalid tokens now error (with negative-result caching, nice touch), multiple tags error instead of being field-order dependent, duplicates are deduped, the modernize loop style is fixed, the slice is pre-sized and hasBody extracted, the docs example no longer leaks a marker field into JSON, the note uses :::info with the partial-list/unknown-source semantics spelled out, and the test/benchmark coverage is now thorough. 👏
I also verified locally (fork CI hasn't run yet):
- ✅ All
Test_Bind_All*tests pass. - ✅ No regression on the default path —
BenchmarkBind_Allactually improved slightly vsmain(59 → 57 allocs/op, ~2056 → ~1991 B/op), thanks to the pre-sized slice. - ❌ Lint will fail CI — golangci-lint v2.12.2 (the version pinned in
.github/workflows/lint.yml) reports 6 issues, all inbind_test.go: 5×errcheckon the bare.(*DefaultCtx)assertions, and 1×gofmton the benchmark'sUserstruct alignment. Both are mechanical fixes — details inline.
Requesting changes only for the two lint items; the remaining inline comments are optional nits (stale cache comment, empty-token error message, require.EqualError, and a non-blocking note about the error path skipping returnErr). Once lint is green this looks good to me.
Generated by Claude Code
Description
Currently, Fiber's ctx.Bind().All() method binds values from request sources using a strict, hardcoded precedence (URI params -> Body -> Query -> Headers -> Cookies). If conflicting data exists across these sources, developers have no mechanism to override which source takes priority on a per-struct basis.
This PR introduces support for a new struct tag, binding_source, which allows developers to define a custom precedence order for data binding. For example: binding_source:"query,header,cookie,body,uri".
To maintain Fiber's strict zero-allocation and high-performance standards, this implementation avoids parsing struct tags or splitting strings on the hot path for every request. Instead, it utilizes a highly optimized internal caching layer (bindingPrecedenceCache via sync.Map) to process and store the precedence configuration exactly once per reflect.Type.
Fixes # (issue)
Changes introduced
List the new features or adjustments introduced in this pull request. Provide details on benchmarks, documentation updates, changelog entries, and if applicable, the migration guide.
Type of change
Please delete options that are not relevant.
Checklist
Before you submit your pull request, please make sure you meet these requirements:
/docs/directory for Fiber's documentation.Commit formatting
Please use emojis in commit messages for an easy way to identify the purpose or intention of a commit. Check out the emoji cheatsheet here: CONTRIBUTING.md