Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥 feat: Add support for CBOR encoding #3173

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

imsk17
Copy link

@imsk17 imsk17 commented Oct 20, 2024

Description

Please provide a clear and concise description of the changes you've made and the problem they address. Include the purpose of the change, any relevant issues it solves, and the benefits it brings to the project. If this change introduces new features or adjustments, highlight them here.

Fixes #3156

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.

  • Benchmarks: Describe any performance benchmarks and improvements related to the changes.
  • Documentation Update: Detail the updates made to the documentation and links to the changed files.
  • Changelog/What's New: Include a summary of the additions for the upcoming release notes.
  • Migration Guide: If necessary, provide a guide or steps for users to migrate their existing code to accommodate these changes.
  • API Alignment with Express: Explain how the changes align with the Express API.
  • API Longevity: Discuss the steps taken to ensure that the new or updated APIs are consistent and not prone to breaking changes.
  • Examples: Provide examples demonstrating the new features or changes in action.

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • Enhancement (improvement to existing features and functionality)
  • Documentation update (changes to documentation)
  • Performance improvement (non-breaking change which improves efficiency)
  • Code consistency (non-breaking change which improves code reliability and robustness)

Checklist

Before you submit your pull request, please make sure you meet these requirements:

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

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

@imsk17 imsk17 requested a review from a team as a code owner October 20, 2024 22:16
@imsk17 imsk17 requested review from gaby, sixcolors, ReneWerner87 and efectn and removed request for a team October 20, 2024 22:16
Copy link
Contributor

coderabbitai bot commented Oct 20, 2024

Walkthrough

The changes in this pull request enhance the fiber package by adding support for CBOR (Concise Binary Object Representation) data serialization. Key modifications include the introduction of new configuration options for custom CBOR encoding and decoding, the addition of a CBOR method in the DefaultCtx struct for encoding data, and a new MIME type constant for CBOR. These updates provide users with more flexible data handling capabilities within the framework.

Changes

File Change Summary
app.go Added fields CBOREncoder and CBORDecoder to Config struct for custom CBOR handling.
constants.go Introduced new constant MIMEApplicationCBOR with value "application/cbor".
ctx.go, ctx_interface_gen.go, ctx_test.go Added CBOR method to DefaultCtx and Ctx interface for CBOR encoding, including error handling and tests.
bind.go, client/client.go, client/request.go, client/response.go Added methods for CBOR handling in Bind, Client, and Response structs, including serialization and deserialization capabilities.
middleware/cache/manager_msgp.go Modified DecodeMsg and UnmarshalMsg methods to initialize za0002 to an empty byte slice if nil.
docs/whats_new.md Updated to reflect changes in Fiber v3, including CBOR support and other framework enhancements.

Assessment against linked issues

Objective Addressed Explanation
Add support for CBOR codec
Implement CBOR serialization in context
Ensure CBOR handling aligns with RFC standards

Possibly related PRs

Suggested labels

🧹 Updates, 📒 Documentation

Suggested reviewers

  • sixcolors
  • gaby
  • ReneWerner87
  • efectn

Poem

🐰 In the land of code so bright,
CBOR hops in with delight.
New paths for data, oh what a sight,
With encoders and decoders, all feels right!
So let’s celebrate this joyful change,
In our framework, we’ll rearrange! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gaby gaby added the v3 label Oct 20, 2024
@gaby gaby added this to the v3 milestone Oct 20, 2024
@gaby gaby changed the title feat(cbor): allow encoding response bodies in cbor feat: Add support for CBOR encoding Oct 20, 2024
@gaby gaby changed the title feat: Add support for CBOR encoding 🔥 feat: Add support for CBOR encoding Oct 20, 2024
@gaby
Copy link
Member

gaby commented Oct 20, 2024

@imsk17 Thank you for the PR. Seems the tests are failing. The hex values dont match.

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

🧹 Outside diff range and nitpick comments (3)
ctx.go (2)

886-902: LGTM! Consider adding a brief comment.

The implementation of the CBOR method looks good. It follows the pattern of similar methods like JSON, handles errors appropriately, and allows for custom content types. The use of SetBodyRaw is efficient for setting the response body.

Consider adding a brief comment explaining the purpose of this method, similar to other methods in this file. For example:

// CBOR converts any interface or string to CBOR encoded bytes and sets it as the response body.
// If the ctype parameter is given, it sets the Content-Type header to the provided value.
// Otherwise, it sets the Content-Type header to "application/cbor".
func (c *DefaultCtx) CBOR(data any, ctype ...string) error {
    // ... (existing implementation)
}

Line range hint 1048-1066: Consider improving error handling in the JSON method

For consistency with the newly added CBOR method, consider updating the JSON method to return an error. This would allow for better error handling when JSON encoding fails.

Here's a suggested modification to the JSON method:

-func (c *DefaultCtx) JSON(data any, ctype ...string) error {
+func (c *DefaultCtx) JSON(data any, ctype ...string) error {
 	raw, err := c.app.config.JSONEncoder(data)
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to encode JSON: %w", err)
 	}
 	c.fasthttp.Response.SetBodyRaw(raw)
 	if len(ctype) > 0 {
 		c.fasthttp.Response.Header.SetContentType(ctype[0])
 	} else {
 		c.fasthttp.Response.Header.SetContentType(MIMEApplicationJSON)
 	}
 	return nil
 }

This change would make the error handling more informative and consistent with the new CBOR method.

app.go (1)

321-334: Ensure comments for CBOR encoder and decoder fields are clear and consistent

The comments for CBOREncoder and CBORDecoder in the Config struct could be improved for clarity and consistency with existing documentation comments. Consider revising the comments to match the style of other encoder/decoder fields.

Apply this diff to adjust the comments:

321,325c321,325
-	// When set by an external client of Fiber it will use the provided implementation of a
-	// CBORMarshal
-	//
-	// Allowing for flexibility in using another cbor library for encoding
-	// Default: cbor.Marshal
+	// When set by an external client of Fiber, it will use the provided implementation of a
+	// CBORMarshal.
+	//
+	// Allowing for flexibility in using another CBOR library for encoding.
+	// Default: cbor.Marshal

Similarly, adjust the comments for CBORDecoder:

328,333c328,333
-	// When set by an external client of Fiber it will use the provided implementation of a
-	// CBORUnmarshal
-	//
-	// Allowing for flexibility in using another cbor library for decoding
-	// Default: cbor.Unmarshal
+	// When set by an external client of Fiber, it will use the provided implementation of a
+	// CBORUnmarshal.
+	//
+	// Allowing for flexibility in using another CBOR library for decoding.
+	// Default: cbor.Unmarshal
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 298975a and 7f7fb38.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (6)
  • app.go (3 hunks)
  • constants.go (1 hunks)
  • ctx.go (1 hunks)
  • ctx_interface_gen.go (1 hunks)
  • ctx_test.go (2 hunks)
  • middleware/cache/manager_msgp.go (2 hunks)
🧰 Additional context used
🔇 Additional comments (14)
middleware/cache/manager_msgp.go (3)

55-57: Approve: Improved nil handling in headers map

This change enhances the robustness of the DecodeMsg method by ensuring that no nil values are stored in the headers map. By initializing nil byte slices to empty slices, it maintains consistency in the data structure and potentially prevents nil pointer dereferences in code that uses these headers. This is a good practice for handling potentially nil values.


273-275: Approve: Consistent nil handling in UnmarshalMsg

This change in the UnmarshalMsg method mirrors the improvement made in DecodeMsg. It ensures consistent handling of nil values across different serialization operations, maintaining data integrity and preventing potential issues with nil values in the headers map. This consistency is crucial and demonstrates a thorough approach to the nil-value handling enhancement.


55-57: Summary: Improved robustness in cache serialization

These changes enhance the reliability of the caching mechanism by ensuring consistent handling of nil values in the headers map during both decoding and unmarshaling operations. While not directly related to CBOR encoding, this improvement aligns with the PR's objective of enhancing data handling capabilities within the framework. It provides a more robust foundation for interacting with various data formats, including CBOR, by ensuring that the underlying data structures are always in a consistent state.

The nil-to-empty-slice conversion simplifies error handling for consumers of this cache data, as they can now assume that header values are always valid byte slices. This could lead to more predictable behavior and easier integration with new features like CBOR encoding.

While there might be a negligible performance impact due to the additional nil checks and potential memory allocations for empty slices, the benefits in terms of increased robustness and consistency outweigh this minor concern.

Also applies to: 273-275

constants.go (2)

26-26: LGTM: Correct MIME type constant for CBOR added

The addition of MIMEApplicationCBOR constant with the value "application/cbor" is correct and consistent with the existing MIME type constants in the file. This constant will be useful for setting the appropriate Content-Type header when sending CBOR-encoded responses.


26-26: Summary: Minimal, focused change for CBOR support

The addition of the MIMEApplicationCBOR constant is the only change in this file. It's a minimal and focused modification that supports the PR's objective of adding CBOR encoding capabilities. The change maintains backward compatibility and follows existing patterns in the codebase.

ctx_interface_gen.go (3)

166-170: New CBOR method added to Ctx interface

The addition of the CBOR method to the Ctx interface is consistent with the existing pattern for other data serialization methods like JSON and XML. This enhancement allows for encoding response bodies in CBOR format, which aligns with the PR objectives.

A few observations:

  1. The method signature CBOR(data any, ctype ...string) error is consistent with other serialization methods in the interface.
  2. The comment describes the functionality and default behavior for the Content-Type header, which is helpful for developers.

To ensure consistency across the codebase, let's verify the implementation of this method:

#!/bin/bash
# Search for the CBOR method implementation
rg -p 'func \(c \*DefaultCtx\) CBOR\(' --type go

Line range hint 1-170: Summary of changes to ctx_interface_gen.go

The changes to this file are minimal but significant:

  1. A new CBOR method has been added to the Ctx interface, enhancing the framework's serialization capabilities.
  2. The addition is consistent with existing patterns and doesn't break the interface contract.

Overall, this change successfully implements part of the PR's objective to allow encoding response bodies in CBOR format. The integration is clean and follows the established conventions of the fiber package.

To ensure full implementation:

Let's check for any related configuration options or utilities added for CBOR support:

#!/bin/bash
# Search for CBOR-related additions in other files
rg -p 'CBOR' --type go

Line range hint 1-170: Overall interface consistency and documentation considerations

The addition of the CBOR method to the Ctx interface is well-integrated and consistent with the existing design. It follows the same pattern as other serialization methods like JSON, JSONP, and XML.

Considerations:

  1. The interface remains backwards-compatible as the new method doesn't alter existing method signatures.
  2. The placement of the CBOR method alongside other serialization methods enhances discoverability for developers.

Consider updating the package documentation and examples to include usage of the new CBOR functionality. This will help developers understand how to utilize this new feature effectively.

Let's check if the documentation has been updated:

ctx.go (1)

Line range hint 1-3140: Overall, the changes look good with minor suggestions for improvement

The addition of the CBOR method to the DefaultCtx struct is well-implemented and consistent with the existing codebase. The suggested improvements (adding a comment to the CBOR method and updating the JSON method's error handling) would enhance the code's documentation and consistency.

No other significant issues were found in the surrounding code. The file maintains a good structure and follows consistent patterns throughout.

app.go (2)

26-26: Import statement added appropriately

The import of github.com/fxamacker/cbor/v2 is necessary to support CBOR encoding and decoding functionalities.


552-557: Default CBOR encoder and decoder are correctly initialized

The default CBOR encoder and decoder are properly set to cbor.Marshal and cbor.Unmarshal if they are not provided in the configuration, ensuring consistent behavior.

ctx_test.go (3)

15-15: Import of "encoding/hex" is appropriate

The addition of "encoding/hex" to the imports is necessary for encoding CBOR outputs to hex strings in the tests.


3576-3631: CBOR test functions are well implemented

The Test_Ctx_CBOR function provides comprehensive tests for the CBOR encoding functionality. It covers various cases including complex numbers, different data types, custom content types, empty values, and custom CBOR encoders. The tests are well-structured and follow existing patterns in the codebase.


3633-3655: Benchmark function for CBOR encoding is properly structured

The Benchmark_Ctx_CBOR function effectively measures the performance of CBOR encoding. It aligns with the standard benchmarking practices used in the codebase, ensuring consistency and reliability of benchmark results.

@imsk17
Copy link
Author

imsk17 commented Oct 20, 2024

Yea, I fixed that flaky test.

@gaby
Copy link
Member

gaby commented Oct 20, 2024

Yea, I fixed that flaky test.

Thanks! 💪

Copy link

codecov bot commented Oct 20, 2024

Codecov Report

Attention: Patch coverage is 47.54098% with 32 lines in your changes missing coverage. Please review.

Project coverage is 82.53%. Comparing base (7126e48) to head (a8192d1).

Files with missing lines Patch % Lines
client/hooks.go 0.00% 8 Missing ⚠️
middleware/cache/manager_msgp.go 0.00% 6 Missing ⚠️
client/client.go 58.33% 5 Missing ⚠️
binder/cbor.go 0.00% 4 Missing ⚠️
client/request.go 0.00% 4 Missing ⚠️
bind.go 57.14% 2 Missing and 1 partial ⚠️
client/response.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3173      +/-   ##
==========================================
- Coverage   82.76%   82.53%   -0.24%     
==========================================
  Files         114      115       +1     
  Lines       11149    11210      +61     
==========================================
+ Hits         9228     9252      +24     
- Misses       1521     1556      +35     
- Partials      400      402       +2     
Flag Coverage Δ
unittests 82.53% <47.54%> (-0.24%) ⬇️

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.

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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7f7fb38 and ea59267.

📒 Files selected for processing (1)
  • ctx_test.go (2 hunks)
🧰 Additional context used

ctx_test.go Show resolved Hide resolved
ctx_test.go Show resolved Hide resolved
@gaby
Copy link
Member

gaby commented Oct 20, 2024

@imsk17 Can you add a smalk section in https://github.com/gofiber/fiber/blob/main/docs/whats_new.md explaining the new feature. This will be used in the future to showcase Fiber v2 vs V3

Copy link
Member

@gaby gaby left a comment

Choose a reason for hiding this comment

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

👍 LGTM, just missing a section in "Whats_Change.md"

@imsk17
Copy link
Author

imsk17 commented Oct 20, 2024

Done.

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

🧹 Outside diff range and nitpick comments (5)
docs/whats_new.md (5)

199-200: Consider expanding the CBOR documentation

The introduction of CBOR support is a significant feature that aligns well with the PR objectives. To ensure users can fully leverage this new capability, consider expanding the documentation with:

  1. A brief explanation of what CBOR is and its benefits.
  2. An example of how to use the new CBOR method.
  3. Any performance considerations or best practices for using CBOR in Fiber.

This additional information would help users understand and adopt the new feature more easily.

Also applies to: 213-213


Line range hint 76-91: Enhance explanation of Router changes

The updates to the Router interface, particularly the changes to HTTP method registration and the new Route chaining, are significant improvements. To help users better understand and appreciate these changes, consider:

  1. Explaining the benefits of making the handler mandatory in the method signatures (e.g., improved type safety, clearer API).
  2. Providing a brief comparison of the old and new Route chaining syntax, highlighting how it improves code readability and maintainability.
  3. Adding a note on any potential breaking changes these updates might cause for existing codebases.

These additions would provide more context and help users understand why these changes were made and how they can benefit from them.

Also applies to: 96-102

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)


Line range hint 252-254: Expand the Client package section

The Client package rebuild seems to be a major update in Fiber v3. To give users a better understanding of these changes, consider:

  1. Listing a few key new features or improvements (e.g., Cookiejar, request/response hooks) with brief explanations.
  2. Providing a simple before-and-after code example to illustrate how the usage of the Client package has changed.
  3. Mentioning any performance improvements or changes in behavior that users should be aware of.

This additional information would help users quickly grasp the significance of the Client package updates and how they might affect their existing code.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)


Line range hint 321-326: Clarify middleware changes and migration steps

The updates to various middlewares represent significant changes in Fiber v3. To ensure a smooth transition for users, consider:

  1. For the Filesystem middleware removal:

    • Explain the rationale behind merging it into the Static middleware.
    • Provide a more detailed example of how to migrate from Filesystem to Static, covering common use cases.
  2. For the Monitor middleware move to Contrib:

    • Explain why this change was made (e.g., to keep the core lighter, to allow for more frequent updates).
    • Provide clear instructions on how to install and import the Contrib package.
  3. For other middleware updates (e.g., Adaptor, CORS):

    • Highlight any potential breaking changes.
    • Provide before-and-after examples for common configurations.

These additions would help users understand the impact of these changes and how to update their existing code effectively.

Also applies to: 410-416, 495-507

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)


Line range hint 509-515: Enhance the migration guide structure and content

The migration guide is a crucial resource for users upgrading to Fiber v3. To make it even more effective, consider the following improvements:

  1. Add a brief introduction explaining the scope of changes in v3 and who needs to pay attention to which sections.
  2. Include a "Quick Start" section for users with simpler applications, highlighting the most common and critical changes.
  3. For each major change, provide:
    • A brief explanation of why the change was made.
    • A complete before-and-after code example.
    • Any gotchas or common pitfalls to watch out for during migration.
  4. Add a "Troubleshooting" section addressing common issues users might encounter during the upgrade process.
  5. Consider adding a "Deprecation Timeline" for any features that are being phased out but not immediately removed in v3.

These enhancements would make the migration guide more user-friendly and comprehensive, helping to ensure a smoother transition for all Fiber users.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ea59267 and db00468.

📒 Files selected for processing (1)
  • docs/whats_new.md (2 hunks)
🧰 Additional context used
🔇 Additional comments (1)
docs/whats_new.md (1)

Line range hint 1-515: Overall, a comprehensive and well-structured document with room for enhancement

This "What's New in v3" document provides a thorough overview of the changes and improvements in Fiber v3. It covers a wide range of topics including app configuration, routing, context handling, client package updates, and middleware changes. The inclusion of a migration guide is particularly helpful for users upgrading from v2.

To further improve this document, consider:

  1. Expanding on new features like CBOR support with more detailed explanations and examples.
  2. Providing more context for significant changes, such as those in the Router interface, to help users understand the benefits and potential impacts.
  3. Enhancing the Client package section with more specific details about new features and improvements.
  4. Clarifying the middleware changes, particularly for removed or relocated middlewares, with more detailed migration instructions.
  5. Structuring the migration guide to be more user-friendly, including a quick start section, more comprehensive examples, and a troubleshooting guide.

These enhancements would make the document even more valuable for Fiber users, ensuring a smooth transition to v3 and helping them leverage all the new features and improvements effectively.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)

@gaby
Copy link
Member

gaby commented Oct 20, 2024

@imsk17 I found one more place CBOR is missing. In the bind/binder which have support for JSON and XML

See here:

@imsk17
Copy link
Author

imsk17 commented Oct 20, 2024

Right. I will have a look.

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

🧹 Outside diff range and nitpick comments (4)
docs/whats_new.md (4)

199-200: Enhance CBOR documentation with examples and configuration options.

The CBOR feature introduction would benefit from:

  1. Code examples showing usage
  2. Configuration options (if any)
  3. Performance characteristics compared to JSON/XML

Add a code example like this:

// Example CBOR usage
app.Get("/", func(c *fiber.Ctx) error {
    data := map[string]interface{}{
        "message": "Hello, World!",
        "number": 42,
    }
    return c.CBOR(data)
})

213-213: Cross-reference CBOR method in Context section.

The CBOR method listing should include a link to its detailed API documentation and mention any available configuration options.

Update the line to:

-CBOR -> for CBOR encoding
+CBOR -> for CBOR encoding (see [CBOR API documentation](./api/ctx.md#cbor))

Line range hint 1-24: Consider adding version compatibility matrix.

The introduction section would benefit from a clear compatibility matrix showing:

  1. Go version requirements
  2. Breaking changes overview
  3. Deprecation timeline for v2

Add a compatibility matrix like:

| Fiber Version | Go Version | Status      |
|--------------|------------|-------------|
| v3.x         | ≥ 1.22     | Current     |
| v2.x         | ≥ 1.17     | Maintenance |
🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)


Line range hint 12-24: Update table of contents to match actual content.

The table of contents is missing some sections that are present in the document:

  1. Drop for old Go versions
  2. Generic functions

Update the table of contents to include all sections and maintain consistent ordering with the document body.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between db00468 and 84c71a5.

📒 Files selected for processing (1)
  • docs/whats_new.md (2 hunks)
🔇 Additional comments (1)
docs/whats_new.md (1)

Line range hint 199-213: Verify CBOR implementation details in codebase.

Let's verify the CBOR implementation details to ensure documentation accuracy.

✅ Verification successful

CBOR implementation is properly documented and implemented

The documentation accurately reflects the CBOR implementation in the codebase. The verification shows:

  • CBOR is fully implemented using the github.com/fxamacker/cbor/v2 package
  • The implementation includes:
    • CBOR() method in the context with proper content type handling
    • Configurable CBOREncoder/CBORDecoder interfaces
    • Comprehensive test coverage in ctx_test.go
    • Default MIME type constant MIMEApplicationCBOR

The feature is well-tested, properly documented, and follows the same patterns as other response formats in the framework.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CBOR-related code
echo "Searching for CBOR method implementation..."
ast-grep --pattern 'func $_(c *fiber.Ctx) error {
  $$$
  c.CBOR($$$)
  $$$
}'

echo "Searching for CBOR tests..."
rg -l "TestCBOR" -g "**/*_test.go"

echo "Searching for CBOR configuration..."
rg "CBOR.*Config"

Length of output: 378


Script:

#!/bin/bash
# Let's try different search patterns to find CBOR implementation

# Search for CBOR-related files and functions
echo "Searching for CBOR in all files..."
rg -i "cbor" -A 5 -B 5

# Search for CBOR type or interface definitions
echo "Searching for CBOR type definitions..."
ast-grep --pattern 'type $_ struct {
  $$$
  CBOR $$$
  $$$
}'

# Search for CBOR method declarations
echo "Searching for CBOR method declarations..."
ast-grep --pattern 'func (c *Ctx) CBOR($$$) error'

# Look for imports of CBOR-related packages
echo "Searching for CBOR-related imports..."
rg "import.*cbor"

Length of output: 10999

🧰 Tools
🪛 LanguageTool

[uncategorized] ~203-~203: The official spelling of this programming framework is “Express.js”.
Context: ...ions. ### new methods - AutoFormat -> ExpressJs like - Host -> ExpressJs like - Port ->...

(NODE_JS)

@gaby
Copy link
Member

gaby commented Nov 6, 2024

@imsk17 Any updates on this?

@gaby gaby self-requested a review November 6, 2024 13:58
@imsk17
Copy link
Author

imsk17 commented Nov 6, 2024

Hi, Done with the tests.

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: 5

🧹 Outside diff range and nitpick comments (11)
binder/cbor.go (1)

1-15: Consider adding unit tests and documentation.

As this is a new binding implementation, please ensure:

  1. Add comprehensive unit tests covering both success and error cases
  2. Add godoc comments explaining the binding's purpose and usage
  3. Update the framework's documentation to include CBOR binding examples
  4. Consider adding benchmarks to compare with other binding implementations

Would you like me to help generate:

  1. Unit test cases?
  2. Documentation examples?
  3. Benchmark tests?
client/response.go (1)

78-81: Enhance method documentation for better clarity.

The implementation looks good and follows the established pattern of other unmarshal methods. Consider enhancing the documentation to provide more details about the CBOR unmarshaling process and any potential errors that might be returned.

-// CBOR method will unmarshal body to cbor.
+// CBOR method unmarshals the response body as CBOR into the given value.
+// It uses the client's CBOR unmarshaler to decode the response body.
+// Returns an error if the unmarshaling fails.
bind.go (1)

123-128: Add documentation and ensure test coverage.

Please consider the following improvements:

  1. Add documentation comments for the CBOR method explaining:
    • Purpose and usage
    • Any specific CBOR encoding considerations
    • Example usage if helpful
  2. Ensure comprehensive test coverage in bind_test.go:
    • Basic CBOR binding
    • Error cases
    • Performance benchmarks comparing with JSON

Example documentation:

+// CBOR binds CBOR-encoded body data into the provided struct.
+// The binding uses the application's configured CBORDecoder for custom decoding if provided.
 func (b *Bind) CBOR(out any) error {
client/hooks.go (1)

133-134: Consider setting Accept header for consistency

While the CBOR case correctly sets the Content-Type header, consider setting the Accept header to match the pattern used in the JSON case for consistency:

 case cborBody:
   req.RawRequest.Header.SetContentType(applicationCBOR)
+  req.RawRequest.Header.Set(headerAccept, applicationCBOR)
client/client.go (2)

155-175: Fix documentation comments referencing XML instead of CBOR

The documentation comments for CBOR methods incorrectly reference XML. This should be updated to maintain accuracy.

Update the comments as follows:

-// CBORMarshal returns xml marshal function in Core.
+// CBORMarshal returns CBOR marshal function in Core.

-// SetCBORMarshal Set xml encoder.
+// SetCBORMarshal Set CBOR encoder.

-// CBORUnmarshal returns xml unmarshal function in Core.
+// CBORUnmarshal returns CBOR unmarshal function in Core.

-// SetCBORUnmarshal Set xml decoder.
+// SetCBORUnmarshal Set CBOR decoder.

Line range hint 607-608: Consider adding CBOR support to Config struct

The Config struct and setConfigToRequest function currently default to JSON serialization for the Body field. Consider adding support for CBOR serialization to maintain consistency with the new CBOR functionality.

Consider adding a field to specify the serialization format:

 type Config struct {
     Body      any
+    // BodyFormat specifies the serialization format (e.g., "json", "xml", "cbor")
+    BodyFormat string
     // ... rest of the fields
 }

Then update setConfigToRequest:

 if cfg.Body != nil {
+    switch cfg.BodyFormat {
+    case "cbor":
+        req.SetCBOR(cfg.Body)
+    case "xml":
+        req.SetXML(cfg.Body)
+    default:
         req.SetJSON(cfg.Body)
+    }
     return
 }
client/request.go (2)

341-345: Add documentation comments for consistency.

Other methods in this file include documentation comments. Consider adding a comment to describe the CBOR functionality:

+// SetCBOR method sets CBOR body in request.
 func (r *Request) SetCBOR(v any) *Request {

341-345: LGTM! Consider adding validation for better error handling.

The implementation correctly follows the established pattern. However, consider adding validation to ensure the input can be properly encoded to CBOR:

 func (r *Request) SetCBOR(v any) *Request {
+    if v == nil {
+        return r
+    }
     r.body = v
     r.bodyType = cborBody
     return r
 }
bind_test.go (3)

15-15: Use an import alias for clarity

Consider adding an alias for the cbor package to improve code readability and avoid potential naming conflicts.

Apply this diff to add an import alias:

-	"github.com/fxamacker/cbor/v2"
+	cbor "github.com/fxamacker/cbor/v2"

1103-1131: Handle errors consistently in benchmarks

In the Benchmark_Bind_Body_CBOR function, consider using b.Fatalf instead of b.Error to halt the benchmark immediately if marshalling fails. This ensures that the benchmark does not continue running with invalid data.

Apply this diff for consistent error handling:

 body, err := cbor.Marshal(&Demo{Name: "john"})
 if err != nil {
-	b.Error(err)
+	b.Fatalf("Failed to marshal CBOR data: %v", err)
 }

1751-1760: Avoid duplicating error handling code

Extract the CBOR marshalling and error handling into a helper function to reduce code duplication and improve maintainability.

Create a helper function:

func marshalCBOR(t *testing.T, v interface{}) []byte {
	enc, err := cbor.Marshal(v)
	if err != nil {
		t.Fatal(err)
	}
	return enc
}

Modify your test code to use the helper function:

-	cb, err := cbor.Marshal(&Request{
+	cb := marshalCBOR(t, &Request{
 	BodyParam: "body_param",
-})
-if err != nil {
-	t.Error(err)
-}
+})

Update the call to testDecodeParser:

-	testDecodeParser(MIMEApplicationCBOR, string(cb))
+	testDecodeParser(MIMEApplicationCBOR, cb)

Ensure testDecodeParser accepts a byte slice:

-func testDecodeParser(contentType, body string) {
+func testDecodeParser(contentType string, body []byte) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 84c71a5 and ae8407c.

📒 Files selected for processing (9)
  • bind.go (2 hunks)
  • bind_test.go (4 hunks)
  • binder/binder.go (1 hunks)
  • binder/cbor.go (1 hunks)
  • client/client.go (2 hunks)
  • client/client_test.go (2 hunks)
  • client/hooks.go (3 hunks)
  • client/request.go (2 hunks)
  • client/response.go (1 hunks)
🔇 Additional comments (11)
binder/cbor.go (2)

7-7: LGTM! Clean type definition.

The empty struct is an appropriate choice for a stateless binding implementation.


13-15: 🛠️ Refactor suggestion

Consider adding input validation.

The Bind method directly passes the input to the decoder without any validation. Consider adding checks for:

  1. nil body
  2. empty body
  3. nil decoder function
  4. nil output parameter

Here's a suggested implementation:

func (*cborBinding) Bind(body []byte, cborDecoder utils.CBORUnmarshal, out any) error {
+	if len(body) == 0 {
+		return nil
+	}
+	if cborDecoder == nil {
+		return fmt.Errorf("cbor decoder is nil")
+	}
+	if out == nil {
+		return fmt.Errorf("output parameter is nil")
+	}
	return cborDecoder(body, out)
}
#!/bin/bash
# Description: Check how other binders handle validation
# Test: Look for similar validation patterns in other binders
rg -A 5 'func.*Bind.*\(.*\).*error' binder/
binder/binder.go (2)

23-23: LGTM! The CBORBinder addition follows the established pattern.

The new CBORBinder variable is correctly initialized and placed logically with other data format binders.


23-23: Verify the cborBinding type implementation.

Let's ensure the cborBinding type is properly implemented with the necessary methods.

client/response.go (1)

78-81: Verify client's CBOR unmarshal implementation.

The method relies on client.cborUnmarshal. Let's verify its implementation to ensure proper CBOR support.

✅ Verification successful

CBOR implementation is properly supported and configured

The codebase has comprehensive CBOR support with proper implementation:

  • The client uses fxamacker/cbor/v2 library for CBOR encoding/decoding
  • CBOR functionality is properly initialized in the client:
    • cborUnmarshal is a configurable field in the Client struct
    • Default CBOR decoder is set to cbor.Unmarshal if not explicitly configured
    • Custom CBOR decoder can be set via SetCBORUnmarshal method
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for the existence and implementation of cborUnmarshal in the Client struct

# Search for cborUnmarshal definition
echo "Searching for cborUnmarshal implementation..."
ast-grep --pattern 'func (c *Client) cborUnmarshal($_, $_) error'

# Search for CBOR-related imports
echo "Checking for CBOR-related imports..."
rg 'import.*cbor'

Length of output: 271


Script:

#!/bin/bash
# Let's try a broader search for CBOR-related code and implementations

# Search for any CBOR-related function definitions
echo "Searching for CBOR-related function implementations..."
ast-grep --pattern 'func $_($$$) $_($$$) {
  $$$
  cbor$$$
  $$$
}'

# Search for any CBOR usage in the codebase
echo "Searching for CBOR usage in the codebase..."
rg -i "cbor" -A 3

# Search for unmarshal-related functions in client
echo "Searching for unmarshal functions in client..."
fd -e go -x grep -l "unmarshal" {} \; | xargs rg "func.*[Uu]nmarshal"

Length of output: 12701

bind.go (2)

192-193: Verify CBOR MIME type constant definition.

The implementation correctly handles CBOR content type in the Body method.

Let's verify the MIME type constant:

#!/bin/bash
# Description: Verify CBOR MIME type constant definition and usage
# Expected: Should find MIMEApplicationCBOR constant definition with value "application/cbor"

# Search for MIMEApplicationCBOR constant definition
rg "MIMEApplicationCBOR.*=.*\"application/cbor\""

# Search for other usages of this constant
rg "MIMEApplicationCBOR"

123-128: Implementation looks good and follows established patterns.

The CBOR binding implementation correctly follows the same patterns as JSON and XML bindings, including proper error handling and struct validation.

Let's verify the CBORDecoder initialization:

✅ Verification successful

Based on the search results, I can now provide a final response since I have found sufficient evidence about the CBOR decoder initialization:

CBORDecoder is properly initialized with default implementation

The implementation is verified to be correct:

  • CBORDecoder is defined in the Config struct with type utils.CBORUnmarshal
  • Default initialization is handled in app.go: if app.config.CBORDecoder == nil { app.config.CBORDecoder = cbor.Unmarshal }
  • This follows the same pattern as other decoders (JSON, XML) in the framework
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CBORDecoder initialization in app.go
# Expected: Should find CBORDecoder initialization in Config struct and default configuration

# Search for CBORDecoder in Config struct and its initialization
rg -A 5 "CBORDecoder"

Length of output: 485


Script:

#!/bin/bash
# Let's search for CBORDecoder in the codebase
rg -A 5 "CBORDecoder"

# Also search for CBOR-related configuration
ast-grep --pattern 'type Config struct {
  $$$
  CBORDecoder $_ 
  $$$
}'

# Check for any default CBOR decoder initialization
rg -A 5 "func New|func Config"

Length of output: 35440

client/hooks.go (2)

26-26: LGTM: CBOR MIME type constant follows conventions

The applicationCBOR constant correctly uses the standard MIME type "application/cbor" as specified in RFC 8949 and follows the existing naming pattern.


195-200: Verify CBOR marshaling implementation

The CBOR case follows the established pattern for body parsing, but let's verify the implementation of the referenced cborMarshal function.

✅ Verification successful

Based on the search results, I can now generate the final response since I have found sufficient evidence about the CBOR implementation:

CBOR marshaling implementation is properly integrated

The codebase shows that CBOR support is well-implemented:

  • The cborMarshal function is available through the client's CBORMarshal() method
  • CBOR marshaling uses the github.com/fxamacker/cbor/v2 package
  • Default CBOR marshaling is set via c.config.CBOREncoder = cbor.Marshal
  • Content type is properly set to application/cbor
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of cborMarshal function
# Expected: Should find the implementation of cborMarshal in the client package

# Search for cborMarshal implementation
echo "Searching for cborMarshal implementation..."
rg -p "func.*cborMarshal" --type go

# Search for CBOR-related imports to verify the marshaling library
echo "Checking CBOR-related imports..."
rg "import.*cbor" --type go

Length of output: 239


Script:

#!/bin/bash
# Let's try a broader search for CBOR-related code and the cborMarshal method

# Search for any CBOR-related code
echo "Searching for any CBOR references..."
rg -i "cbor" --type go -A 5 -B 5

# Search for method definitions in the client struct
echo "Searching for client struct methods..."
ast-grep --pattern 'func (c *Client) $_($$$) $$$'

# Look for any marshal-related functions
echo "Searching for marshal-related functions..."
rg "func.*[Mm]arshal" --type go

Length of output: 39240

client/request.go (1)

37-37: LGTM! The new bodyType constant follows the established pattern.

The cborBody constant is correctly added to the bodyType enum, maintaining consistency with the existing implementation.

client/client_test.go (1)

6-6: LGTM!

The encoding/hex import is correctly placed and necessary for CBOR test cases.

binder/cbor.go Outdated
Comment on lines 9 to 11
func (*cborBinding) Name() string {
return "json"
}
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

Fix incorrect binding name.

The Name() method returns "json" which is incorrect for a CBOR binding. This could cause confusion and potential issues with binding selection.

Apply this fix:

func (*cborBinding) Name() string {
-	return "json"
+	return "cbor"
}
📝 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
func (*cborBinding) Name() string {
return "json"
}
func (*cborBinding) Name() string {
return "cbor"
}

Comment on lines +1 to +5
package binder

import (
"github.com/gofiber/utils/v2"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Additional imports are required for CBOR functionality

The current implementation is missing the required CBOR package import. Based on the codebase analysis:

  • The main CBOR functionality uses github.com/fxamacker/cbor/v2 as seen in app.go and bind_test.go
  • The implementation relies on utils.CBORUnmarshal type from gofiber/utils/v2, but the actual CBOR decoding is handled by the external CBOR package

Suggested changes:

  • Add github.com/fxamacker/cbor/v2 to the imports
🔗 Analysis chain

Verify if additional CBOR-related imports are needed.

The current implementation only imports utils/v2. Consider if we need to import any CBOR-specific packages or testing packages for unit tests.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for CBOR-related imports in other files
# Test: Look for CBOR-related imports across the codebase
rg -l 'import.*cbor' 

Length of output: 116


Script:

#!/bin/bash
# Let's try a more comprehensive search for CBOR-related code and imports
# First, let's find all files that might be related to CBOR
rg -i "cbor" --type go

# Also check the content of the cbor.go file to understand implementation
cat binder/cbor.go

Length of output: 5415

Comment on lines +47 to +48
cborMarshal utils.CBORMarshal
cborUnmarshal utils.CBORUnmarshal
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

Initialize CBOR marshal/unmarshal functions in New() constructor

The CBOR marshal/unmarshal fields are added but not initialized in the New() constructor, which could lead to nil pointer dereferences when these functions are called.

Add initialization in the New() constructor, similar to how JSON and XML functions are initialized:

 func New() *Client {
   return &Client{
     // ... existing initialization ...
     xmlMarshal:           xml.Marshal,
     xmlUnmarshal:         xml.Unmarshal,
+    cborMarshal:          utils.DefaultCBORMarshal,
+    cborUnmarshal:        utils.DefaultCBORUnmarshal,
     logger:               log.DefaultLogger(),
   }
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +206 to +231
t.Run("set cbor marshal", func(t *testing.T) {
t.Parallel()
bs, err := hex.DecodeString("f6")
if err != nil {
t.Error(err)
}
client := New().
SetCBORMarshal(func(_ any) ([]byte, error) {
return bs, nil
})
val, err := client.CBORMarshal()(nil)

require.NoError(t, err)
require.Equal(t, bs, val)
})

t.Run("set cbor marshal error", func(t *testing.T) {
t.Parallel()
client := New().SetCBORMarshal(func(_ any) ([]byte, error) {
return nil, errors.New("invalid struct")
})

val, err := client.CBORMarshal()(nil)
require.Nil(t, val)
require.Equal(t, errors.New("invalid struct"), err)
})
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance CBOR test coverage with more comprehensive test cases.

While the basic test structure is good, consider the following improvements:

  1. Add test cases with more complex CBOR data structures (e.g., maps, arrays, nested objects) to ensure proper encoding.
  2. Use a more specific error message in the error test case to indicate CBOR-specific issues.
  3. Add test cases that verify the actual CBOR encoding/decoding logic, not just the marshaling function plumbing.

Here's an example of a more comprehensive test case:

 t.Run("set cbor marshal", func(t *testing.T) {
     t.Parallel()
-    bs, err := hex.DecodeString("f6")
+    // Test complex CBOR data
+    // a2                                      # map(2)
+    //    63                                   # text(3)
+    //       666F6F                           # "foo"
+    //    63                                   # text(3)
+    //       626172                           # "bar"
+    //    65                                   # text(5)
+    //       76616C7565                       # "value"
+    //    82                                   # array(2)
+    //       01                                # unsigned(1)
+    //       02                                # unsigned(2)
+    bs, err := hex.DecodeString("a263666f6f63626172657661667565820102")
     if err != nil {
         t.Error(err)
     }
     client := New().
         SetCBORMarshal(func(_ any) ([]byte, error) {
             return bs, nil
         })
     val, err := client.CBORMarshal()(nil)

     require.NoError(t, err)
     require.Equal(t, bs, val)
 })

 t.Run("set cbor marshal error", func(t *testing.T) {
     t.Parallel()
     client := New().SetCBORMarshal(func(_ any) ([]byte, error) {
-        return nil, errors.New("invalid struct")
+        return nil, errors.New("cbor: cannot marshal cyclic structure")
     })

     val, err := client.CBORMarshal()(nil)
     require.Nil(t, val)
-    require.Equal(t, errors.New("invalid struct"), err)
+    require.Equal(t, errors.New("cbor: cannot marshal cyclic structure"), err)
 })

+t.Run("set cbor marshal with nested structures", func(t *testing.T) {
+    t.Parallel()
+    // Test nested map with array
+    // a1                                      # map(1)
+    //    63                                   # text(3)
+    //       6D6170                           # "map"
+    //    82                                   # array(2)
+    //       01                                # unsigned(1)
+    //       82                                # array(2)
+    //          02                             # unsigned(2)
+    //          03                             # unsigned(3)
+    bs, err := hex.DecodeString("a163636d617082018202")
+    if err != nil {
+        t.Error(err)
+    }
+    client := New().
+        SetCBORMarshal(func(_ any) ([]byte, error) {
+            return bs, nil
+        })
+    val, err := client.CBORMarshal()(nil)
+
+    require.NoError(t, err)
+    require.Equal(t, bs, val)
+})
📝 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
t.Run("set cbor marshal", func(t *testing.T) {
t.Parallel()
bs, err := hex.DecodeString("f6")
if err != nil {
t.Error(err)
}
client := New().
SetCBORMarshal(func(_ any) ([]byte, error) {
return bs, nil
})
val, err := client.CBORMarshal()(nil)
require.NoError(t, err)
require.Equal(t, bs, val)
})
t.Run("set cbor marshal error", func(t *testing.T) {
t.Parallel()
client := New().SetCBORMarshal(func(_ any) ([]byte, error) {
return nil, errors.New("invalid struct")
})
val, err := client.CBORMarshal()(nil)
require.Nil(t, val)
require.Equal(t, errors.New("invalid struct"), err)
})
t.Run("set cbor marshal", func(t *testing.T) {
t.Parallel()
// Test complex CBOR data
// a2 # map(2)
// 63 # text(3)
// 666F6F # "foo"
// 63 # text(3)
// 626172 # "bar"
// 65 # text(5)
// 76616C7565 # "value"
// 82 # array(2)
// 01 # unsigned(1)
// 02 # unsigned(2)
bs, err := hex.DecodeString("a263666f6f63626172657661667565820102")
if err != nil {
t.Error(err)
}
client := New().
SetCBORMarshal(func(_ any) ([]byte, error) {
return bs, nil
})
val, err := client.CBORMarshal()(nil)
require.NoError(t, err)
require.Equal(t, bs, val)
})
t.Run("set cbor marshal error", func(t *testing.T) {
t.Parallel()
client := New().SetCBORMarshal(func(_ any) ([]byte, error) {
return nil, errors.New("cbor: cannot marshal cyclic structure")
})
val, err := client.CBORMarshal()(nil)
require.Nil(t, val)
require.Equal(t, errors.New("cbor: cannot marshal cyclic structure"), err)
})
t.Run("set cbor marshal with nested structures", func(t *testing.T) {
t.Parallel()
// Test nested map with array
// a1 # map(1)
// 63 # text(3)
// 6D6170 # "map"
// 82 # array(2)
// 01 # unsigned(1)
// 82 # array(2)
// 02 # unsigned(2)
// 03 # unsigned(3)
bs, err := hex.DecodeString("a163636d617082018202")
if err != nil {
t.Error(err)
}
client := New().
SetCBORMarshal(func(_ any) ([]byte, error) {
return bs, nil
})
val, err := client.CBORMarshal()(nil)
require.NoError(t, err)
require.Equal(t, bs, val)
})

bind_test.go Outdated
Comment on lines 931 to 938
t.Run("CBOR", func(t *testing.T) {
enc, err := cbor.Marshal(&Demo{Name: "john"})
if err != nil {
t.Error(err)
}
str := string(enc)
testDecodeParser(t, MIMEApplicationCBOR, str)
})
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

Avoid converting CBOR binary data to a string

CBOR data is binary, and converting it to a string can lead to data corruption or unexpected behavior. Modify testDecodeParser to accept a byte slice instead of a string to handle binary data properly.

Refactor testDecodeParser to accept []byte for the body parameter:

-func testDecodeParser(t *testing.T, contentType, body string) {
+func testDecodeParser(t *testing.T, contentType string, body []byte) {
     t.Helper()
     c := app.AcquireCtx(&fasthttp.RequestCtx{})
     c.Request().Header.SetContentType(contentType)
-    c.Request().SetBody([]byte(body))
+    c.Request().SetBody(body)
     c.Request().Header.SetContentLength(len(body))
     d := new(Demo)
     require.NoError(t, c.Bind().Body(d))
     require.Equal(t, "john", d.Name)
 }

Update the test case to pass the byte slice directly:

-	str := string(enc)
-	testDecodeParser(t, MIMEApplicationCBOR, str)
+	testDecodeParser(t, MIMEApplicationCBOR, enc)
📝 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
t.Run("CBOR", func(t *testing.T) {
enc, err := cbor.Marshal(&Demo{Name: "john"})
if err != nil {
t.Error(err)
}
str := string(enc)
testDecodeParser(t, MIMEApplicationCBOR, str)
})
t.Run("CBOR", func(t *testing.T) {
enc, err := cbor.Marshal(&Demo{Name: "john"})
if err != nil {
t.Error(err)
}
testDecodeParser(t, MIMEApplicationCBOR, enc)
})

@gaby
Copy link
Member

gaby commented Nov 6, 2024

@imsk17 Can you fix the merge conflict with go.mod

There's a few issues raised by CodeRabbit. For ex in binder it returns JSON instead of cbor.

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

🧹 Outside diff range and nitpick comments (2)
ctx_test.go (2)

3619-3679: Consider expanding test coverage for CBOR encoding

The test cases look good but could be enhanced for more thorough coverage:

  1. Add test cases for complex nested structures and arrays
  2. Add test cases for all primitive types (bool, int8/16/32/64, uint8/16/32/64, float32/64)
  3. Add test cases for concurrent encoding to verify thread safety
  4. Add test cases for handling nil values in nested structures

Example test case for nested structure:

type NestedStruct struct {
    Name     string
    Age      int
    IsActive bool
    Tags     []string
    Metadata map[string]interface{}
}

data := NestedStruct{
    Name:     "John",
    Age:      30,
    IsActive: true,
    Tags:     []string{"user", "admin"},
    Metadata: map[string]interface{}{
        "lastLogin": time.Now(),
        "visits":    42,
    },
}
err := c.CBOR(data)

3681-3702: Consider enhancing benchmark coverage

The benchmark is good but could be expanded to:

  1. Add benchmarks for different payload sizes
  2. Add benchmarks comparing against JSON encoding
  3. Add parallel benchmarks to test concurrent performance
  4. Add benchmarks for custom encoder scenarios
func Benchmark_Ctx_CBOR_Parallel(b *testing.B) {
    app := New()
    data := SomeStruct{
        Name: "Grame",
        Age:  20,
    }
    b.RunParallel(func(pb *testing.PB) {
        c := app.AcquireCtx(&fasthttp.RequestCtx{})
        for pb.Next() {
            _ = c.CBOR(data)
        }
    })
}

func Benchmark_Ctx_CBOR_Large(b *testing.B) {
    app := New()
    c := app.AcquireCtx(&fasthttp.RequestCtx{})
    data := generateLargeStruct() // Generate large test data
    b.ReportAllocs()
    b.ResetTimer()
    for n := 0; n < b.N; n++ {
        _ = c.CBOR(data)
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ae8407c and 988fd26.

⛔ Files ignored due to path filters (1)
  • go.mod is excluded by !**/*.mod
📒 Files selected for processing (4)
  • app.go (3 hunks)
  • ctx.go (1 hunks)
  • ctx_interface_gen.go (1 hunks)
  • ctx_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • ctx.go
  • ctx_interface_gen.go
🔇 Additional comments (4)
app.go (4)

26-26: LGTM! Good choice of CBOR library.

The fxamacker/cbor library is a well-maintained and widely-used implementation of CBOR for Go.


321-334: LGTM! Well-structured Config additions.

The new CBOR configuration fields follow the established pattern of existing encoder/decoder fields. The documentation is clear and the types allow for custom implementations, maintaining flexibility.


552-557: LGTM! Proper initialization of CBOR encoders/decoders.

The default initialization follows the established pattern and uses appropriate default implementations from the CBOR library.


321-334: Verify complete CBOR integration across the framework.

While the core CBOR support is well implemented, ensure that CBOR handling is consistently implemented across all necessary components.

Also applies to: 552-557

✅ Verification successful

CBOR integration is complete and well-implemented across the framework

The verification shows comprehensive CBOR support across all necessary components:

  • CBOR binding implementation exists in binder/cbor.go
  • CBOR binding method is properly integrated in bind.go
  • CBOR response method is available in ctx.go
  • CBOR support is present in client components
  • The implementation follows the same pattern as other formats (JSON, XML) with consistent integration across binding, context, and client layers

The framework provides complete CBOR support with proper integration across all required components, matching the implementation pattern of other supported formats.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential missing CBOR implementations in related files

# Test 1: Check for files that handle JSON/XML but might be missing CBOR
echo "Files that might need CBOR support:"
rg -l "func.*JSON|func.*XML" | grep -v "app.go"

# Test 2: Specifically check bind/binder files as mentioned in PR comments
echo -e "\nChecking bind/binder files:"
rg -l "JSON|XML" bind/

Length of output: 479


Script:

#!/bin/bash
# Let's analyze the CBOR integration more thoroughly

# Check for CBOR-related code in bind and binder directories
echo "=== Checking CBOR implementations ==="
rg -l "CBOR"

# Check specific binding implementations
echo -e "\n=== Checking binder implementations ==="
fd -t f ".*\\.go$" binder/

# Look for content in bind.go to understand current binding mechanisms
echo -e "\n=== Analyzing bind.go content ==="
rg "func.*Bind|type.*Binder" bind.go -A 5

# Check ctx.go for CBOR-related methods
echo -e "\n=== Checking ctx.go for CBOR methods ==="
rg "func.*CBOR" ctx.go

Length of output: 3804

Comment on lines +3625 to +3626
require.Error(t, c.CBOR(complex(1, 1)))

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling test coverage

The error test for complex numbers is good, but should be expanded to cover more error cases:

  1. Test encoding of channels (should error)
  2. Test encoding of functions (should error)
  3. Test encoding of recursive structures (should error)
  4. Test encoding of very large numbers that may overflow
// Test invalid types
err = c.CBOR(make(chan int))
require.Error(t, err)

err = c.CBOR(func() {})
require.Error(t, err)

// Test recursive struct
type Recursive struct {
    Next *Recursive
}
r := &Recursive{}
r.Next = r
err = c.CBOR(r)
require.Error(t, err)

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

🧹 Outside diff range and nitpick comments (3)
client/client.go (2)

156-176: Fix method documentation to correctly reference CBOR.

The comments incorrectly reference "xml" instead of "cbor". Please update the documentation:

-// CBORMarshal returns xml marshal function in Core.
+// CBORMarshal returns CBOR marshal function in Core.

-// SetCBORMarshal Set xml encoder.
+// SetCBORMarshal sets the CBOR encoder.

-// CBORUnmarshal returns xml unmarshal function in Core.
+// CBORUnmarshal returns CBOR unmarshal function in Core.

-// SetCBORUnmarshal Set xml decoder.
+// SetCBORUnmarshal sets the CBOR decoder.

726-727: Consider enhancing Config struct for CBOR support.

The current implementation allows setting CBOR functions but doesn't provide a way to specify CBOR as the preferred encoding in the Config struct. Consider:

  1. Adding a ContentType field to Config to allow specifying the encoding (JSON/XML/CBOR)
  2. Updating setConfigToRequest to handle CBOR encoding when specified

This would make CBOR support more accessible in the convenient request methods (Get, Post, etc.).

bind_test.go (1)

1102-1129: Consider using CBOR-specific struct tags

While the benchmark is well-implemented, consider using CBOR-specific struct tags for better clarity and to ensure CBOR-specific features can be utilized if needed in the future.

 type Demo struct {
-    Name string `json:"name"`
+    Name string `cbor:"name" json:"name"`
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 988fd26 and a8192d1.

⛔ Files ignored due to path filters (1)
  • go.mod is excluded by !**/*.mod
📒 Files selected for processing (3)
  • bind_test.go (4 hunks)
  • binder/cbor.go (1 hunks)
  • client/client.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • binder/cbor.go
🔇 Additional comments (4)
client/client.go (2)

16-16: LGTM! Good choice of CBOR library and consistent field naming.

The fxamacker/cbor library is a solid choice as it's well-maintained, security-focused, and widely adopted. The new fields follow the established pattern used for JSON and XML.

Also applies to: 48-49


726-727: LGTM! Proper initialization of CBOR functions.

The CBOR marshal/unmarshal functions are correctly initialized in the New() constructor, following the same pattern as JSON and XML.

bind_test.go (2)

15-15: LGTM: Import of CBOR library

The chosen CBOR library (fxamacker/cbor) is a well-maintained and secure implementation.


931-936: LGTM: CBOR test case implementation

The test case properly validates CBOR encoding and decoding, following the same pattern as other encoding tests.

Comment on lines +1750 to +1759
cb, err := cbor.Marshal(&Request{
BodyParam: "body_param",
})
if err != nil {
t.Error(err)
}

testDecodeParser(MIMEApplicationJSON, `{"body_param":"body_param"}`)
testDecodeParser(MIMEApplicationXML, `<Demo><body_param>body_param</body_param></Demo>`)
testDecodeParser(MIMEApplicationCBOR, string(cb))
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

Fix potential binary data corruption

Converting CBOR binary data to string and back could lead to data corruption. The testDecodeParser function should be used with the raw byte slice.

-    testDecodeParser(MIMEApplicationCBOR, string(cb))
+    testDecodeParser(MIMEApplicationCBOR, cb)
📝 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
cb, err := cbor.Marshal(&Request{
BodyParam: "body_param",
})
if err != nil {
t.Error(err)
}
testDecodeParser(MIMEApplicationJSON, `{"body_param":"body_param"}`)
testDecodeParser(MIMEApplicationXML, `<Demo><body_param>body_param</body_param></Demo>`)
testDecodeParser(MIMEApplicationCBOR, string(cb))
cb, err := cbor.Marshal(&Request{
BodyParam: "body_param",
})
if err != nil {
t.Error(err)
}
testDecodeParser(MIMEApplicationJSON, `{"body_param":"body_param"}`)
testDecodeParser(MIMEApplicationXML, `<Demo><body_param>body_param</body_param></Demo>`)
testDecodeParser(MIMEApplicationCBOR, cb)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

📝 [Proposal]: Add support for CBOR codec
3 participants