-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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: wire v2 handlers #22112
feat: wire v2 handlers #22112
Conversation
📝 Walkthrough📝 WalkthroughWalkthroughThe pull request focuses on updates to the Changes
Possibly related PRs
Suggested labels
Suggested reviewers
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this 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 (3)
server/v2/api/rest/config.go (2)
12-18
: LGTM with a minor suggestion: Config struct is well-defined.The
Config
struct is well-documented and properly annotated for configuration parsing. The field names and types are appropriate for their purposes.Consider updating the comment for the
Config
struct to use "REST server" instead of "REST server" for consistency with the component name, as suggested in a past review comment:- // Config defines configuration for the REST server. + // Config defines configuration for the REST server.
27-32
: LGTM with a minor suggestion: Disable function is well-implemented.The
Disable
function provides a convenient way to disable the REST server and is implemented correctly.Consider updating the comment to improve clarity:
- // Disable the rest server by default (default enabled). + // Disable returns a CfgOption that disables the REST server.This change more accurately describes the function's behavior and purpose.
server/v2/api/rest/README.md (1)
60-73
: LGTM: Helpful curl example, minor formatting fix neededThe Using Tools section provides a clear and helpful example of how to use curl to interact with the API. The curl command is well-formatted and easy to understand.
Please add a newline character at the end of the file to comply with the Markdown linting rules:
}'
<details> <summary>🧰 Tools</summary> <details> <summary>🪛 Markdownlint</summary><blockquote> 73-73: null Files should end with a single newline character (MD047, single-trailing-newline) </blockquote></details> </details> </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: .coderabbit.yml** **Review profile: CHILL** <details> <summary>📥 Commits</summary> Files that changed from the base of the PR and between 40b5baed095db387b55980be0229ccee33f43df5 and 506267d2efaf2417103a4b59c98f76246e01ce2e. </details> <details> <summary>📒 Files selected for processing (6)</summary> * runtime/v2/go.mod (2 hunks) * server/v2/api/rest/README.md (1 hunks) * server/v2/api/rest/config.go (1 hunks) * server/v2/api/rest/handler.go (1 hunks) * server/v2/api/rest/server.go (1 hunks) * simapp/v2/simdv2/cmd/commands.go (2 hunks) </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary> * runtime/v2/go.mod * server/v2/api/rest/server.go * simapp/v2/simdv2/cmd/commands.go </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>📓 Path-based instructions (3)</summary><blockquote> <details> <summary>server/v2/api/rest/README.md (1)</summary> Pattern `**/*.md`: "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness" </details> <details> <summary>server/v2/api/rest/config.go (1)</summary> Pattern `**/*.go`: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations. </details> <details> <summary>server/v2/api/rest/handler.go (1)</summary> Pattern `**/*.go`: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations. </details> </blockquote></details> <details> <summary>🪛 LanguageTool</summary><blockquote> <details> <summary>server/v2/api/rest/README.md</summary><blockquote> [grammar] ~7-~7: The usual collocation for “returned” is “to”, not “in”. Context: ...ol message (`proto`), and responses are returned in JSON format. ## Example ### 1. `Query... (RETURN_IN_THE) --- [uncategorized] ~32-~32: Loose punctuation mark. Context: ..._DENOMINATION>" } ``` - `address`: Account address on the Cosmos network. ... (UNLIKELY_OPENING_PUNCTUATION) --- [uncategorized] ~33-~33: Loose punctuation mark. Context: ...dress on the Cosmos network. - `denom`: Token denomination (e.g., `stake`). - ... (UNLIKELY_OPENING_PUNCTUATION) </blockquote></details> </blockquote></details> <details> <summary>🪛 Markdownlint</summary><blockquote> <details> <summary>server/v2/api/rest/README.md</summary><blockquote> 15-15: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 17-17: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 19-19: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 21-21: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 23-23: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 32-32: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 33-33: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 35-35: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 47-47: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 21-21: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 32-32: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 33-33: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 37-37: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 73-73: null Files should end with a single newline character (MD047, single-trailing-newline) </blockquote></details> </blockquote></details> </details> <details> <summary>🔇 Additional comments (7)</summary><blockquote> <details> <summary>server/v2/api/rest/config.go (3)</summary><blockquote> `3-8`: **LGTM: Default configuration looks good.** The `DefaultConfig` function provides sensible default values for the REST server configuration. Enabling the server by default and using "localhost:8080" as the default address is a common and reasonable choice for local development. --- `10-10`: **LGTM: Good use of functional options pattern.** The `CfgOption` type alias is well-defined and follows the functional options pattern, which is a good practice in Go for flexible and extensible configuration. --- `20-25`: **LGTM: OverwriteDefaultConfig function implemented as requested.** The `OverwriteDefaultConfig` function has been implemented correctly, addressing the request from a previous review comment. It properly overwrites the entire configuration, and the function name and behavior match the provided comment. </blockquote></details> <details> <summary>server/v2/api/rest/README.md (2)</summary><blockquote> `5-7`: **LGTM: Clear and concise General Description** The General Description section provides a clear and concise overview of the service's functionality. It effectively communicates the purpose and basic operation of the API. <details> <summary>🧰 Tools</summary> <details> <summary>🪛 LanguageTool</summary><blockquote> [grammar] ~7-~7: The usual collocation for “returned” is “to”, not “in”. Context: ...ol message (`proto`), and responses are returned in JSON format. ## Example ### 1. `Query... (RETURN_IN_THE) </blockquote></details> </details> --- `1-73`: **Excellent documentation for the Cosmos SDK REST API** This README provides a comprehensive and well-structured overview of the Cosmos SDK REST API. It effectively covers all the essential aspects: 1. A clear introduction and general description of the service. 2. A detailed example demonstrating the usage of a specific endpoint (`QueryBalanceRequest`). 3. Practical information on using tools like curl to interact with the API. The document is informative and will be very helpful for developers working with the Cosmos SDK REST API. The minor formatting and grammar issues mentioned in previous comments are the only improvements needed. Great job on creating this valuable documentation! <details> <summary>🧰 Tools</summary> <details> <summary>🪛 LanguageTool</summary><blockquote> [grammar] ~7-~7: The usual collocation for “returned” is “to”, not “in”. Context: ...ol message (`proto`), and responses are returned in JSON format. ## Example ### 1. `Query... (RETURN_IN_THE) --- [uncategorized] ~32-~32: Loose punctuation mark. Context: ..._DENOMINATION>" } ``` - `address`: Account address on the Cosmos network. ... (UNLIKELY_OPENING_PUNCTUATION) --- [uncategorized] ~33-~33: Loose punctuation mark. Context: ...dress on the Cosmos network. - `denom`: Token denomination (e.g., `stake`). - ... (UNLIKELY_OPENING_PUNCTUATION) </blockquote></details> <details> <summary>🪛 Markdownlint</summary><blockquote> 15-15: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 17-17: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 19-19: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 21-21: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 23-23: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 32-32: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 33-33: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 35-35: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 47-47: Expected: asterisk; Actual: dash Unordered list style (MD004, ul-style) --- 21-21: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 32-32: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 33-33: Expected: 4; Actual: 2 Unordered list indentation (MD007, ul-indent) --- 37-37: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 73-73: null Files should end with a single newline character (MD047, single-trailing-newline) </blockquote></details> </details> </blockquote></details> <details> <summary>server/v2/api/rest/handler.go (2)</summary><blockquote> `13-14`: **Previous suggestion on replacing deprecated `jsonpb` is still applicable** The use of `github.com/cosmos/gogoproto/jsonpb` is deprecated. Consider replacing it with `google.golang.org/protobuf/encoding/protojson` for better maintainability. --- `85-86`: **Minimize the use of reflection for better performance and safety** Using reflection can impact performance and may introduce runtime errors. Consider alternative methods to create new message instances without reflection, such as maintaining a registry or map of constructor functions keyed by message type. </blockquote></details> </blockquote></details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
# Cosmos SDK REST API | ||
|
||
This document describes how to use a service that exposes endpoints based on Cosmos SDK Protobuf message types. Each endpoint responds with data in JSON format. | ||
|
||
## General Description | ||
|
||
The service allows querying the blockchain using any type of Protobuf message available in the Cosmos SDK application through HTTP `POST` requests. Each endpoint corresponds to a Cosmos SDK protocol message (`proto`), and responses are returned in JSON format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve grammar in the introduction
The introduction is clear and informative. However, there's a minor grammar issue in the last sentence.
Apply this change to improve the grammar:
-The service allows querying the blockchain using any type of Protobuf message available in the Cosmos SDK application through HTTP `POST` requests. Each endpoint corresponds to a Cosmos SDK protocol message (`proto`), and responses are returned in JSON format.
+The service allows querying the blockchain using any type of Protobuf message available in the Cosmos SDK application through HTTP `POST` requests. Each endpoint corresponds to a Cosmos SDK protocol message (`proto`), and responses are returned as JSON format.
📝 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.
# Cosmos SDK REST API | |
This document describes how to use a service that exposes endpoints based on Cosmos SDK Protobuf message types. Each endpoint responds with data in JSON format. | |
## General Description | |
The service allows querying the blockchain using any type of Protobuf message available in the Cosmos SDK application through HTTP `POST` requests. Each endpoint corresponds to a Cosmos SDK protocol message (`proto`), and responses are returned in JSON format. | |
# Cosmos SDK REST API | |
This document describes how to use a service that exposes endpoints based on Cosmos SDK Protobuf message types. Each endpoint responds with data in JSON format. | |
## General Description | |
The service allows querying the blockchain using any type of Protobuf message available in the Cosmos SDK application through HTTP `POST` requests. Each endpoint corresponds to a Cosmos SDK protocol message (`proto`), and responses are returned as JSON format. |
🧰 Tools
🪛 LanguageTool
[grammar] ~7-~7: The usual collocation for “returned” is “to”, not “in”.
Context: ...ol message (proto
), and responses are returned in JSON format. ## Example ### 1. `Query...(RETURN_IN_THE)
|
||
msg, err := h.createMessage(r) | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid exposing internal error details to clients
Revealing internal error messages to clients can expose sensitive information. Return a generic error message to the client and log the detailed error internally.
Apply this diff to return a generic error message:
- http.Error(w, err.Error(), http.StatusBadRequest)
+ http.Error(w, "Bad Request", http.StatusBadRequest)
📝 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.
http.Error(w, err.Error(), http.StatusBadRequest) | |
http.Error(w, "Bad Request", http.StatusBadRequest) |
|
||
w.Header().Set("Content-Type", ContentTypeJSON) | ||
if err := json.NewEncoder(w).Encode(query); err != nil { | ||
http.Error(w, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid exposing internal error details when encoding response
Including internal error details in the HTTP response may leak sensitive information. Return a generic error message to the client and log the detailed error internally.
Apply this diff to return a generic error message:
- http.Error(w, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
+ http.Error(w, "Internal Server Error", http.StatusInternalServerError)
📝 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.
http.Error(w, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError) | |
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
server/v2/api/rest/handler.go
Outdated
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"reflect" | ||
"strings" | ||
|
||
"cosmossdk.io/core/transaction" | ||
"cosmossdk.io/server/v2/appmanager" | ||
"github.com/cosmos/gogoproto/jsonpb" | ||
gogoproto "github.com/cosmos/gogoproto/proto" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reorganize imports according to Go import conventions
To conform with the Uber Go Style Guide, organize imports into three groups separated by blank lines: standard library packages, third-party packages, and local packages.
Apply this diff to reorganize the imports:
import (
"encoding/json"
"fmt"
"io"
"net/http"
"reflect"
"strings"
+ gogoproto "github.com/cosmos/gogoproto/proto"
+ "github.com/cosmos/gogoproto/jsonpb"
+ "cosmossdk.io/core/transaction"
+ "cosmossdk.io/server/v2/appmanager"
)
📝 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.
import ( | |
"encoding/json" | |
"fmt" | |
"io" | |
"net/http" | |
"reflect" | |
"strings" | |
"cosmossdk.io/core/transaction" | |
"cosmossdk.io/server/v2/appmanager" | |
"github.com/cosmos/gogoproto/jsonpb" | |
gogoproto "github.com/cosmos/gogoproto/proto" | |
) | |
import ( | |
"encoding/json" | |
"fmt" | |
"io" | |
"net/http" | |
"reflect" | |
"strings" | |
gogoproto "github.com/cosmos/gogoproto/proto" | |
"github.com/cosmos/gogoproto/jsonpb" | |
"cosmossdk.io/core/transaction" | |
"cosmossdk.io/server/v2/appmanager" | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit, for consistency for the other, can we get the logger error lowercase?
additionally, could you fix conflicts?
There was a problem hiding this 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
📜 Review details
Configuration used: .coderabbit.yml
Review profile: CHILL
📒 Files selected for processing (2)
- server/v2/api/rest/handler.go (1 hunks)
- server/v2/api/rest/server.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- server/v2/api/rest/server.go
🧰 Additional context used
📓 Path-based instructions (1)
server/v2/api/rest/handler.go (1)
Pattern
**/*.go
: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.
query, err := h.appManager.Query(r.Context(), 0, msg) | ||
if err != nil { | ||
http.Error(w, "Error querying", http.StatusInternalServerError) | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log internal errors for better diagnostics
In the ServeHTTP
method, when h.appManager.Query
returns an error, the error is not logged. Logging internal errors while returning a generic message to the client aids in debugging without exposing sensitive information.
Apply this diff to log the error internally:
if err != nil {
+ log.Printf("Error querying: %v", err)
http.Error(w, "Error querying", http.StatusInternalServerError)
return
}
📝 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.
query, err := h.appManager.Query(r.Context(), 0, msg) | |
if err != nil { | |
http.Error(w, "Error querying", http.StatusInternalServerError) | |
return | |
} | |
query, err := h.appManager.Query(r.Context(), 0, msg) | |
if err != nil { | |
log.Printf("Error querying: %v", err) | |
http.Error(w, "Error querying", http.StatusInternalServerError) | |
return | |
} |
err := jsonpb.Unmarshal(limitedReader, msg) | ||
if err != nil { | ||
return nil, fmt.Errorf("error parsing body: %w", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use io.ReadAll
for better error handling
Reading from io.LimitReader
and then unmarshalling can lead to partial reads if the body exceeds the MaxBodySize
. Instead, read the full body into a byte slice and check for io.EOF
to ensure the entire body is read.
Apply this diff to improve request body handling:
defer r.Body.Close()
-limitedReader := io.LimitReader(r.Body, MaxBodySize)
-err := jsonpb.Unmarshal(limitedReader, msg)
+body, err := io.ReadAll(io.LimitReader(r.Body, MaxBodySize))
+if err != nil {
+ return nil, fmt.Errorf("error reading body: %w", err)
+}
+err = jsonpb.Unmarshal(bytes.NewReader(body), msg)
if err != nil {
return nil, fmt.Errorf("error parsing body: %w", err)
}
Don't forget to import the bytes
package:
import (
"encoding/json"
"fmt"
"io"
+ "bytes"
"net/http"
📝 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.
err := jsonpb.Unmarshal(limitedReader, msg) | |
if err != nil { | |
return nil, fmt.Errorf("error parsing body: %w", err) | |
} | |
body, err := io.ReadAll(io.LimitReader(r.Body, MaxBodySize)) | |
if err != nil { | |
return nil, fmt.Errorf("error reading body: %w", err) | |
} | |
err = jsonpb.Unmarshal(bytes.NewReader(body), msg) | |
if err != nil { | |
return nil, fmt.Errorf("error parsing body: %w", err) | |
} |
if r.Method != http.MethodPost { | ||
return fmt.Errorf("method not allowed") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error message for unsupported methods
In the validateMethodIsPOST
function, the error message "method not allowed" lacks specificity. To enhance clarity and adhere to Go's error handling conventions, consider returning the HTTP status text corresponding to the error.
Apply this diff to improve the error message:
- return fmt.Errorf("method not allowed")
+ return fmt.Errorf(http.StatusText(http.StatusMethodNotAllowed))
📝 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.
if r.Method != http.MethodPost { | |
return fmt.Errorf("method not allowed") | |
} | |
if r.Method != http.MethodPost { | |
return fmt.Errorf(http.StatusText(http.StatusMethodNotAllowed)) | |
} |
path := strings.TrimPrefix(r.URL.Path, "/") | ||
requestType := gogoproto.MessageType(path) | ||
if requestType == nil { | ||
return nil, fmt.Errorf("unknown request type") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate and sanitize request path
Using r.URL.Path
directly can lead to security issues if the path contains unexpected segments or escape characters. Ensure the path is sanitized and validated to prevent potential misuse.
Consider applying this diff to safely extract the message type:
path := strings.TrimPrefix(r.URL.Path, "/")
+if path == "" {
+ return nil, fmt.Errorf("request path cannot be empty")
+}
+if strings.Contains(path, "/") {
+ return nil, fmt.Errorf("invalid request path")
+}
requestType := gogoproto.MessageType(path)
if requestType == nil {
return nil, fmt.Errorf("unknown request type")
}
📝 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.
path := strings.TrimPrefix(r.URL.Path, "/") | |
requestType := gogoproto.MessageType(path) | |
if requestType == nil { | |
return nil, fmt.Errorf("unknown request type") | |
} | |
path := strings.TrimPrefix(r.URL.Path, "/") | |
if path == "" { | |
return nil, fmt.Errorf("request path cannot be empty") | |
} | |
if strings.Contains(path, "/") { | |
return nil, fmt.Errorf("invalid request path") | |
} | |
requestType := gogoproto.MessageType(path) | |
if requestType == nil { | |
return nil, fmt.Errorf("unknown request type") | |
} |
contentType := r.Header.Get("Content-Type") | ||
if contentType != ContentTypeJSON { | ||
return fmt.Errorf("unsupported content type, expected %s", ContentTypeJSON) | ||
} | ||
|
||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle Content-Type header with parameters
The current validation checks if the Content-Type
header exactly matches application/json
. However, Content-Type
may include parameters like charset=utf-8
, causing valid requests to fail. Use mime.ParseMediaType
to robustly parse the media type.
Apply this diff to enhance content type validation:
-import "strings"
+import (
+ "mime"
+ "strings"
+)
func (h *DefaultHandler[T]) validateContentTypeIsJSON(r *http.Request) error {
contentType := r.Header.Get("Content-Type")
- if contentType != ContentTypeJSON {
+ mediaType, _, err := mime.ParseMediaType(contentType)
+ if err != nil || mediaType != ContentTypeJSON {
return fmt.Errorf("unsupported content type, expected %s", ContentTypeJSON)
}
Committable suggestion was skipped due to low confidence.
Description
ref: #21682
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...
!
in the type prefix if API or client breaking changeCHANGELOG.md
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...
Summary by CodeRabbit
New Features
QueryBalanceRequest
endpoint.Documentation