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

refactor(server/v2): auto-gateway improvements #23262

Merged
merged 35 commits into from
Jan 13, 2025

Conversation

technicallyty
Copy link
Contributor

@technicallyty technicallyty commented Jan 9, 2025

Description

ref: #23188

  • adds doc.go to explain behavior and impl
  • introduces new type matcher to handle URI matching logic, and hold the data required for matching.
  • changes server to pre-generate the regexp matchers upfront, instead of each query request.
  • completely overhauls the proto message unmarshaling logic, using the same underlying code that gateway handlers use.
  • added a warning log when duplicate http annotations are found.

Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

Please see Pull Request Reviewer section in the contributing guide for more information on how to review a pull request.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a custom HTTP multiplexer for gRPC gateway requests.
    • Enhanced routing capabilities with wildcard and catch-all endpoint support.
    • Added ability to specify query height via custom header.
  • Improvements

    • Refined request matching using regular expressions.
    • Improved error handling for HTTP requests.
    • Streamlined message creation for GET and POST requests.
    • Updated expected outputs in system tests for error handling of invalid heights.
  • Testing

    • Added comprehensive unit tests for new routing and message creation functionality.
    • Updated tests to focus on URI pattern matching with wildcards.
    • Modified system test cases for GRPC supply endpoint to handle larger block height increments.

Copy link
Contributor

coderabbitai bot commented Jan 9, 2025

📝 Walkthrough

Walkthrough

The pull request introduces a new package grpcgateway, which provides a custom HTTP multiplexer designed for routing gRPC gateway requests. This package supports both POST requests with JSON bodies and GET requests with query parameters, including wildcard and catch-all endpoints. The URL matching mechanism utilizes regular expressions derived from HTTP annotations for routing, and it allows specifying a query height via the x-cosmos-block-height header. Additionally, the changes include enhancements in error handling and the introduction of unit tests to validate the new functionality.

Changes

File Change Summary
server/v2/api/grpcgateway/doc.go Added new package documentation for grpcgateway
server/v2/api/grpcgateway/interceptor.go - Introduced queryMetadata struct
- Updated gatewayInterceptor with regex-based mapping
- Added methods for creating messages from GET and POST requests
- Implemented createRegexMapping utility function
- Defined MaxBodySize constant
server/v2/api/grpcgateway/interceptor_test.go - Added comprehensive unit tests for message creation
- Introduced test types like DummyProto, Pagination, and Nested
- Created test cases for regex mapping and request handling
server/v2/api/grpcgateway/uri.go - Simplified URL matching logic
- Removed HasParams method
- Deleted createMessageFromJSON and createMessage functions
- Updated matchURL function to use regex-based matching
server/v2/api/grpcgateway/uri_test.go - Removed old URI matching tests
- Added Test_patternToRegex for new matching strategy
- Streamlined test suite
tests/systemtests/bank_test.go Updated test to expect a larger block height increment for bad request validation
server/v2/api/grpcgateway/server.go Updated comment for clarity regarding WithIncomingHeaderMatcher option
tests/systemtests/distribution_test.go Consolidated expected outputs for invalid height scenarios in tests

Possibly related PRs

Suggested reviewers

  • kocubinski
  • julienrbrt
  • testinginprod
  • tac0turtle
  • lucaslopezf
  • facundomedica

Finishing Touches

  • 📝 Generate Docstrings (Beta)

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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

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.

@github-actions github-actions bot added C:server/v2 Issues related to server/v2 C:server/v2 api labels Jan 9, 2025
server/v2/api/grpcgateway/interceptor.go Dismissed Show dismissed Hide dismissed
@bearycool11

This comment was marked as spam.

server/v2/api/grpcgateway/interceptor.go Dismissed Show dismissed Hide dismissed
@technicallyty technicallyty marked this pull request as ready for review January 10, 2025 23:41
@technicallyty technicallyty requested review from julienrbrt and a team as code owners January 10, 2025 23:41
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

🔭 Outside diff range comments (1)
server/v2/api/grpcgateway/uri.go (1)

Line range hint 9-9: Remove unused constant maxBodySize

The constant maxBodySize declared at line 9 is unused in the code. Unused constants can clutter the codebase and should be removed for better maintainability.

Apply this diff to remove the unused constant:

-const maxBodySize = 1 << 20 // 1 MB
♻️ Duplicate comments (2)
server/v2/api/grpcgateway/uri.go (1)

28-43: ⚠️ Potential issue

Potential non-determinism in map iteration

Iterating over maps in Go does not guarantee the order of iteration. In the loop over regexpToQueryMetadata, the order in which regex patterns are matched could be non-deterministic, potentially leading to inconsistent behavior if multiple patterns can match the same URI.

Consider converting regexpToQueryMetadata to a slice of structs containing the regex and metadata, and iterate over it in a deterministic order.

server/v2/api/grpcgateway/interceptor.go (1)

219-235: ⚠️ Potential issue

Potential non-determinism in map iteration

Iterating over the annotationMapping map does not guarantee order, which could lead to inconsistent regex pattern matching.

Consider converting annotationMapping to a slice of key-value pairs and iterating over it to ensure deterministic behavior.

🧹 Nitpick comments (7)
server/v2/api/grpcgateway/uri_test.go (2)

5-6: Avoid using os.Stdout for logging in tests

Using os.Stdout for logging in tests can clutter the test output and make it harder to read the results. It is better to discard the logger output or use a testing logger.

Apply this diff to use io.Discard:

+	"io"

...

-	logger := log.NewLogger(os.Stdout)
+	logger := log.NewLogger(io.Discard)

Also applies to: 71-71


77-77: Remove unnecessary error check

The err variable is not modified after the previous check, making require.NoError(t, err) redundant at line 77. This can be safely removed.

Apply this diff to remove the redundant error check:

-			require.NoError(t, err)
server/v2/api/grpcgateway/interceptor.go (1)

91-93: Minimize use of reflect for message instantiation

Using reflect to instantiate messages can lead to performance overhead. Consider using generated constructors or factory methods if available to avoid reflection.

server/v2/api/grpcgateway/doc.go (1)

1-11: Enhance package documentation with examples and implementation details.

While the documentation provides a good overview, consider adding:

  1. Example request formats for both POST and GET scenarios
  2. Details about error handling and status codes
  3. Documentation about regex pattern construction and performance implications
  4. Examples of how to use the x-cosmos-block-height header

Add examples like:

// Example GET request with query parameters:
// GET /cosmos/bank/v1beta1/balances/{address}?pagination.limit=10
//
// Example POST request with JSON body:
// POST /cosmos/bank/v1beta1/send_enabled
// {
//   "denoms": ["atom", "osmo"]
// }
//
// Example request with block height:
// GET /cosmos/bank/v1beta1/balances/{address}
// x-cosmos-block-height: 1234567
server/v2/api/grpcgateway/interceptor_test.go (3)

60-165: Consider adding more edge cases to GET request tests.

While the current test coverage is good, consider adding:

  1. Test case for very long query parameters
  2. Test case for special characters in wildcards
  3. Test case for multiple nested pagination levels
  4. Test case for empty string values

Add test cases like:

{
    name: "long query params and special characters",
    request: func() *http.Request {
        return httptest.NewRequest(
            http.MethodGet,
            "/dummy?foo=" + strings.Repeat("x", 2048) + "&special=!@#$%",
            nil,
        )
    },
    wildcardValues: map[string]string{
        "path": "value/with/slashes",
    },
    expected: &DummyProto{...},
    wantErr: false,
},

167-261: Enhance POST request test coverage.

Consider adding test cases for:

  1. Very large JSON payloads
  2. Malformed nested structures
  3. Invalid field types (e.g., string where number expected)
  4. Unicode characters in strings

Add test cases like:

{
    name: "invalid field types",
    body: map[string]any{
        "baz": "not_an_int32",  // should be int32
        "bar": "not_a_bool",    // should be bool
    },
    wantErr: true,
    errCode: codes.InvalidArgument,
},

266-301: Improve test type implementations.

The current implementations of Reset(), String(), and ProtoMessage() are minimal. Consider:

  1. Implementing proper Reset() to clear all fields
  2. Implementing meaningful String() for debugging
  3. Adding proper struct field documentation

Example improvements:

 func (n Nested) Reset() {
-    // Empty implementation
+    n.Foo = 0
 }

 func (n Nested) String() string {
-    return ""
+    return fmt.Sprintf("Nested{Foo: %d}", n.Foo)
 }
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1a4c9a and b0aff3e.

📒 Files selected for processing (5)
  • server/v2/api/grpcgateway/doc.go (1 hunks)
  • server/v2/api/grpcgateway/interceptor.go (5 hunks)
  • server/v2/api/grpcgateway/interceptor_test.go (1 hunks)
  • server/v2/api/grpcgateway/uri.go (1 hunks)
  • server/v2/api/grpcgateway/uri_test.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
server/v2/api/grpcgateway/doc.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

server/v2/api/grpcgateway/uri.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

server/v2/api/grpcgateway/uri_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

server/v2/api/grpcgateway/interceptor.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

server/v2/api/grpcgateway/interceptor_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

🪛 GitHub Actions: Lint
server/v2/api/grpcgateway/uri.go

[error] 9-9: const 'maxBodySize' is unused

🪛 golangci-lint (1.62.2)
server/v2/api/grpcgateway/interceptor.go

103-103: SA4006: this value of err is never used

(staticcheck)


105-105: SA4006: this value of err is never used

(staticcheck)


143-143: comparing with != will fail on wrapped errors. Use errors.Is to check for a specific error

(errorlint)

⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: tests (03)
  • GitHub Check: tests (02)
  • GitHub Check: tests (00)
  • GitHub Check: test-simapp-v2
  • GitHub Check: test-integration
  • GitHub Check: build (amd64)
  • GitHub Check: test-system-v2
  • GitHub Check: Analyze
  • GitHub Check: Summary
🔇 Additional comments (3)
server/v2/api/grpcgateway/uri.go (1)

16-18: Addition of Params field enhances URI matching

The introduction of the Params field in the uriMatch struct improves the handling of wildcard parameters in URIs, making the matching process more robust.

server/v2/api/grpcgateway/uri_test.go (1)

84-145: Comprehensive addition of Test_patternToRegex function

The new Test_patternToRegex function thoroughly tests the patternToRegex function with various cases, ensuring reliability and correctness in URI pattern conversion.

server/v2/api/grpcgateway/interceptor_test.go (1)

21-58: Test coverage for regex mapping looks good.

The test cases effectively cover:

  • Empty annotations
  • Different annotations
  • Duplicate annotations with warning validation

server/v2/api/grpcgateway/interceptor.go Outdated Show resolved Hide resolved
server/v2/api/grpcgateway/interceptor.go Outdated Show resolved Hide resolved
server/v2/api/grpcgateway/interceptor.go Outdated Show resolved Hide resolved
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 (3)
server/v2/api/grpcgateway/uri.go (1)

Line range hint 49-71: Optimize regex compilation and enhance documentation

The function uses regex patterns that could be pre-compiled as package-level variables for better performance. Additionally, the function would benefit from more detailed documentation about the supported wildcard patterns.

Consider these improvements:

+// Pre-compiled regex patterns
+var (
+    catchAllPattern = regexp.MustCompile(`\\\{([^}]+?)=\\\*\\\*\\}`)
+    wildcardPattern = regexp.MustCompile(`\\\{([^}]+)\\}`)
+    namePattern    = regexp.MustCompile(`\\\{(.+?)=`)
+)
+
+// patternToRegex converts a URI pattern with wildcards to a regex pattern.
+// Supports two types of wildcards:
+// 1. Catch-all wildcards: {param=**} matches any number of path segments
+// 2. Simple wildcards: {param} matches a single path segment
+//
+// Example:
+//   - Pattern: "/users/{id}/posts/{post=**}"
+//   - Matches: "/users/123/posts/2023/comments"
+//   - Returns: ("^/users/([^/]+)/posts/(.+)$", ["id", "post"])
 func patternToRegex(pattern string) (string, []string) {
server/v2/api/grpcgateway/interceptor.go (2)

Line range hint 76-141: Consider breaking down the large method into smaller functions

The ServeHTTP method is quite long and handles multiple responsibilities. Consider extracting the message creation and response handling logic into separate methods for better maintainability.

Consider breaking it down into:

  1. handleGetRequest
  2. handlePostRequest
  3. handleResponse

Example for handleResponse:

func (g *gatewayInterceptor[T]) handleResponse(ctx context.Context, writer http.ResponseWriter, request *http.Request, responseMsg gogoproto.Message, err error) {
    if err != nil {
        if strings.Contains(err.Error(), "no handler") {
            g.gateway.ServeHTTP(writer, request)
        } else {
            runtime.DefaultHTTPProtoErrorHandler(ctx, g.gateway, out, writer, request, err)
        }
        return
    }
    runtime.ForwardResponseMessage(ctx, g.gateway, out, writer, request, responseMsg)
}

222-243: Consider stricter handling of duplicate patterns

While the current implementation logs a warning for duplicate patterns (referencing issue #23281), consider maintaining a list of known/allowed duplicates to distinguish between expected and unexpected duplicates.

Example implementation:

+var allowedDuplicatePatterns = map[string]struct{}{
+    "/cosmos/bank/v1beta1/balances/{address}": {}, // Known duplicate from issue #23281
+}

 func createRegexMapping(logger log.Logger, annotationMapping map[string]string) map[*regexp.Regexp]queryMetadata {
     // ...
     if otherAnnotation, ok := seenPatterns[pattern]; !ok {
         seenPatterns[pattern] = annotation
     } else {
+        if _, allowed := allowedDuplicatePatterns[annotation]; !allowed {
             logger.Warn("duplicate HTTP annotation found", "annotation1", annotation, "annotation2", otherAnnotation, "query_input_name", queryInputName)
+        }
     }
     // ...
 }
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0aff3e and 8813640.

📒 Files selected for processing (2)
  • server/v2/api/grpcgateway/interceptor.go (5 hunks)
  • server/v2/api/grpcgateway/uri.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
server/v2/api/grpcgateway/uri.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

server/v2/api/grpcgateway/interceptor.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: test-system-v2
  • GitHub Check: test-integration
  • GitHub Check: golangci-lint
  • GitHub Check: Summary
🔇 Additional comments (3)
server/v2/api/grpcgateway/uri.go (1)

22-46: Consider using a deterministic iteration order

The function iterates over a map using a range loop, which could lead to non-deterministic behavior as map iteration order is random in Go.

Consider using one of these approaches:

  1. Sort the regular expressions by pattern string
  2. Use a slice of struct{pattern *regexp.Regexp; metadata queryMetadata} sorted by pattern
-func matchURL(u *url.URL, regexpToQueryMetadata map[*regexp.Regexp]queryMetadata) *uriMatch {
+type regexEntry struct {
+    pattern *regexp.Regexp
+    metadata queryMetadata
+}
+
+func matchURL(u *url.URL, regexpToQueryMetadata map[*regexp.Regexp]queryMetadata) *uriMatch {
 	uriPath := strings.TrimRight(u.Path, "/")
 	params := make(map[string]string)
+
+	// Create a sorted slice of entries
+	entries := make([]regexEntry, 0, len(regexpToQueryMetadata))
+	for pattern, metadata := range regexpToQueryMetadata {
+		entries = append(entries, regexEntry{pattern: pattern, metadata: metadata})
+	}
+	sort.Slice(entries, func(i, j int) bool {
+		return entries[i].pattern.String() < entries[j].pattern.String()
+	})
server/v2/api/grpcgateway/interceptor.go (2)

30-38: LGTM! Well-structured and documented type definition

The queryMetadata struct is well-designed with clear documentation for each field.


174-176: Clarify or remove the TODO comment about filter usage

The comment about the filter's purpose is unclear and seems to be copied from generated code. Either document its purpose clearly or consider if it's actually needed.

Let's check the grpc-gateway source code to understand the filter's purpose:

server/v2/api/grpcgateway/interceptor.go Outdated Show resolved Hide resolved
@technicallyty technicallyty changed the title refactor(server/v2): auto-gateway improvements and doc refactor(server/v2): auto-gateway improvements Jan 13, 2025
@@ -41,57 +57,77 @@ func newGatewayInterceptor[T transaction.Tx](logger log.Logger, gateway *runtime
if err != nil {
return nil, err
}
// convert the mapping to regular expressions for URL matching.
wildcardMatchers, simpleMatchers := createRegexMapping(logger, getMapping)
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

might rm this err check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, thanks - removed it in remove unncessary error check

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 (3)
server/v2/api/grpcgateway/uri.go (1)

Line range hint 65-92: Consider optimizing regex handling.

The function effectively converts URI patterns to regex patterns, but could be improved:

  1. Consider extracting regex patterns as constants for better maintainability.
  2. Consider compiling the regex patterns once at init time for better performance.

Apply this diff to optimize the implementation:

+var (
+    paramStarPattern = regexp.MustCompile(`\\\{([^}]+?)=\\\*\\\*\\}`)
+    paramNameStarPattern = regexp.MustCompile(`\\\{(.+?)=`)
+    paramPattern = regexp.MustCompile(`\\\{([^}]+)\\}`)
+    paramNamePattern = regexp.MustCompile(`\\\{(.*?)\\}`)
+)

 func patternToRegex(pattern string) (string, []string) {
     escaped := regexp.QuoteMeta(pattern)
     var wildcardNames []string

-    r1 := regexp.MustCompile(`\\\{([^}]+?)=\\\*\\\*\\}`)
-    escaped = r1.ReplaceAllStringFunc(escaped, func(match string) string {
-        name := regexp.MustCompile(`\\\{(.+?)=`).FindStringSubmatch(match)[1]
+    escaped = paramStarPattern.ReplaceAllStringFunc(escaped, func(match string) string {
+        name := paramNameStarPattern.FindStringSubmatch(match)[1]
         wildcardNames = append(wildcardNames, name)
         return "(.+)"
     })

-    r2 := regexp.MustCompile(`\\\{([^}]+)\\}`)
-    escaped = r2.ReplaceAllStringFunc(escaped, func(match string) string {
-        name := regexp.MustCompile(`\\\{(.*?)\\}`).FindStringSubmatch(match)[1]
+    escaped = paramPattern.ReplaceAllStringFunc(escaped, func(match string) string {
+        name := paramNamePattern.FindStringSubmatch(match)[1]
         wildcardNames = append(wildcardNames, name)
         return "([^/]+)"
     })
server/v2/api/grpcgateway/uri_test.go (1)

107-171: Consider adding test cases for invalid patterns.

While the current test cases are good, consider adding test cases for:

  1. Invalid wildcard syntax (e.g., unclosed braces)
  2. Empty wildcard names
  3. Duplicate wildcard names in the same pattern
server/v2/api/grpcgateway/interceptor_test.go (1)

76-181: Consider adding test cases for query parameter size limits.

While the test coverage is good, consider adding test cases for:

  1. Query parameters exceeding size limits
  2. Maximum number of query parameters
  3. Query parameters with special characters
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02deaf9 and db043fe.

📒 Files selected for processing (5)
  • server/v2/api/grpcgateway/interceptor.go (5 hunks)
  • server/v2/api/grpcgateway/interceptor_test.go (1 hunks)
  • server/v2/api/grpcgateway/server.go (1 hunks)
  • server/v2/api/grpcgateway/uri.go (1 hunks)
  • server/v2/api/grpcgateway/uri_test.go (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • server/v2/api/grpcgateway/server.go
🧰 Additional context used
📓 Path-based instructions (4)
server/v2/api/grpcgateway/interceptor_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

server/v2/api/grpcgateway/uri_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

server/v2/api/grpcgateway/interceptor.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

server/v2/api/grpcgateway/uri.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: tests (03)
  • GitHub Check: tests (02)
  • GitHub Check: tests (01)
  • GitHub Check: tests (00)
  • GitHub Check: test-simapp-v2
  • GitHub Check: test-integration
  • GitHub Check: test-system-v2
  • GitHub Check: build (arm64)
  • GitHub Check: Analyze
  • GitHub Check: build (amd64)
  • GitHub Check: golangci-lint
  • GitHub Check: Summary
🔇 Additional comments (9)
server/v2/api/grpcgateway/uri.go (2)

9-15: Well-structured type definition with clear documentation!

The separation of simple and wildcard matchers is a good design choice that optimizes performance by using O(1) lookups for simple URIs.


30-63: Excellent implementation of URL matching logic!

The method effectively handles both simple and wildcard matches, with proper prioritization of simple matches. This implementation successfully addresses the previous concern about differentiating URIs like blocks/latest and blocks/{height}.

server/v2/api/grpcgateway/uri_test.go (1)

Line range hint 14-105: Comprehensive test coverage with well-documented test cases!

The test suite effectively covers various URI matching scenarios including simple matches, wildcard matches, and edge cases.

server/v2/api/grpcgateway/interceptor_test.go (2)

21-74: Well-structured test cases with proper log output verification!

The test effectively verifies regex mapping creation and duplicate annotation detection.


183-277: Excellent test coverage for POST request handling!

The test cases effectively cover various scenarios including valid JSON, invalid JSON, and empty bodies.

server/v2/api/grpcgateway/interceptor.go (4)

28-40: Well-defined constants and types with clear documentation!

The MaxBodySize constant and queryMetadata type are well-structured and properly documented.


Line range hint 74-141: Add error handling for message creation.

The error checks for createMessageFromGetRequest and createMessageFromPostRequest are missing.

Apply this diff to add proper error handling:

 switch request.Method {
 case http.MethodGet:
     inputMsg, err = g.createMessageFromGetRequest(request.Context(), in, request, msg, match.Params)
+    if err != nil {
+        runtime.DefaultHTTPProtoErrorHandler(request.Context(), g.gateway, out, writer, request, err)
+        return
+    }
 case http.MethodPost:
     inputMsg, err = g.createMessageFromPostRequest(request.Context(), in, request, msg)
+    if err != nil {
+        runtime.DefaultHTTPProtoErrorHandler(request.Context(), g.gateway, out, writer, request, err)
+        return
+    }

143-185: Well-implemented message creation with proper size limits!

The methods effectively handle message creation with appropriate error handling and size limits.


225-263: Consider deterministic map iteration.

Map iteration in Go is non-deterministic by design, which could lead to inconsistent behavior.

Run this script to check for map iteration patterns in the codebase:

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 (1)
tests/systemtests/distribution_test.go (1)

182-182: LGTM! Consider adding a comment explaining the placeholder usage.

The consolidation of error messages improves maintainability. Consider adding a comment explaining that "NUMBER" is a placeholder replaced during testing.

+// invalidHeightOutput represents the expected error message format for invalid height values
+// where "NUMBER" serves as a placeholder for the actual invalid value
 invalidHeightOutput := `"code":"NUMBER", "details":[]interface {}{}, "message":"strconv.ParseUint: parsing \"NUMBER\": invalid syntax"`
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db043fe and 08d052e.

📒 Files selected for processing (1)
  • tests/systemtests/distribution_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/systemtests/distribution_test.go (3)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern tests/**/*: "Assess the integration and e2e test code assessing sufficient code coverage for the changes associated in the pull request"


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: tests (03)
  • GitHub Check: tests (02)
  • GitHub Check: tests (01)
  • GitHub Check: tests (00)
  • GitHub Check: Analyze
  • GitHub Check: test-simapp-v2
  • GitHub Check: test-integration
  • GitHub Check: test-system-v2
  • GitHub Check: build (amd64)
  • GitHub Check: golangci-lint
  • GitHub Check: Summary
🔇 Additional comments (1)
tests/systemtests/distribution_test.go (1)

189-189: LGTM! Test cases properly validate error handling.

The test cases effectively cover invalid height scenarios using the consolidated error message format.

To ensure comprehensive error handling coverage, verify that all similar height validation endpoints use consistent error messages:

Also applies to: 195-195

✅ Verification successful

Test properly validates height parsing errors using Go's standard error format

The test case correctly uses Go's standard strconv.ParseUint error message for invalid height values, which is appropriate for number parsing validation. No changes needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other height validation test cases to ensure consistent error handling
rg -A 3 'starting_height|ending_height' 'tests/systemtests/**/*_test.go'

Length of output: 145


Script:

#!/bin/bash
# First, find all Go test files
fd "_test\.go$" --type f

# Then search for height-related patterns and error messages
rg -U "(?s)func.*Test.*Height.*\{.*\}" --type go
rg "invalid.*height" --type go

Length of output: 86328


Script:

#!/bin/bash
# Search for invalidHeightOutput variable definition
rg -A 2 "invalidHeightOutput.*=" tests/systemtests/

Length of output: 351

@julienrbrt julienrbrt added the backport/v0.52.x PR scheduled for inclusion in the v0.52's next stable release label Jan 13, 2025
@julienrbrt
Copy link
Member

Adding backport label for the system tests backport

Copy link
Member

@julienrbrt julienrbrt left a comment

Choose a reason for hiding this comment

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

👏🏾

return input, nil
}

func (g *gatewayInterceptor[T]) createMessageFromGetRequest(_ context.Context, _ runtime.Marshaler, req *http.Request, input gogoproto.Message, wildcardValues map[string]string) (gogoproto.Message, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need the context.Context argument for these create* functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines 177 to 178
// im not really sure what this filter is for, but defaulting it like so doesn't seem to break anything.
// pb.gw.go code uses it in a few queries, but it's not clear what actual behavior is gained from this.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should either remove this comment/logic or find the real reason we are including this code. Let's not add code we don't understand

Copy link
Contributor Author

Choose a reason for hiding this comment

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

whoops, forgot to get back to that one. updated in construct filter value

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 (6)
server/v2/api/grpcgateway/interceptor_test.go (4)

20-73: Enhance test coverage with additional test cases.

Consider adding the following test scenarios:

  1. Invalid regex patterns in annotations
  2. Empty annotation strings
  3. Overlapping patterns that could cause ambiguous matches

75-178: Add test cases for edge cases in GET request handling.

Consider adding test cases for:

  1. URL-encoded parameters with special characters
  2. Multiple occurrences of the same query parameter
  3. Nested query parameters with type mismatches

180-273: Extend POST request test coverage.

Add test cases to verify:

  1. Request body size limit enforcement
  2. Content-type header validation
  3. JSON with valid syntax but invalid field types
  4. Large nested JSON structures approaching size limits

278-313: Improve test type implementations.

The proto.Message interface implementations could be more realistic:

  1. String() methods should return meaningful string representations
  2. Reset() methods should properly reset all fields to zero values
server/v2/api/grpcgateway/interceptor.go (2)

108-112: Enhance error messages in error handling.

Consider providing more descriptive error messages that include:

  1. The specific validation that failed
  2. The expected format or constraints
  3. The actual value that caused the error

142-156: Add Content-Type validation and improve error messages.

  1. Add Content-Type validation to ensure only supported content types are accepted
  2. Include the content type in error messages when validation fails
  3. Enhance the size limit error message to suggest breaking down large requests
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b85a1c and 71dc664.

📒 Files selected for processing (2)
  • server/v2/api/grpcgateway/interceptor.go (5 hunks)
  • server/v2/api/grpcgateway/interceptor_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
server/v2/api/grpcgateway/interceptor_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

server/v2/api/grpcgateway/interceptor.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: repo-analysis
  • GitHub Check: test-system-v2
  • GitHub Check: Analyze
  • GitHub Check: Summary

server/v2/api/grpcgateway/interceptor.go Show resolved Hide resolved
server/v2/api/grpcgateway/interceptor.go Dismissed Show dismissed Hide dismissed
@julienrbrt julienrbrt added this pull request to the merge queue Jan 13, 2025
Merged via the queue into main with commit b461a31 Jan 13, 2025
71 of 72 checks passed
@julienrbrt julienrbrt deleted the technicallyty/23188-gateway-improvements branch January 13, 2025 21:20
mergify bot pushed a commit that referenced this pull request Jan 13, 2025
Co-authored-by: Alex | Interchain Labs <[email protected]>
(cherry picked from commit b461a31)

# Conflicts:
#	server/v2/api/grpcgateway/interceptor.go
#	server/v2/api/grpcgateway/server.go
#	server/v2/api/grpcgateway/uri.go
#	server/v2/api/grpcgateway/uri_test.go
julienrbrt added a commit that referenced this pull request Jan 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/v0.52.x PR scheduled for inclusion in the v0.52's next stable release C:server/v2 api C:server/v2 Issues related to server/v2
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants