Skip to content

Conversation

@ReneWerner87
Copy link
Member

@ReneWerner87 ReneWerner87 commented Dec 7, 2025

  • check benchmark output and compare with main branch

Copilot AI review requested due to automatic review settings December 7, 2025 20:12
@ReneWerner87 ReneWerner87 requested a review from a team as a code owner December 7, 2025 20:12
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR replaces many manual index/slice/contains patterns with safer, idiomatic parsing primitives (strings.Cut, strings.Index/IndexByte, bytes.Cut, length checks) and adopts small utils helpers across middleware and core packages. No exported/public API signatures were changed.

Changes

Cohort / File(s) Summary
Core & request parsing
client/core.go, req.go, ctx.go, helpers.go, path.go, res.go
Replace index/slice/HasPrefix/HasSuffix/Contains with strings.Cut, strings.Index/IndexByte, bytes.Cut, and length-based checks for port/host, headers, Transfer-Encoding, MIME types, ETag normalization, ranges, and route param length logic.
Middleware — CORS & CSRF
middleware/cors/cors.go, middleware/cors/utils.go, middleware/csrf/csrf.go, middleware/csrf/helpers.go
Move wildcard-origin and subdomain parsing to strings.Cut and index-based checks; add normalization/validation for scheme://host, use utils for casing, and tighten subdomain matching and wildcard handling.
Middleware — Auth, Idempotency, Redirect, ETag, Compress, Cache
middleware/basicauth/basicauth.go, middleware/idempotency/idempotency.go, middleware/redirect/redirect.go, middleware/etag/etag.go, middleware/compress/compress.go, middleware/cache/cache.go, middleware/csrf/config.go
Use strings.Cut for credential splitting and origin parsing, employ utils helpers and CopyString for safe key handling, replace Contains/HasPrefix with index/length-safe checks, and adjust ETag/Cache-Control containment logic.
Logger & template processing
middleware/logger/logger.go, middleware/logger/template_chain.go
Replace index-based template/tag parsing with bytes.Cut-based splits; switch latency/time tag checks to index-based containment and adjust function/parameter extraction logic.
Proxy / Static / Router / Binder
middleware/proxy/proxy.go, middleware/static/static.go, router.go, binder/mapping.go, listen.go
Replace scheme extraction and wildcard/trim logic with bytes.Cut/strings.Cut or IndexByte checks; refine bracketed IPv6 handling, multi-value splitting, and startup banner newline logic.
App, services, client cookiejar
app.go, services.go, client/cookiejar.go
Use index/length-safe checks for CIDR detection and error substring checks; replace strings.ToUpper with utils.ToUpper; add preallocated https bytes slice to avoid allocations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • req.go — Host(), Scheme(), Range() parsing and X-Forwarded semantics after Cut-based changes.
    • middleware/logger/template_chain.go — correctness of funcChain/fixParts assembly and parameter lookup.
    • middleware/cors & middleware/csrf — wildcard normalization, validation, and panic paths.
    • middleware/idempotency — correct use of utils.CopyString for stable map keys.
    • binder/mapping.go — assignBindData splitting and new else-branch behavior.
    • Ensure no subtle behavioral regressions for edge inputs (empty strings, short ETags, bracketed IPv6).

Possibly related PRs

Suggested reviewers

  • sixcolors
  • efectn
  • gaby

Poem

🐇 I nibble at Index, choose Cut with delight,
No more brittle slices that kept me up at night.
Wildcards smoothed, headers neat and trim,
Fewer allocations, my hops are quick and prim. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is severely incomplete, containing only a single unchecked checkbox item instead of the required template sections like objectives, changes, type of change, and checklist items. Complete the PR description following the template: add clear change objectives, list specific changes made, select appropriate type(s) of change, and check off relevant checklist items with supporting details.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective of the PR: refactoring to replace string functions with more efficient alternatives throughout the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ReneWerner87 ReneWerner87 added this to the v3 milestone Dec 7, 2025
@ReneWerner87 ReneWerner87 added this to v3 Dec 7, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ReneWerner87, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on a significant refactoring effort across the codebase to modernize string and byte manipulation. By consistently adopting strings.Cut, bytes.Cut, strings.Contains, and bytes.Contains, the changes aim to simplify complex parsing logic, improve code readability, and enhance the overall maintainability and robustness of various components, including middleware, client utilities, and request/response handling.

Highlights

  • Modern Go String/Byte Manipulation: Replaced numerous instances of strings.Index, bytes.IndexByte, and manual string/byte slicing with the more idiomatic and readable strings.Cut, bytes.Cut, strings.Contains, and bytes.Contains functions.
  • Simplified Parsing Logic: Streamlined the parsing of credentials in basic authentication, HTTP Range headers, X-Forwarded-Host/X-Forwarded-Proto headers, and MIME types by using strings.Cut for cleaner extraction of substrings.
  • Improved Address and Origin Validation: Enhanced the logic for adding missing ports to addresses and parsing origins in CORS and CSRF middleware, making the validation more robust and easier to understand.
  • Refactored Template and Path Handling: Updated the template parsing chain in the logger middleware and parameter length calculation in path handling to use bytes.Cut and strings.Cut, improving clarity and efficiency.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 7, 2025

Codecov Report

❌ Patch coverage is 94.35484% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.62%. Comparing base (3f01d29) to head (b7beb05).

Files with missing lines Patch % Lines
middleware/cors/cors.go 71.42% 1 Missing and 1 partial ⚠️
middleware/logger/template_chain.go 84.61% 1 Missing and 1 partial ⚠️
ctx.go 80.00% 1 Missing ⚠️
middleware/pprof/pprof.go 0.00% 0 Missing and 1 partial ⚠️
middleware/proxy/proxy.go 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3923      +/-   ##
==========================================
- Coverage   91.64%   91.62%   -0.02%     
==========================================
  Files         119      119              
  Lines       10165    10165              
==========================================
- Hits         9316     9314       -2     
- Misses        538      539       +1     
- Partials      311      312       +1     
Flag Coverage Δ
unittests 91.62% <94.35%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ReneWerner87 ReneWerner87 changed the title ♻️ refactor: Simplify credential parsing and improve address validation ♻️ refactor: Replace string functions Dec 7, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a nice refactoring that simplifies string and byte slice manipulation across the codebase by using functions like strings.Cut and strings.Contains. These changes generally improve code readability and maintainability. I've identified a couple of areas for improvement. One is a logic issue in address parsing that isn't fully resolved by the refactoring, and I've suggested a more robust approach using the net package. The other is a minor performance regression in one of the refactored lines due to unnecessary memory allocation in a loop, for which I've proposed reverting to the previous, more efficient implementation.

client/core.go Outdated
Comment on lines 36 to 38
if strings.ContainsRune(addr, ':') {
return addr
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

While this change is a valid refactoring, the underlying logic of checking for a colon to detect a port is not robust. It can lead to incorrect behavior with IPv6 addresses (e.g., [::1] or 2001:db8::1), which contain colons but may not have a port specified. This check would incorrectly assume a port is present and return the address as is.

A more reliable approach is to use net.SplitHostPort to parse the address and specifically check for a 'missing port' error.

	if _, _, err := net.SplitHostPort(addr); err == nil {
		return addr
	} else if addrErr, ok := err.(*net.AddrError); !ok || !strings.Contains(addrErr.Err, "missing port") {
		return addr
	}

res.go Outdated
for key, val := range params {
isSame := key == segment.ParamName || (!app.config.CaseSensitive && utils.EqualFold(key, segment.ParamName))
isGreedy := segment.IsGreedy && len(key) == 1 && bytes.IndexByte(greedyParameters, key[0]) != -1
isGreedy := segment.IsGreedy && len(key) == 1 && bytes.Contains(greedyParameters, []byte{key[0]})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The change from bytes.IndexByte to bytes.Contains with []byte{key[0]} introduces a small performance regression. The expression []byte{key[0]} causes a memory allocation for a new byte slice on every iteration of the loop. The previous implementation using bytes.IndexByte was more efficient as it avoids this allocation.

Suggested change
isGreedy := segment.IsGreedy && len(key) == 1 && bytes.Contains(greedyParameters, []byte{key[0]})
isGreedy := segment.IsGreedy && len(key) == 1 && bytes.IndexByte(greedyParameters, key[0]) != -1

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors string and byte searching operations throughout the codebase by replacing manual index-based operations with more idiomatic strings.Cut/bytes.Cut calls and replacing some IndexByte checks with Contains. The changes improve code readability and add validation checks in CORS and CSRF middleware.

  • Replaced strings.Index/bytes.Index patterns with strings.Cut/bytes.Cut for cleaner string splitting
  • Replaced some IndexByte checks with Contains/ContainsRune for readability
  • Added validation for normalized origins in CORS and CSRF middleware

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
res.go Refactored greedy parameter check to use bytes.Contains
req.go Refactored Host(), Is(), Scheme(), and Range() methods to use strings.Cut
path.go Refactored parameter length finding to use strings.Cut and strings.Contains
middleware/static/static.go Refactored sanitizePath() to use strings.Contains and prefix handling with strings.Cut
middleware/proxy/proxy.go Simplified scheme extraction using bytes.Cut
middleware/logger/template_chain.go Refactored template parsing to use bytes.Cut for cleaner tag extraction
middleware/csrf/csrf.go Refactored origin parsing with strings.Cut and added post-normalization validation, plus constant usage for scheme comparison
middleware/cors/utils.go Refactored scheme matching and domain normalization to use strings.Cut
middleware/cors/cors.go Refactored origin parsing with strings.Cut and added post-normalization validation
middleware/basicauth/basicauth.go Simplified credential parsing using strings.Cut
helpers.go Refactored MIME type and language acceptance checks to use strings.Cut and strings.Contains
ctx.go Refactored transfer encoding parsing to use strings.Cut
client/core.go Simplified port checking to use strings.ContainsRune

sd := subdomain{prefix: normalizedOrigin[:schemeSep], suffix: normalizedOrigin[schemeSep:]}
scheme, host, ok := strings.Cut(normalizedOrigin, "://")
if !ok {
panic("[CSRF] Invalid origin format after normalization:" + maskValue(origin))
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after the colon in the error message. For consistency with line 80 ("[CSRF] Invalid origin format in configuration:"), add a space: "[CSRF] Invalid origin format after normalization: " + maskValue(origin)

Suggested change
panic("[CSRF] Invalid origin format after normalization:" + maskValue(origin))
panic("[CSRF] Invalid origin format after normalization: " + maskValue(origin))

Copilot uses AI. Check for mistakes.
sd := subdomain{prefix: normalizedOrigin[:schemeSep], suffix: normalizedOrigin[schemeSep:]}
scheme, host, ok := strings.Cut(normalizedOrigin, "://")
if !ok {
panic("[CORS] Invalid origin format after normalization:" + maskValue(trimmedOrigin))
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after the colon in the error message. For consistency with line 80 ("[CSRF] Invalid origin format in configuration:") and line 62 in cors.go, add a space: "[CORS] Invalid origin format after normalization: " + maskValue(trimmedOrigin)

Suggested change
panic("[CORS] Invalid origin format after normalization:" + maskValue(trimmedOrigin))
panic("[CORS] Invalid origin format after normalization: " + maskValue(trimmedOrigin))

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
middleware/cors/cors.go (1)

49-77: Wildcard origin normalization is more robust; minor panic message nit

The new strings.Cut(trimmedOrigin, "://*.") + normalizeOrigin flow produces a canonical scheme://host before constructing subdomain{prefix: scheme + "://", suffix: host}, which integrates cleanly with the subdomain.match logic and ensures invalid wildcard origins are rejected early.

One small readability nit: the panic string for the post-normalization failure is missing a space before the redacted value.

-            panic("[CORS] Invalid origin format after normalization:" + maskValue(trimmedOrigin))
+            panic("[CORS] Invalid origin format after normalization: " + maskValue(trimmedOrigin))
path.go (1)

545-584: Param length calculation now enforces segment boundaries more strictly

The updated findParamLen behavior:

  • Still respects precomputed segment.Length and greedy handling.
  • Uses strings.Cut(s, segment.ComparePart) to locate the following constant, and for non‑greedy params rejects matches where the prefix contains '/', so routes like /api/:param/fixedEnd won’t accept /api/123/456/fixedEnd. This is a correctness improvement for non‑greedy parameters.

findParamLenForLastSegment’s switch to strings.Cut on "/" keeps the existing semantics (first slash splits the last segment) while simplifying the code.

If you want to make the invariants more explicit and guard against future changes that might produce a parameter with an empty ComparePart reaching the Cut branch, you could add a cheap early return:

 func findParamLen(s string, segment *routeSegment) int {
@@
-    if before, _, found := strings.Cut(s, segment.ComparePart); found {
+    if segment.ComparePart == "" {
+        return len(s)
+    }
+    if before, _, found := strings.Cut(s, segment.ComparePart); found {
         // if the compare part was found, but contains a slash although this part is not greedy, then it must not match
         // example: /api/:param/fixedEnd -> path: /api/123/456/fixedEnd = no match , /api/123/fixedEnd = match
         if !segment.IsGreedy && strings.Contains(before, "/") {
             return 0
         }
         return len(before)
     }

Not strictly required with current route construction, but it clarifies expectations and avoids relying on Cut’s empty‑separator behavior.

helpers.go (1)

286-323: Cut-based MIME parsing in acceptsOfferType preserves wildcard semantics

Switching to strings.Cut for splitting spec and mimetype around '/', guarded by mimeFound && specFound, avoids index math and panics while keeping behavior for exact matches and <type>/* wildcards intact; allowing mimeAfter == "*" also safely supports wildcard offers. One minor nit is that the comment mentioning only <MIME_type>/* is now slightly narrower than what the code accepts.

req.go (1)

321-331: X-Forwarded-Host first-value extraction via strings.Cut is correct

Using strings.Cut(host, ",") to return the substring before the first comma correctly selects the leftmost host in multi-hop proxy lists while preserving existing behavior for single-valued headers; optionally trimming spaces around before would make it a bit more robust against headers like "example.com, proxy".

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eda2197 and cbd024f.

📒 Files selected for processing (13)
  • client/core.go (1 hunks)
  • ctx.go (1 hunks)
  • helpers.go (2 hunks)
  • middleware/basicauth/basicauth.go (1 hunks)
  • middleware/cors/cors.go (1 hunks)
  • middleware/cors/utils.go (2 hunks)
  • middleware/csrf/csrf.go (2 hunks)
  • middleware/logger/template_chain.go (1 hunks)
  • middleware/proxy/proxy.go (1 hunks)
  • middleware/static/static.go (4 hunks)
  • path.go (2 hunks)
  • req.go (4 hunks)
  • res.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Prefer github.com/gofiber/utils/v2 helpers (for example, utils.Trim) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Files:

  • middleware/basicauth/basicauth.go
  • ctx.go
  • middleware/static/static.go
  • middleware/cors/utils.go
  • path.go
  • middleware/logger/template_chain.go
  • res.go
  • req.go
  • helpers.go
  • middleware/csrf/csrf.go
  • middleware/cors/cors.go
  • client/core.go
  • middleware/proxy/proxy.go
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code
📚 Learning: 2025-12-07T15:07:23.885Z
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Applied to files:

  • path.go
  • req.go
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.

Applied to files:

  • req.go
🧬 Code graph analysis (2)
middleware/logger/template_chain.go (1)
middleware/logger/errors.go (1)
  • ErrTemplateParameterMissing (8-8)
req.go (1)
error.go (1)
  • ErrRangeMalformed (32-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Agent
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: unit (1.25.x, macos-latest)
  • GitHub Check: repeated
  • GitHub Check: Compare
  • GitHub Check: lint
🔇 Additional comments (18)
middleware/static/static.go (4)

45-45: LGTM: Clearer loop condition.

The refactor to strings.Contains is more idiomatic and improves readability. The loop semantics remain unchanged—it continues unescaping while percent-encoded sequences exist.


57-57: LGTM: More explicit null-byte validation.

The change to strings.Contains(s, "\x00") is clearer and more explicit about checking for null bytes. This maintains the security validation while improving code clarity.


119-121: LGTM: Safer and more idiomatic wildcard handling.

The refactor to strings.Cut is excellent. This modern Go approach (Go 1.18+) is:

  • Safer than manual Index + slicing
  • More efficient (single pass)
  • Clearer in intent

The functional behavior is preserved—extracting the substring before the first asterisk for partial wildcard routes.


31-31: LGTM: Improved idiom for backslash detection.

The change from bytes.IndexByte to bytes.Contains is more idiomatic and clearer. The semantics remain equivalent, and the github.com/gofiber/utils/v2 package does not provide a Contains-like helper for this operation, making the stdlib approach appropriate per coding guidelines.

res.go (1)

617-621: Greedy parameter detection change keeps behavior intact

Using bytes.Contains(greedyParameters, []byte{key[0]}) preserves the original “single‑byte greedy key in the whitelist” semantics; given the tiny greedyParameters set and non–hot-path usage in getLocationFromRoute, the extra single‑byte slice construction is acceptable here.

client/core.go (1)

33-44: Simplified port detection remains correct

Switching to strings.ContainsRune(addr, ':') for deciding whether to append the default port keeps the original behavior while making the intent clearer and avoiding manual index checks.

middleware/cors/utils.go (1)

8-28: Scheme and port handling semantics are preserved and clearer

matchScheme now cleanly extracts schemes via strings.Cut(domain, ":") / strings.Cut(pattern, ":") and only matches when both sides actually have a scheme, which aligns with the function’s contract. The normalizeDomain change to strings.Cut(input, ":") under the non‑IPv6 condition keeps the previous “strip first port separator” behavior for host:port while avoiding manual index math.

ctx.go (1)

386-425: Transfer-Encoding parsing now correctly ignores parameters

The added strings.Cut(token, ";") + trim before checking for "identity" ensures that values like identity;q=0.8 are treated as identity (i.e., no body), while any non‑identity encodings still set hasEncoding = true. This brings hasTransferEncodingBody closer to the HTTP spec without changing behavior for simple cases.

middleware/basicauth/basicauth.go (1)

84-104: Cut-based credential split is safer and clearer

Using strings.Cut(creds, ":") both simplifies the "username:password" parsing and properly rejects malformed credentials that lack a colon, while preserving support for empty passwords and colon-containing passwords.

middleware/proxy/proxy.go (1)

204-210: getScheme refactor preserves URI handling

Refactoring getScheme to bytes.Cut(uri, []byte("://")) keeps the previous behavior—returning the bytes before the first "://" or nil if absent—while removing manual index arithmetic and making the intent of the code self-evident.

middleware/csrf/csrf.go (2)

74-87: Trusted origin wildcard normalization via strings.Cut looks solid

The new strings.Cut(trimmedOrigin, "://*.") path correctly rewrites scheme://*.host to scheme://host for normalization, then safely re-splits the normalized value into scheme and host with a second Cut, panicking on invalid formats. This keeps trustedSubOrigins consistent and improves validation without changing the matching semantics.


139-150: Missing Origin on non-HTTPS now bypasses referer check — confirm this is intentional

The updated logic only falls back to refererMatchesHost when c.Scheme() == schemeHTTPS, and otherwise clears errOriginNotFound, effectively relaxing CSRF origin/referer enforcement for plain HTTP requests. That can be a deliberate trade-off (since referer is less reliable on HTTP), but it is a security-behavior change; please confirm this matches the intended CSRF policy and that tests/docs reflect it.

helpers.go (2)

207-220: Language range wildcard handling remains consistent with intent

Using strings.Contains(spec, "*") (after the special-case spec == "*") still enforces that only a standalone "*" is accepted as a wildcard and any other occurrence of * makes the range invalid, matching the documented behavior.


704-737: parseAddr host/port splitting correctly handles IPv6 and edge cases

The function now prefers bracketed IPv6 ([::1]:8080), uses LastIndexByte for generic host:port, and falls back to treating unbracketed IPv6 literals containing additional : as pure hosts with no port, which is appropriate for its use in Hostname().

req.go (3)

488-502: Content-Type parameter stripping in Is is safely simplified

Replacing the index/slice logic with strings.Cut(ct, ";") to drop parameters, followed by utils.TrimSpace and utils.EqualFold, keeps the same matching semantics while making the code clearer and less error-prone.


635-652: Scheme determination from X-Forwarded headers benefits from Cut-based comma handling

For X-Forwarded-Proto / X-Forwarded-Protocol, taking the substring before the first comma via strings.Cut ensures only the leftmost forwarded scheme is considered when multiple values are present, which aligns with typical proxy header semantics and avoids manual index management.


741-822: Range header Cut-based parsing looks sound; verify behavior for missing/malformed headers

The new strings.Cut usage to separate <type>=<ranges> and to split each range on , and - keeps support for nnn-, -nnn, and multiple ranges while enforcing a single '=' in the header and simplifying the control flow. Note that when the Range header is empty or lacks '=', you now return ErrRangeMalformed immediately via the !found check; please confirm all call sites treat this as expected (e.g., differentiating between “no Range header” and “malformed Range” when choosing status codes).

middleware/logger/template_chain.go (1)

17-70: buildLogFuncChain Cut-based parsing keeps func/param alignment and improves clarity

The refactor to use bytes.Cut around startTag and endTag cleanly separates fixed segments from function blocks, and the bytes.Cut(before, paramSeparatorB) path correctly distinguishes parameterized tags (tagFunctions[tag+paramSeparator] with the param stored in fixParts) from non-parameter tags, while preserving the existing behavior for missing end tags and maintaining fixParts/funcChain alignment.

@ReneWerner87
Copy link
Member Author

I will change back the strings.Contains to the index functions

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
middleware/cors/cors.go (1)

66-66: Missing space after the colon in the error message.

For consistency with the error message on line 62 and line 73, add a space after the colon.

-				panic("[CORS] Invalid origin format after normalization:" + maskValue(trimmedOrigin))
+				panic("[CORS] Invalid origin format after normalization: " + maskValue(trimmedOrigin))
🧹 Nitpick comments (2)
middleware/cors/utils.go (1)

92-92: Misleading performance comment.

The nolint comment states strings.Index is faster than strings.Contains, but in Go's standard library, strings.Contains is literally implemented as return Index(s, substr) >= 0. They have identical performance since Contains is just a thin wrapper around Index.

If the intent is to use index-based functions for consistency (per PR objectives), consider updating the comment to reflect that reason rather than an inaccurate performance claim.

-	if sub == "" || sub[0] == '.' || strings.Index(sub, "..") >= 0 { //nolint:gocritic,staticcheck // strings.Index is faster than strings.Contains
+	if sub == "" || sub[0] == '.' || strings.Index(sub, "..") >= 0 { //nolint:gocritic,staticcheck // using Index for consistency with codebase style
middleware/compress/compress.go (1)

115-119: Weak ETag check is correct; consider optional readability helper

The new condition tag != "" && (len(tag) < 2 || tag[0] != 'W' || tag[1] != '/') is logically equivalent to the old !strings.HasPrefix(tag, "W/") and remains safe (short‑circuiting prevents out‑of‑bounds). This looks good and keeps things allocation‑free. If you want to make it more self‑documenting, you could optionally extract this into a small isWeakETag(tag string) bool helper and negate that here, but it’s not required.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cbd024f and 9c01107.

📒 Files selected for processing (17)
  • app.go (2 hunks)
  • binder/mapping.go (2 hunks)
  • helpers.go (5 hunks)
  • listen.go (1 hunks)
  • middleware/cache/cache.go (1 hunks)
  • middleware/compress/compress.go (1 hunks)
  • middleware/cors/cors.go (2 hunks)
  • middleware/cors/utils.go (5 hunks)
  • middleware/csrf/helpers.go (3 hunks)
  • middleware/idempotency/idempotency.go (1 hunks)
  • middleware/logger/logger.go (1 hunks)
  • middleware/redirect/redirect.go (2 hunks)
  • middleware/static/static.go (3 hunks)
  • path.go (2 hunks)
  • req.go (5 hunks)
  • res.go (4 hunks)
  • services.go (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • middleware/logger/logger.go
  • middleware/cache/cache.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • middleware/static/static.go
  • path.go
  • res.go
  • helpers.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Prefer github.com/gofiber/utils/v2 helpers (for example, utils.Trim) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Files:

  • app.go
  • middleware/redirect/redirect.go
  • req.go
  • middleware/cors/cors.go
  • binder/mapping.go
  • middleware/compress/compress.go
  • middleware/idempotency/idempotency.go
  • middleware/csrf/helpers.go
  • middleware/cors/utils.go
  • services.go
  • listen.go
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code
📚 Learning: 2025-12-07T15:07:23.885Z
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Applied to files:

  • app.go
  • middleware/redirect/redirect.go
  • middleware/idempotency/idempotency.go
  • middleware/cors/utils.go
  • services.go
📚 Learning: 2024-11-15T07:56:21.623Z
Learnt from: ReneWerner87
Repo: gofiber/fiber PR: 3161
File: app.go:923-932
Timestamp: 2024-11-15T07:56:21.623Z
Learning: In the Fiber framework, breaking changes are acceptable when moving from version 2 to version 3, including modifications to method signatures such as in the `Test` method in `app.go`.

Applied to files:

  • middleware/redirect/redirect.go
📚 Learning: 2025-10-16T07:15:26.529Z
Learnt from: grivera64
Repo: gofiber/fiber PR: 3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:15:26.529Z
Learning: In Fiber v3, net/http handlers (http.Handler, http.HandlerFunc, or raw func(http.ResponseWriter, *http.Request)) can be passed directly to routing methods like app.Get(), app.Post(), etc. The framework automatically detects and wraps them internally via toFiberHandler/collectHandlers. The github.com/gofiber/fiber/v3/middleware/adaptor package is legacy and should not be suggested for tests or code using native net/http handler support.

Applied to files:

  • middleware/redirect/redirect.go
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.

Applied to files:

  • req.go
  • middleware/cors/cors.go
  • middleware/idempotency/idempotency.go
📚 Learning: 2025-10-16T07:19:52.418Z
Learnt from: grivera64
Repo: gofiber/fiber PR: 3807
File: adapter_test.go:118-144
Timestamp: 2025-10-16T07:19:52.418Z
Learning: In the Fiber codebase, the linter does not allow `require` assertions from within HTTP handlers (including net/http-style handlers). Use `t.Fatalf`, `t.Errorf`, or similar `testing.T` methods for error handling inside handler functions instead.

Applied to files:

  • middleware/idempotency/idempotency.go
📚 Learning: 2025-05-07T13:07:33.899Z
Learnt from: mdelapenya
Repo: gofiber/fiber PR: 3434
File: docs/api/services.md:39-43
Timestamp: 2025-05-07T13:07:33.899Z
Learning: When documenting Go interface methods in the Fiber project, avoid showing method signatures with the interface type as the receiver (e.g., `func (d *Service) Method()`) since interfaces cannot be used as receivers in Go. Instead, show just the method signature without a receiver or use a placeholder implementation name.

Applied to files:

  • services.go
🧬 Code graph analysis (3)
app.go (2)
log/fiberlog.go (1)
  • Error (14-16)
constants.go (1)
  • ErrNotImplemented (149-149)
req.go (1)
error.go (1)
  • ErrRangeMalformed (32-32)
middleware/compress/compress.go (1)
constants.go (1)
  • HeaderETag (181-181)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: repeated
  • GitHub Check: lint
  • GitHub Check: Compare
🔇 Additional comments (22)
middleware/idempotency/idempotency.go (1)

54-56: LGTM! Follows coding guidelines with proper safety measures.

The combination of utils.ToLower and utils.CopyString correctly ensures map keys are immutable copies, addressing the unsafe string usage mentioned in the comment. The approach aligns with the coding guideline to prefer github.com/gofiber/utils/v2 helpers for string manipulation. The added comment clearly documents the rationale, and the pattern is consistently applied (note that line 154's lookup correctly uses utils.ToLower without CopyString since it's only a temporary comparison value, not a stored key).

As per coding guidelines, this properly uses utils helpers for string operations.

binder/mapping.go (2)

340-340: LGTM!

Using strings.IndexByte for single-character presence checks is more efficient than strings.Contains.


379-386: LGTM!

The refactored assignBindData function correctly uses strings.IndexByte for comma detection and properly handles the else branch to append single values.

middleware/csrf/helpers.go (3)

61-63: LGTM!

The change to strings.IndexByte for detecting colons in IPv6 hostnames is correct and more efficient for single-byte checks.


86-88: LGTM!

Using strings.IndexByte for wildcard detection is appropriate and efficient.


129-132: LGTM!

Using strings.Index for the multi-character substring ".." is correct. The nolint comment appropriately documents the performance rationale.

app.go (2)

673-673: LGTM!

Using strings.IndexByte for detecting the CIDR slash character is correct and efficient.


1350-1353: LGTM!

The refactor to strings.Index for error message detection preserves existing behavior. The nolint comments appropriately document the performance rationale.

req.go (6)

324-327: LGTM!

Using strings.Cut for comma-separated header parsing is cleaner and correctly returns the portion before the first comma.


497-501: LGTM!

Using strings.Cut to strip Content-Type parameters after the semicolon is cleaner and maintains the same behavior.


647-651: LGTM!

The refactor to strings.Cut for extracting the scheme from comma-separated forwarded headers is correct and more readable.


760-791: LGTM!

The Range parsing has been cleanly refactored to use strings.Cut:

  • Line 761 correctly validates no extra = characters
  • Lines 776-778 properly iterate through comma-separated ranges
  • Lines 786-791 correctly parse start-end bounds with hyphen separator

The logic is equivalent and more readable than the previous index-based approach.


852-856: LGTM!

Using strings.Index for the multi-character "xn--" punycode prefix check is correct. The nolint comment documents the performance rationale.


860-862: LGTM!

The length-based bracket check is more efficient than HasPrefix/HasSuffix for single-character checks at known positions.

middleware/cors/cors.go (2)

58-68: LGTM on the refactored wildcard origin parsing.

The use of strings.Cut to detect and process wildcard subdomain patterns (://*.) is cleaner. The subsequent normalization and scheme/host extraction is correct.


101-101: LGTM!

Using utils.ToLower aligns with the coding guidelines to prefer github.com/gofiber/utils/v2 helpers.

middleware/cors/utils.go (5)

6-7: LGTM!

Adding the utils import aligns with the coding guidelines to prefer github.com/gofiber/utils/v2 helpers for common operations.


12-14: LGTM!

Using strings.Cut is idiomatic for extracting the scheme portion, and the logic correctly ensures both inputs contain a scheme separator before comparing.


24-26: LGTM!

Clean use of strings.Cut to extract the host portion before the port separator.


45-45: LGTM!

Using strings.IndexByte for single-character search is appropriate and consistent with the PR's objective of using index-based functions.


57-59: LGTM!

Good use of utils.ToLower per coding guidelines, with appropriate utils.CopyString wrapper to ensure safety when the result is stored. The comment clearly explains the rationale.

middleware/redirect/redirect.go (1)

9-9: LGTM: Import aligns with coding guidelines.

Adding the utils/v2 package follows the established guideline to prefer Fiber's utility helpers for string manipulation.

As per coding guidelines and learnings, prefer github.com/gofiber/utils/v2 helpers when performing common operations.

Comment on lines 434 to 439
if preData.BannerHeader != "" {
header := preData.BannerHeader
fmt.Fprint(out, header)
if !strings.HasSuffix(header, "\n") {
if header == "" || header[len(header)-1] != '\n' {
fmt.Fprintln(out)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Dead code: header == "" check is unreachable.

Since line 434 ensures preData.BannerHeader != "", the header variable assigned on line 435 is guaranteed to be non-empty. The header == "" check on line 437 can never be true.

Apply this diff to simplify the condition:

 	if preData.BannerHeader != "" {
 		header := preData.BannerHeader
 		fmt.Fprint(out, header)
-		if header == "" || header[len(header)-1] != '\n' {
+		if header[len(header)-1] != '\n' {
 			fmt.Fprintln(out)
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if preData.BannerHeader != "" {
header := preData.BannerHeader
fmt.Fprint(out, header)
if !strings.HasSuffix(header, "\n") {
if header == "" || header[len(header)-1] != '\n' {
fmt.Fprintln(out)
}
if preData.BannerHeader != "" {
header := preData.BannerHeader
fmt.Fprint(out, header)
if header[len(header)-1] != '\n' {
fmt.Fprintln(out)
}
🤖 Prompt for AI Agents
In listen.go around lines 434 to 439, the check `header == ""` is unreachable
because the outer `if preData.BannerHeader != ""` guarantees non-empty header;
remove the redundant empty-string check and simplify the condition to only test
whether the last character is a newline (i.e., call fmt.Fprintln(out) when
header[len(header)-1] != '\n'), keeping the existing assignment and fmt.Fprint
call.

Comment on lines 46 to 49
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
if len(input) > 1 {
input = strings.TrimSuffix(input, "/")
input = utils.TrimRight(input, '/')
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check utils.TrimRight implementation/behavior
echo "=== Checking utils.TrimRight implementation ==="
rg -n -A 10 'func TrimRight' --type=go | head -30

# Find tests for captureTokens function
echo -e "\n=== Finding tests for captureTokens ==="
rg -n 'captureTokens|TestCapture' --type=go -g '*_test.go'

# Check the redirect test file to understand test coverage
echo -e "\n=== Checking redirect test file ==="
fd -e go -p '*redirect*test*' | head -5

Repository: gofiber/fiber

Length of output: 494


🏁 Script executed:

# Find redirect test file with correct glob pattern
echo "=== Finding redirect test files ==="
fd -e go 'redirect.*test' --type f

# Check imports in redirect.go to understand utils source
echo -e "\n=== Checking imports in redirect.go ==="
head -20 middleware/redirect/redirect.go

# Search for TrimRight in entire codebase (might be in utils v2)
echo -e "\n=== Searching for TrimRight usage/definition ==="
rg -n 'TrimRight' --type=go | head -20

# Check if utils is a dependency
echo -e "\n=== Checking go.mod for utils dependency ==="
grep -n 'gofiber/utils' go.mod

Repository: gofiber/fiber

Length of output: 1774


🏁 Script executed:

# Check redirect_test.go for captureTokens tests
echo "=== Examining redirect_test.go for captureTokens tests ==="
cat middleware/redirect/redirect_test.go

Repository: gofiber/fiber

Length of output: 7381


🏁 Script executed:

# View the captureTokens function implementation
echo "=== Viewing captureTokens function ==="
sed -n '45,60p' middleware/redirect/redirect.go

# Check if utils.TrimRight behavior is documented
echo -e "\n=== Searching for TrimRight usage patterns in path contexts ==="
rg -B 2 -A 2 'utils.TrimRight.*"/"' --type=go | head -40

Repository: gofiber/fiber

Length of output: 626


🏁 Script executed:

# Check the git history to see what the previous implementation was
echo "=== Checking git history for this function ==="
git log --oneline -n 20 -- middleware/redirect/redirect.go

# Check if there's any documentation about trailing slash behavior
echo -e "\n=== Searching for documentation about trailing slash behavior ==="
rg -n 'trailing|slash' --type=go middleware/redirect/ -i

Repository: gofiber/fiber

Length of output: 276


Confirm the behavioral change from TrimSuffix to TrimRight is intentional and add test coverage.

The change from strings.TrimSuffix(input, "/") to utils.TrimRight(input, '/') alters path normalization behavior:

  • strings.TrimSuffix removes exactly one trailing "/"
  • utils.TrimRight removes all trailing "/" characters

For example, "/path//" changes from "/path/" to "/path". While using utils.TrimRight aligns with the coding guidelines for utils helper usage, the behavioral difference for paths with multiple trailing slashes is not covered by existing tests.

Ensure this normalization behavior is intentional for v3 and consider adding a test case for "/path//" patterns to verify the redirect matching works as expected.

🤖 Prompt for AI Agents
In middleware/redirect/redirect.go around lines 46 to 49, the change from
strings.TrimSuffix(input, "/") to utils.TrimRight(input, '/') changes path
normalization by removing all trailing slashes instead of just one; verify this
behavioral change is intentional for v3 and either revert to TrimSuffix if the
single-slash semantics must be preserved or keep TrimRight but add unit tests
covering inputs like "/path//" (and other multi-trailing-slash cases) to assert
expected redirect matching; update or add test cases in the redirect middleware
test file to codify the chosen behavior and add a short comment in the code
explaining the normalization decision.

Comment on lines +149 to +151
state = utils.ToUpper(state)
}
fmt.Fprintf(out, "%sINFO%s 🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, strings.ToUpper(state), srv.String(), scheme.Reset)
fmt.Fprintf(out, "%sINFO%s 🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, utils.ToUpper(state), srv.String(), scheme.Reset)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Redundant utils.ToUpper call on line 151.

The state variable is already uppercased on line 149. The second call to utils.ToUpper(state) on line 151 is unnecessary.

Apply this diff to remove the redundant call:

 			state = utils.ToUpper(state)
 		}
-		fmt.Fprintf(out, "%sINFO%s    🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, utils.ToUpper(state), srv.String(), scheme.Reset)
+		fmt.Fprintf(out, "%sINFO%s    🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, state, srv.String(), scheme.Reset)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
state = utils.ToUpper(state)
}
fmt.Fprintf(out, "%sINFO%s 🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, strings.ToUpper(state), srv.String(), scheme.Reset)
fmt.Fprintf(out, "%sINFO%s 🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, utils.ToUpper(state), srv.String(), scheme.Reset)
state = utils.ToUpper(state)
}
fmt.Fprintf(out, "%sINFO%s 🥡 %s[ %s ] %s%s\n", scheme.Green, scheme.Reset, stateColor, state, srv.String(), scheme.Reset)
🤖 Prompt for AI Agents
In services.go around lines 149 to 151, the code redundantly calls utils.ToUpper
on state twice; remove the second utils.ToUpper call in the fmt.Fprintf
invocation and use the already-uppercased state variable instead so the printed
state reuses state (e.g., replace utils.ToUpper(state) with state) to eliminate
the unnecessary function call.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
router.go (1)

331-349: Flash-cookie detection refactor is behaviorally equivalent

Using bytes.Index(rawHeaders, flashCookieNameBytes) >= 0 (with the length guard) preserves the prior bytes.Contains behavior for both DefaultCtx and CustomCtx paths while matching the PR’s index‑based pattern. The duplication between the two branches is acceptable and keeps their behavior in lockstep.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c01107 and ebfbc8b.

📒 Files selected for processing (4)
  • middleware/etag/etag.go (1 hunks)
  • middleware/static/static.go (2 hunks)
  • res.go (4 hunks)
  • router.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • middleware/static/static.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Prefer github.com/gofiber/utils/v2 helpers (for example, utils.Trim) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Files:

  • middleware/etag/etag.go
  • res.go
  • router.go
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.

Applied to files:

  • router.go
📚 Learning: 2024-11-10T23:44:13.704Z
Learnt from: gaby
Repo: gofiber/fiber PR: 3193
File: middleware/adaptor/adaptor.go:111-111
Timestamp: 2024-11-10T23:44:13.704Z
Learning: In the `middleware/adaptor/adaptor.go` file of the Fiber framework, when updating context handling, replacing `c.Context()` with `c.RequestCtx()` is appropriate to access the `fasthttp.RequestCtx`.

Applied to files:

  • router.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: repeated
  • GitHub Check: Compare
  • GitHub Check: lint
🔇 Additional comments (4)
middleware/etag/etag.go (1)

105-110: Index-based ETag match preserves previous behavior

Switching from bytes.Contains to bytes.Index(...) >= 0 keeps the same containment semantics, is nil/empty‑safe for clientEtag, and doesn’t change the weak/strong ETag handling logic. The added //nolint is appropriate given the explicit perf intent.

res.go (3)

619-619: LGTM! Performance issue correctly resolved.

The change from bytes.Contains(greedyParameters, []byte{key[0]}) to bytes.IndexByte(greedyParameters, key[0]) >= 0 properly addresses the past review comments about memory allocation. This avoids creating a temporary byte slice on each loop iteration.


660-660: Intentional optimization per PR objectives.

The use of strings.Index with >= 0 check instead of strings.Contains is consistent with this PR's performance optimization goals. The nolint comment appropriately documents the rationale.


1022-1024: Manual prefix check is correct and safe.

The length-based prefix check properly guards against out-of-bounds access and is functionally equivalent to strings.HasPrefix.

Comment on lines +1035 to 1037
if len(mimeType) >= 5 && (mimeType[len(mimeType)-5:] == "+json" || mimeType[len(mimeType)-4:] == "+xml") {
return true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Edge case: 4-character strings ending in "+xml" won't be detected.

The condition requires len(mimeType) >= 5, which safely handles the "+json" suffix check (5 chars) but excludes MIME types of exactly 4 characters ending in "+xml". The original strings.HasSuffix(mimeType, "+xml") would have detected these.

In practice, valid MIME types are much longer (e.g., "application/foo+xml"), so this edge case is unlikely to occur. However, it's technically a behavior change.

If you want to preserve the original behavior, apply this diff:

-	if len(mimeType) >= 5 && (mimeType[len(mimeType)-5:] == "+json" || mimeType[len(mimeType)-4:] == "+xml") {
+	if (len(mimeType) >= 5 && mimeType[len(mimeType)-5:] == "+json") || (len(mimeType) >= 4 && mimeType[len(mimeType)-4:] == "+xml") {
 		return true
 	}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
middleware/csrf/config.go (1)

5-5: Remove unused strings import to fix build failure

The strings import at line 5 is no longer used after switching to utils.EqualFold. Go treats unused imports as compilation errors and must be removed.

import (
	"fmt"
-	"strings"
	"time"

	"github.com/gofiber/fiber/v3"
	"github.com/gofiber/fiber/v3/extractors"
	"github.com/gofiber/fiber/v3/log"
	"github.com/gofiber/fiber/v3/middleware/session"
	"github.com/gofiber/utils/v2"
)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebfbc8b and 9e2d61a.

📒 Files selected for processing (5)
  • client/cookiejar.go (3 hunks)
  • ctx.go (2 hunks)
  • helpers.go (8 hunks)
  • middleware/csrf/config.go (1 hunks)
  • req.go (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ctx.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Prefer github.com/gofiber/utils/v2 helpers (for example, utils.Trim) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code

Files:

  • middleware/csrf/config.go
  • req.go
  • client/cookiejar.go
  • helpers.go
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: gofiber/fiber PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T15:07:23.885Z
Learning: Applies to **/*.go : Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code
📚 Learning: 2025-07-27T17:28:53.403Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3625
File: middleware/session/config.go:57-58
Timestamp: 2025-07-27T17:28:53.403Z
Learning: In the session middleware `Config` struct, the `Extractor` field uses function closures (like `FromCookie(key)`), making it impossible to introspect extractor parameters at runtime for validation purposes without complex reflection techniques.

Applied to files:

  • middleware/csrf/config.go
📚 Learning: 2024-09-25T15:57:10.221Z
Learnt from: sixcolors
Repo: gofiber/fiber PR: 3016
File: middleware/csrf/csrf_test.go:188-193
Timestamp: 2024-09-25T15:57:10.221Z
Learning: In the Fiber framework tests, using `ctx.Response.Header.Cookie` may not be suitable for parsing cookies from the response header, as it requires a `*Cookie` and fills it rather than returning a string value; thus, manual parsing of the `Set-Cookie` header may be necessary.

Applied to files:

  • req.go
🪛 GitHub Actions: Modernize Lint
middleware/csrf/config.go

[error] 5-5: "strings" imported and not used


[error] 5-5: Go build failed due to unused import while running: go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -test=false ./...

🪛 GitHub Actions: Run govulncheck
middleware/csrf/config.go

[error] 5-5: "strings" imported and not used

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (17)
middleware/csrf/config.go (1)

217-220: EqualFold change looks good and matches project utilities

Using utils.EqualFold here is consistent with the rest of the middleware and the guideline to prefer github.com/gofiber/utils/v2 helpers for string ops, while preserving the existing case‑insensitive warning behavior.

client/cookiejar.go (2)

56-56: LGTM! Usages are correct.

Both call sites correctly use the pre-allocated httpsScheme slice, eliminating inline allocations while preserving the original logic.

Also applies to: 218-218


21-22: LGTM! Good performance optimization.

Pre-allocating the httpsScheme byte slice eliminates repeated allocations at the comparison sites (lines 56 and 218), improving performance without changing behavior. The read-only usage pattern is thread-safe and appropriate for this performance-critical path.

helpers.go (8)

45-50: LGTM! Good performance optimization.

Preallocating byte slices for common header patterns avoids repeated allocations during header parsing.


218-218: LGTM! Addresses past review feedback.

The switch from strings.Contains to strings.IndexByte (as suggested in past review) improves performance. Using >= 0 instead of != -1 is equally performant and more idiomatic in Go.


320-327: LGTM! Safer MIME type parsing.

Using strings.Cut for splitting MIME types is more idiomatic and eliminates slice bounds concerns compared to manual Index + slicing.


524-524: LGTM! Efficient quality value parsing.

Using the preallocated semicolonQEquals byte slice with HasPrefix avoids repeated allocations in the hot path.


566-568: LGTM! Consistent use of preallocated byte slices.

Using preallocated wildcardAll and wildcardSuffix for wildcard checks maintains consistency with the optimization pattern and reduces allocations.


639-639: LGTM! More explicit weak ETag detection.

The explicit length and index checks are clear and perform the same validation as HasPrefix("W/") while being slightly more direct.


719-719: LGTM! Safer IPv6 bracket detection.

Adding the explicit raw != "" check before indexing prevents potential panics on empty input, though the function already returns early for empty strings at line 712.


736-736: LGTM! Optimized single-character search.

Using IndexByte for single-character searches is more efficient than Contains and aligns with the PR's optimization strategy.

req.go (6)

18-26: LGTM! Well-organized header constants.

Preallocating byte slices for frequently-checked header patterns reduces allocations in request parsing hot paths.


334-336: LGTM! Cleaner comma-separated host parsing.

Using strings.Cut to extract the first host from comma-separated X-Forwarded-Host values is more readable than manual index-based slicing.


507-509: LGTM! Cleaner Content-Type parameter stripping.

Using strings.Cut to separate the MIME type from parameters is more idiomatic than index-based slicing.


653-667: LGTM! Optimized scheme detection with preallocated byte slices.

The refactored scheme detection uses preallocated byte slices and strings.Cut for cleaner parsing of comma-separated proxy headers.


870-870: LGTM! Efficient IPv6 bracket detection.

The explicit length check and index comparison is more direct than HasPrefix/HasSuffix and clearly conveys the intent of detecting bracketed IPv6 addresses.


770-801: Range header parsing correctly uses strings.Cut for safer parsing.

The refactor properly handles:

  • Type/ranges separation on "=" with validation for multiple "=" characters
  • Comma-separated range segments parsing
  • Start/end bounds extraction with "-" delimiter

The code appropriately uses utils.ToLower() and utils.TrimSpace() from the utils package per the coding guidelines.

Recommend verifying test coverage exists for edge cases: multiple ranges (e.g., "bytes=0-100,200-300"), suffix ranges (e.g., "bytes=-500"), open-ended ranges (e.g., "bytes=500-"), and malformed inputs (e.g., "bytes==0-100").

@ReneWerner87 ReneWerner87 marked this pull request as draft December 8, 2025 10:59
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: ff190ff Previous: dd0b041 Ratio
Benchmark_Compress/Zstd - B/op 1 B/op 0 B/op +∞

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_CBORBinder_Bind-12               149.7n ± 3%   143.8n ± 4%  -3.94% (p=0.011 n=6)
_CookieBinder_Bind-12             1.634µ ± 7%   1.604µ ± 0%  -1.84% (p=0.002 n=6)
_FormBinder_Bind-12               1.634µ ± 2%   1.645µ ± 1%       ~ (p=0.567 n=6)
_FormBinder_BindMultipart-12      1.668µ ± 2%   1.654µ ± 5%       ~ (p=0.286 n=6)
_HeaderBinder_Bind-12             1.636µ ± 1%   1.626µ ± 1%       ~ (p=0.061 n=6)
_QueryBinder_Bind-12              1.611µ ± 2%   1.603µ ± 2%  -0.50% (p=0.037 n=6)
_RespHeaderBinder_Bind-12         1.711µ ± 1%   1.716µ ± 3%       ~ (p=0.318 n=6)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                                      │ client_old.txt │          client_new.txt           │
                                      │     sec/op     │   sec/op     vs base              │
_Client_Request-12                         5.487µ ± 1%   5.434µ ± 3%       ~ (p=0.310 n=6)
_Client_Request_Parallel-12                2.766µ ± 8%   2.747µ ± 8%       ~ (p=0.818 n=6)
_Client_Request_Send_ContextCancel-12      5.577µ ± 2%   5.550µ ± 1%       ~ (p=0.288 n=6)
geomean                                    4.390µ        4.359µ       -0.71%

                                      │ client_old.txt │          client_new.txt          │
                                      │      B/op      │    B/op     vs base              │
_Client_Request-12                          81.00 ± 1%   81.00 ± 0%       ~ (p=1.000 n=6)
_Client_Request_Parallel-12                 82.50 ± 3%   83.00 ± 2%       ~ (p=1.000 n=6)
_Client_Request_Send_ContextCancel-12       386.5 ± 2%   387.0 ± 3%       ~ (p=0.861 n=6)
geomean                                     137.2        137.5       +0.24%

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                               │ basicauth_old.txt │         basicauth_new.txt          │
                               │      sec/op       │    sec/op     vs base              │
_Middleware_BasicAuth-12              287.1n ± 10%   286.3n ±  2%       ~ (p=0.288 n=6)
_Middleware_BasicAuth_Upper-12        294.9n ±  4%   286.4n ± 13%       ~ (p=0.065 n=6)
geomean                               290.9n         286.4n        -1.57%

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                             │ cache_old.txt │           cache_new.txt           │
                             │    sec/op     │   sec/op     vs base              │
_Cache-12                       51.59µ ± 15%   50.60µ ± 9%       ~ (p=0.093 n=6)
_Cache_Miss-12                  56.45µ ±  5%   54.48µ ± 3%  -3.50% (p=0.009 n=6)
_Cache_Storage-12               50.83µ ±  5%   50.34µ ± 3%       ~ (p=0.240 n=6)
_Cache_AdditionalHeaders-12     100.2µ ± 17%   102.5µ ± 4%       ~ (p=0.065 n=6)
_Cache_MaxSize/Disabled-12      404.4n ±  1%   403.4n ± 1%       ~ (p=0.290 n=6)
_Cache_MaxSize/Unlim-12         404.2n ±  1%   403.4n ± 1%       ~ (p=0.225 n=6)
_Cache_MaxSize/LowBounded-12    404.7n ±  0%   403.5n ± 1%       ~ (p=0.223 n=6)

Copy link
Member Author

@ReneWerner87 ReneWerner87 Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                                                          │ compress_old.txt │           compress_new.txt           │
                                                          │      sec/op      │    sec/op      vs base               │
_Compress/Gzip-12                                               242.2n ±  7%    243.1n ±  2%        ~ (p=0.372 n=6)
_Compress/Deflate-12                                            238.4n ±  2%    243.9n ±  2%   +2.33% (p=0.002 n=6)
_Compress/Brotli-12                                             241.7n ±  2%    244.4n ±  1%        ~ (p=0.091 n=6)
_Compress/Zstd-12                                               240.1n ±  1%    245.2n ± 16%   +2.10% (p=0.002 n=6)
_Compress_Levels/Gzip_LevelDisabled-12                          81.57n ±  1%    83.42n ±  1%   +2.26% (p=0.009 n=6)
_Compress_Levels/Gzip_LevelDefault-12                           242.9n ±  1%    248.3n ±  6%   +2.24% (p=0.002 n=6)
_Compress_Levels/Gzip_LevelBestSpeed-12                         241.4n ±  1%    244.9n ±  0%   +1.45% (p=0.002 n=6)
_Compress_Levels/Gzip_LevelBestCompression-12                   242.8n ±  2%    245.0n ±  1%        ~ (p=0.065 n=6)
_Compress_Levels/Deflate_LevelDisabled-12                       81.33n ±  1%    82.15n ± 25%   +1.01% (p=0.011 n=6)
_Compress_Levels/Deflate_LevelDefault-12                        242.4n ±  1%    244.4n ±  1%   +0.80% (p=0.009 n=6)
_Compress_Levels/Deflate_LevelBestSpeed-12                      241.4n ±  1%    245.3n ±  1%   +1.66% (p=0.004 n=6)
_Compress_Levels/Deflate_LevelBestCompression-12                242.4n ±  1%    244.5n ±  0%   +0.85% (p=0.037 n=6)
_Compress_Levels/Brotli_LevelDisabled-12                        81.45n ±  1%    81.83n ±  0%        ~ (p=0.058 n=6)
_Compress_Levels/Brotli_LevelDefault-12                         242.7n ±  1%    243.1n ±  1%        ~ (p=0.455 n=6)
_Compress_Levels/Brotli_LevelBestSpeed-12                       247.4n ±  4%    244.3n ±  1%        ~ (p=0.126 n=6)
_Compress_Levels/Brotli_LevelBestCompression-12                 254.7n ±  5%    252.2n ±  0%        ~ (p=0.121 n=6)
_Compress_Levels/Zstd_LevelDisabled-12                          82.35n ±  3%    81.87n ±  2%        ~ (p=0.589 n=6)
_Compress_Levels/Zstd_LevelDefault-12                           242.7n ±  1%    244.4n ±  1%   +0.70% (p=0.030 n=6)
_Compress_Levels/Zstd_LevelBestSpeed-12                         243.5n ± 18%    247.4n ±  2%        ~ (p=0.223 n=6)
_Compress_Levels/Zstd_LevelBestCompression-12                   246.4n ±  2%    252.6n ± 13%   +2.50% (p=0.041 n=6)
_Compress_Parallel/Gzip-12                                      30.26n ±  4%    30.50n ±  8%        ~ (p=1.000 n=6)
_Compress_Parallel/Deflate-12                                   31.05n ±  6%    30.54n ±  5%        ~ (p=0.394 n=6)
_Compress_Parallel/Brotli-12                                    33.48n ± 14%    33.24n ± 17%        ~ (p=0.937 n=6)
_Compress_Parallel/Zstd-12                                      30.09n ± 17%    28.87n ±  5%        ~ (p=0.065 n=6)
_Compress_Levels_Parallel/Gzip_LevelDisabled-12                 10.41n ±  7%    10.08n ± 12%        ~ (p=0.310 n=6)
_Compress_Levels_Parallel/Gzip_LevelDefault-12                  29.41n ±  6%    30.11n ± 24%        ~ (p=0.240 n=6)
_Compress_Levels_Parallel/Gzip_LevelBestSpeed-12                28.93n ±  6%    29.46n ±  8%        ~ (p=0.589 n=6)
_Compress_Levels_Parallel/Gzip_LevelBestCompression-12          30.78n ± 22%    29.34n ±  8%        ~ (p=0.180 n=6)
_Compress_Levels_Parallel/Deflate_LevelDisabled-12              9.822n ±  5%   10.170n ±  9%        ~ (p=0.093 n=6)
_Compress_Levels_Parallel/Deflate_LevelDefault-12               29.77n ±  7%    31.03n ±  5%        ~ (p=0.180 n=6)
_Compress_Levels_Parallel/Deflate_LevelBestSpeed-12             28.65n ±  4%    33.85n ± 32%  +18.15% (p=0.009 n=6)
_Compress_Levels_Parallel/Deflate_LevelBestCompression-12       29.47n ±  6%    28.41n ±  5%        ~ (p=0.065 n=6)
_Compress_Levels_Parallel/Brotli_LevelDisabled-12               10.40n ±  4%    10.03n ±  5%        ~ (p=0.071 n=6)
_Compress_Levels_Parallel/Brotli_LevelDefault-12                29.21n ± 12%    29.02n ± 32%        ~ (p=0.699 n=6)
_Compress_Levels_Parallel/Brotli_LevelBestSpeed-12              29.35n ± 11%    29.85n ±  7%        ~ (p=1.000 n=6)
_Compress_Levels_Parallel/Brotli_LevelBestCompression-12        31.52n ± 10%    30.34n ±  7%        ~ (p=0.240 n=6)
_Compress_Levels_Parallel/Zstd_LevelDisabled-12                 10.54n ± 10%    10.29n ±  5%        ~ (p=0.240 n=6)
_Compress_Levels_Parallel/Zstd_LevelDefault-12                  29.39n ± 16%    29.87n ±  9%        ~ (p=0.937 n=6)
_Compress_Levels_Parallel/Zstd_LevelBestSpeed-12                28.84n ± 24%    28.46n ±  6%        ~ (p=0.485 n=6)
_Compress_Levels_Parallel/Zstd_LevelBestCompression-12          29.43n ±  4%    30.01n ± 10%        ~ (p=0.699 n=6)
geomean                                                         68.78n          69.20n         +0.60%
  • revert compress adjustement

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                                                  │ cors_old.txt │            cors_new.txt            │
                                                  │    sec/op    │    sec/op     vs base              │
_CORS_NewHandler-12                                  237.1n ± 6%   231.8n ±  1%  -2.21% (p=0.024 n=6)
_CORS_NewHandler_Parallel-12                         35.93n ± 5%   34.72n ±  7%       ~ (p=0.180 n=6)
_CORS_NewHandlerSingleOrigin-12                      239.8n ± 1%   232.0n ±  1%  -3.23% (p=0.002 n=6)
_CORS_NewHandlerSingleOrigin_Parallel-12             35.24n ± 8%   34.72n ±  5%       ~ (p=0.240 n=6)
_CORS_NewHandlerWildcard-12                          140.6n ± 1%   131.0n ±  1%  -6.83% (p=0.002 n=6)
_CORS_NewHandlerWildcard_Parallel-12                 16.74n ± 7%   15.74n ±  4%  -5.94% (p=0.041 n=6)
_CORS_NewHandlerPreflight-12                         641.2n ± 1%   639.5n ± 19%       ~ (p=1.000 n=6)
_CORS_NewHandlerPreflight_Parallel-12                117.6n ± 4%   117.9n ±  4%       ~ (p=0.669 n=6)
_CORS_NewHandlerPreflightSingleOrigin-12             643.8n ± 1%   632.2n ±  1%  -1.79% (p=0.002 n=6)
_CORS_NewHandlerPreflightSingleOrigin_Parallel-12    116.5n ± 1%   115.0n ±  1%       ~ (p=0.061 n=6)
_CORS_NewHandlerPreflightWildcard-12                 579.7n ± 1%   572.0n ±  1%  -1.33% (p=0.015 n=6)
_CORS_NewHandlerPreflightWildcard_Parallel-12        109.7n ± 7%   111.7n ±  3%       ~ (p=0.665 n=6)
_CORS_SubdomainMatch-12                              6.534n ± 0%   6.530n ±  2%       ~ (p=0.732 n=6)
geomean                                              111.2n        109.0n        -2.00%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants