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

Add service name prefixing logic to Swagger paths in SwaggerForOcelotMiddleware #311

Closed

Conversation

rabdulatif
Copy link
Contributor

@rabdulatif rabdulatif commented Oct 6, 2024

This PR introduces a new feature in the SwaggerForOcelotMiddleware where the serviceName is prefixed to the paths in the Swagger JSON at the beginning of the request processing.

New Method: Added the AddServiceNamePrefixToPaths method, which modifies the paths section in the Swagger JSON by prepending the specified serviceName to each path.
Middleware Change: An else block was added in the SwaggerForOcelotMiddleware to invoke the AddServiceNamePrefixToPaths method and apply the prefixing logic to paths.
Interface Modification: Updated ISwaggerJsonTransformer to include the AddServiceNamePrefixToPaths method, enabling easy transformation of Swagger paths with a service name prefix.

Why This Change is Needed
The ability to prepend a service name to Swagger paths is essential for better API routing and management, particularly in microservice-based architectures like Ocelot. This change ensures that the correct service name is added to each path, improving the clarity of the API documentation and routing

public string AddServiceNamePrefixToPaths(string swaggerJson, SwaggerEndPointOptions endPoint, string version)
    {
        var config = string.IsNullOrEmpty(version)
            ? endPoint.Config.FirstOrDefault()
            : endPoint.Config.FirstOrDefault(x => x.Version == version);

        var serviceName = config?.Service?.Name;
        if (string.IsNullOrEmpty(serviceName))
            return swaggerJson;

        var swaggerObj = JObject.Parse(swaggerJson);
        if (!swaggerObj.TryGetValue(OpenApiProperties.Paths, out var swaggerPaths))
            return swaggerJson;

        if (swaggerPaths is not JObject pathsObj)
            return swaggerJson;

        var properties = pathsObj.Properties().ToList();
        properties.ForEach(f => SetToPathServiceName(f, pathsObj, serviceName));

        return swaggerObj.ToString();
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="jProperty"></param>
    /// <param name="pathsObj"></param>
    /// <param name="serviceName"></param>
    private void SetToPathServiceName(JProperty jProperty, JObject pathsObj, string serviceName)
    {
        jProperty.Remove();

        var path = $"/{serviceName}{jProperty.Name}";
        pathsObj.Add(path, jProperty.Value);
    }```

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Release Notes

- **New Features**
	- Introduced a method to add service name prefixes to paths in Swagger JSON, enhancing configurability.
	- Improved middleware functionality for generating Swagger documentation based on service provider types.
	- Added a new extension method for safely parsing JSON strings.

- **Bug Fixes**
	- Enhanced test coverage for middleware functionalities, ensuring correct transformation and handling of Swagger JSON.

- **Documentation**
	- Updated tests to validate new transformation capabilities and middleware behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Copy link

update-docs bot commented Oct 6, 2024

Thanks for opening this pull request! If you have implemented new functions, write about them in the readme file.

Copy link

coderabbitai bot commented Oct 6, 2024

Walkthrough

The pull request introduces modifications to the SwaggerForOcelotMiddleware class, enhancing the Invoke method to handle different service provider types. A new conditional block processes Swagger JSON based on the ServiceProviderType. Additionally, the ISwaggerJsonTransformer interface is updated with a method for adding service name prefixes to paths in Swagger JSON. A new partial class for SwaggerJsonTransformer is created, implementing this functionality. Tests are also enhanced to validate the new transformations and middleware behaviors.

Changes

File Change Summary
src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs Modified Invoke method to include a new conditional block for handling service provider types and transforming Swagger JSON based on endPoint.TransformByOcelotConfig.
src/MMLib.SwaggerForOcelot/Transformation/ISwaggerJsonTransformer.cs Added new method AddServiceNamePrefixToPaths to the ISwaggerJsonTransformer interface for modifying Swagger JSON paths with a service name prefix.
src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs Introduced a partial class SwaggerJsonTransformer with method AddServiceNamePrefixToPaths that modifies Swagger JSON paths based on service name and version.
src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.cs Changed class declaration from public class SwaggerJsonTransformer to public partial class SwaggerJsonTransformer to allow modular implementation across multiple files.
tests/MMLib.SwaggerForOcelot.Tests/SwaggerForOcelotMiddlewareShould.cs Enhanced SwaggerForOcelotMiddlewareShould test class with new method AddServiceNamePrefixToPaths and additional test cases to validate the middleware's functionality and transformation capabilities.

Possibly related PRs

Suggested reviewers

  • Burgyn

Poem

🐇 In the meadow where the code does play,
A new prefix hops in, brightening the day.
Swagger paths adorned with names so neat,
Transformations dance, a developer's treat!
With tests that leap and bounds so wide,
Our middleware shines, with joy and pride! 🌼


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.

Copy link

@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: 4

🧹 Outside diff range and nitpick comments (6)
src/MMLib.SwaggerForOcelot/Transformation/ISwaggerJsonTransformer.cs (1)

25-37: LGTM with minor suggestions for improvement

The new method AddServiceNamePrefixToPaths is well-defined and properly integrated into the interface. The method name and parameters are appropriate for the task, and the documentation provides a clear description of its functionality.

However, there are a couple of minor improvements that could be made:

  1. The version parameter is not described in the XML documentation. Consider adding a description for this parameter to improve clarity.

  2. Consider using nullable reference types for the swaggerJson and version parameters if they can be null. This would improve type safety and make the method's behavior more explicit.

Here's a suggested improvement for the method signature and documentation:

/// <summary>
/// Modifies the paths in a given Swagger JSON by adding a specified service name as a prefix to each path.
/// If the "paths" section is missing or null, the method returns the original Swagger JSON without modifications.
/// </summary>
/// <param name="swaggerJson">The original Swagger JSON as a string.</param>
/// <param name="serviceName">The service name to be prefixed to each path in the Swagger JSON.</param>
/// <param name="version">The version of the service or API.</param>
/// <returns>
/// A modified Swagger JSON string where each path in the "paths" section is prefixed with the provided service name.
/// If the "paths" section does not exist or is null, the original Swagger JSON is returned.
/// </returns>
string AddServiceNamePrefixToPaths(string? swaggerJson, SwaggerEndPointOptions serviceName, string? version);
tests/MMLib.SwaggerForOcelot.Tests/SwaggerForOcelotMiddlewareShould.cs (1)

497-500: LGTM! Consider adding a comment for clarity.

The AddServiceNamePrefixToPaths method has been correctly added to the TestSwaggerJsonTransformer class, matching the ISwaggerJsonTransformer interface. The implementation is appropriate for a test double, always returning the predetermined _transformedJson.

Consider adding a comment to explain that this is a stub implementation for testing purposes:

 public string AddServiceNamePrefixToPaths(string swaggerJson,
     SwaggerEndPointOptions serviceName,
-    string version) => _transformedJson;
+    string version)
+ {
+    // Stub implementation for testing, always returns the predetermined transformed JSON
+    return _transformedJson;
+ }
src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs (3)

10-12: Provide meaningful summary for the class.

The class SwaggerJsonTransformer lacks a descriptive summary in the XML documentation. Providing a clear summary enhances understandability and maintainability.

Apply this diff to add a meaningful summary:

 /// <summary>
-///
+/// Provides methods to transform Swagger JSON documents, such as adding service name prefixes to paths.
 /// </summary>

49-54: Complete the XML documentation for the private method.

The method SetToPathServiceName lacks a meaningful summary and parameter descriptions in the XML documentation. Even for private methods, proper documentation aids in understanding and maintaining the code.

Apply this diff to enhance the documentation:

 /// <summary>
-///
+/// Modifies a path property by removing it and adding a new property with the service name prefixed.
 /// </summary>
-/// <param name="jProperty"></param>
-/// <param name="pathsObj"></param>
-/// <param name="serviceName"></param>
+/// <param name="jProperty">The original path property to modify.</param>
+/// <param name="pathsObj">The JSON object containing all path properties.</param>
+/// <param name="serviceName">The service name to prefix to each path.</param>

26-47: Add unit tests for AddServiceNamePrefixToPaths method.

The new method introduces important functionality that should be verified through unit tests. Testing various scenarios helps ensure the method behaves as expected.

Consider adding unit tests for the following cases:

  • Valid Swagger JSON with existing "paths" section.
  • Swagger JSON without a "paths" section.
  • Null or empty serviceName.
  • Invalid Swagger JSON input.
  • Different versions in endPoint.Config.

Would you like assistance in creating unit tests for this method?

src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs (1)

108-108: Remove unnecessary blank line before closing brace

There is an extra blank line before the closing brace at line 108~. According to the coding guidelines (SA1508), a closing brace should not be preceded by a blank line.

Apply this diff to remove the blank line:

-    
 }
🧰 Tools
🪛 GitHub Check: CodeFactor

[notice] 108-108: src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs#L108
A closing brace should not be preceded by a blank line. (SA1508)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 349e2dc and b3d41e6.

📒 Files selected for processing (5)
  • src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs (1 hunks)
  • src/MMLib.SwaggerForOcelot/Transformation/ISwaggerJsonTransformer.cs (1 hunks)
  • src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs (1 hunks)
  • src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.cs (1 hunks)
  • tests/MMLib.SwaggerForOcelot.Tests/SwaggerForOcelotMiddlewareShould.cs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.cs
🧰 Additional context used
🪛 GitHub Check: CodeFactor
src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs

[notice] 108-108: src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs#L108
A closing brace should not be preceded by a blank line. (SA1508)

🔇 Additional comments (1)
src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs (1)

32-34: ⚠️ Potential issue

Handle null endPoint.Config to prevent potential NullReferenceException.

If endPoint.Config is null, calling FirstOrDefault() may lead to a NullReferenceException. Consider adding a null check for endPoint.Config before attempting to access it.

Apply this diff to add a null check:

+ if (endPoint.Config == null)
+     return swaggerJson;
 
 var config = string.IsNullOrEmpty(version)
     ? endPoint.Config.FirstOrDefault()
     : endPoint.Config.FirstOrDefault(x => x.Version == version);

Likely invalid or redundant comment.

@rabdulatif rabdulatif closed this Oct 6, 2024
@rabdulatif rabdulatif reopened this Oct 6, 2024
Copy link

@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 (1)
src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs (1)

52-58: Add XML documentation for the SetToPathServiceName method

The SetToPathServiceName method lacks XML documentation. Adding documentation will improve code readability and maintainability.

Consider adding the following XML documentation:

/// <summary>
/// Sets the service name as a prefix to the given path in the Swagger JSON.
/// </summary>
/// <param name="jProperty">The JProperty representing the original path.</param>
/// <param name="pathsObj">The JObject containing all paths in the Swagger JSON.</param>
/// <param name="serviceName">The service name to be prefixed to the path.</param>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b3d41e6 and 9486732.

📒 Files selected for processing (2)
  • src/MMLib.SwaggerForOcelot/Extensions/JsonExtensions.cs (1 hunks)
  • src/MMLib.SwaggerForOcelot/Transformation/SwaggerJsonTransformer.Consul.cs (1 hunks)
🧰 Additional context used
🪛 GitHub Check: build-and-test
src/MMLib.SwaggerForOcelot/Extensions/JsonExtensions.cs

[warning] 24-24:
The variable 'ex' is declared but never used


[warning] 14-14:
XML comment has a param tag for 'obj', but there is no parameter by that name


[warning] 17-17:
Parameter 'jObj' has no matching param tag in the XML comment for 'JsonExtensions.TryParse(string, out JObject)' (but other parameters do)

🔇 Additional comments (2)
src/MMLib.SwaggerForOcelot/Extensions/JsonExtensions.cs (2)

1-9: LGTM: File structure and namespace are well-defined.

The file structure, using statements, and namespace declaration are appropriate and follow good practices.


1-30: Final thoughts on the implementation.

The JsonExtensions class and its TryParse method provide a useful utility for safely parsing JSON strings. With the suggested improvements, this implementation will be more robust and better documented.

As this is a new file in the project, ensure that it's being used appropriately in other parts of the codebase where JSON parsing is needed, particularly in the context of Swagger JSON processing for Ocelot.

🧰 Tools
🪛 GitHub Check: build-and-test

[warning] 24-24:
The variable 'ex' is declared but never used


[warning] 14-14:
XML comment has a param tag for 'obj', but there is no parameter by that name


[warning] 17-17:
Parameter 'jObj' has no matching param tag in the XML comment for 'JsonExtensions.TryParse(string, out JObject)' (but other parameters do)

@rabdulatif
Copy link
Contributor Author

#312

@rabdulatif rabdulatif closed this Oct 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant