Skip to content

Conversation

@joyguptaa
Copy link
Contributor

@joyguptaa joyguptaa commented Mar 17, 2025

Date: 17 Mar 2025
Developer Name: Joy Gupta


Issue Ticket Number

Description

Added functionality to send user Discord data to an external API. This includes generating an authorization token, constructing the data payload, and making a POST request to the external API endpoint.

Documentation Updated?

  • Yes
  • No

Under Feature Flag

  • Yes
  • No

Database Changes

  • Yes
  • No

Breaking Changes

  • Yes
  • No

Development Tested?

  • Yes
  • No

Test Coverage

Screenshot 2025-05-07 at 12 11 03 AM Screenshot 2025-05-07 at 12 10 20 AM

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

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

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

Summary by CodeRabbit

  • New Features

    • Introduced an API utility that streamlines API calls by automatically configuring request headers and ensuring robust error handling.
  • Tests

    • Added comprehensive tests to verify API call operations and header configurations, ensuring enhanced reliability and performance.

Walkthrough

The changes introduce a new WebsiteBackend struct in the helper module with three fields: AuthToken, Method, and URL. Two methods, MakeAPICall and PrepareHeaders, are added to handle API calls by marshaling request bodies into JSON, setting HTTP headers (including an optional Authorization header), and executing the HTTP request. Corresponding tests in the helper test file verify successful calls and error handling for JSON marshaling and HTTP request creation.

Changes

File Changes Summary
utils/helper.go Added new WebsiteBackend struct with fields AuthToken, Method, and URL. Implemented MakeAPICall (handles JSON marshalling, HTTP request creation, header setup, and error logging) and PrepareHeaders (sets "Content-Type" and optional "Authorization" headers).
utils/helper_test.go Added tests: TestMakeAPICall (validates successful API call, JSON marshalling error, and HTTP request creation failure) and TestPrepareHeaders (ensures proper header settings for GET requests and with provided AuthToken).

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant WebsiteBackend
    participant HTTPClient

    Caller->>WebsiteBackend: MakeAPICall(body)
    WebsiteBackend->>WebsiteBackend: json.Marshal(body)
    alt Marshaling Fails
        WebsiteBackend-->>Caller: Return error and nil response
    else
        WebsiteBackend->>WebsiteBackend: Create HTTP Request
        WebsiteBackend->>WebsiteBackend: PrepareHeaders(req)
        WebsiteBackend->>HTTPClient: Execute HTTP Request
        HTTPClient-->>WebsiteBackend: Return response
        WebsiteBackend-->>Caller: Return response
    end
Loading

Poem

I'm a rabbit, hopping through the code so neat,
With new API calls, my joy can't be beat.
JSON whispers softly as headers align,
Errors are dodged in a merry design.
Code leaps ahead with a bound and a cheer—
Happy hops for us all, let's code without fear! 🐇


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecf9b55 and fc25395.

📒 Files selected for processing (2)
  • utils/helper.go (2 hunks)
  • utils/helper_test.go (2 hunks)
🔇 Additional comments (4)
utils/helper.go (2)

14-18: Good struct design with appropriate fields for API calls

The WebsiteBackend struct has a clean design with all necessary fields for making API calls. Making AuthToken a pointer allows for optional authentication while Method and URL provide the essential HTTP request information.


49-54: Authorization header implementation is secure

The PrepareHeaders method correctly sets the Content-Type header and uses the secure Bearer token format for authorization when a token is provided.

utils/helper_test.go (2)

112-135: Well-structured tests for PrepareHeaders

The tests for PrepareHeaders are thorough, covering both scenarios with and without an auth token. The assertions effectively verify the expected header values.


91-92: Good use of unmarshalable type for error testing

Using a channel as test input is an excellent way to force a JSON marshaling error, as channels cannot be marshaled to JSON. This effectively tests the error handling path.

@joyguptaa joyguptaa requested a review from Devashish08 March 18, 2025 17:13
Copy link

@amit-flx amit-flx left a comment

Choose a reason for hiding this comment

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

why we are not adding any documentation, do we don't need this, is that design doc PRD ownership has been moved to RDS

@joyguptaa
Copy link
Contributor Author

why we are not adding any documentation, do we don't need this, is that design doc PRD ownership has been moved to RDS

it only includes ENV this env variable. And that is already mentioned in the .env.example and also in README.

@iamitprakash
Copy link
Member

iamitprakash commented Mar 23, 2025

why we are not adding any documentation, do we don't need this, is that design doc PRD ownership has been moved to RDS

it only includes ENV this env variable. And that is already mentioned in the .env.example and also in README.

what about earlier created docs, please re-read whole line before replying half

@joyguptaa
Copy link
Contributor Author

joyguptaa commented Mar 23, 2025

why we are not adding any documentation, do we don't need this, is that design doc PRD ownership has been moved to RDS

it only includes ENV this env variable. And that is already mentioned in the .env.example and also in README.

what about earlier created docs, please re-read whole line before replying half

I've sent the request to transfer the ownership of the docs mentioned below to [email protected]
RealDevSquad/todo-action-items#235 (comment)

Let me know if there's anything missing. I can add that as well

@joyguptaa joyguptaa requested a review from iamitprakash April 1, 2025 09:16
@RealDevSquad RealDevSquad deleted a comment from joyguptaa Apr 29, 2025
return err
}

func (hcp *HTTPClientService) prepareRequest(body interface{}) (*http.Request, error) {
Copy link
Member

Choose a reason for hiding this comment

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

any reason to use base data type not for going with struct or something else, base data come with certain added disadvantages

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The purpose of this function is to make API calls to external services, where request and response structures can vary widely. Binding specific types within the function would limit its flexibility and reusability. By using interface{}, the responsibility of type binding is delegated to the caller, ensuring the utility remains generic and adaptable across diverse use cases.

Copy link
Member

@iamitprakash iamitprakash May 13, 2025

Choose a reason for hiding this comment

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

If we can't determine contract structure no point of writing this

return req, nil
}

func (hcp *HTTPClientService) readResponseBody(resp *http.Response, result interface{}) error {
Copy link
Member

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same reason : #68 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

return nil
}

func (hcp *HTTPClientService) MakeAPICall(body interface{}, result interface{}) error {
Copy link
Member

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same reason : #68 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

"github.com/stretchr/testify/assert"
)

type MockHTTPClient struct {
Copy link
Member

Choose a reason for hiding this comment

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

is this for unit test or integration test, I need clear segregation b/w unit test and integration test

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did not understand what exact change you are asking for.
Since this file is a unit test file, should I rename this file and add unit in between? or what else is required here?

Copy link
Member

Choose a reason for hiding this comment

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

for unit test why need to mock http client and where is code for integration tests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's making an api call. How do I test for success scenarios without mocking the server?

Copy link
Member

Choose a reason for hiding this comment

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

is this part of unit test or integration test

URL: mockServer.URL,
}
originalTimeout := config.AppConfig.TIMEOUT
config.AppConfig.TIMEOUT = 2
Copy link
Contributor

Choose a reason for hiding this comment

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

The timeout value is set to 2 without a time unit, which defaults to 2 nanoseconds. This is unrealistically short for an HTTP request test and will cause flaky test failures. Consider using a more appropriate duration like 2 * time.Millisecond or 50 * time.Millisecond to ensure consistent test behavior while still failing quickly when needed.

Suggested change
config.AppConfig.TIMEOUT = 2
config.AppConfig.TIMEOUT = 50 * time.Millisecond

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.


t.Run("should return error if response does not matches with the provided dto", func(t *testing.T) {
result := &TestResponse{}
mockServer := MakeMockServer(`{success:false}`, http.StatusInternalServerError)
Copy link
Contributor

Choose a reason for hiding this comment

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

The JSON string is malformed and will cause parsing errors. Keys in JSON must be enclosed in double quotes. Please update to {"success":false} instead of {success:false}.

Suggested change
mockServer := MakeMockServer(`{success:false}`, http.StatusInternalServerError)
mockServer := MakeMockServer(`{"success":false}`, http.StatusInternalServerError)

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +66 to +84
func (hcp *HTTPClientService) MakeAPICall(body interface{}, result interface{}) error {
req, err := hcp.prepareRequest(body)
if err != nil {
return err
}

client := &http.Client{
Timeout: config.AppConfig.TIMEOUT,
}

resp, err := client.Do(req)
if err != nil {
logrus.Errorf("Failed to make request: %v", err)
return err
}

defer resp.Body.Close()
return hcp.readResponseBody(resp, result)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The MakeAPICall method should validate HTTP status codes before processing the response. Currently, it attempts to parse the response body regardless of status code, which could lead to unexpected behavior with error responses (4xx/5xx). Consider adding status code validation to ensure only successful responses (2xx) are processed, while returning appropriate errors for other status codes:

resp, err := client.Do(req)
if err != nil {
    logrus.Errorf("Failed to make request: %v", err)
    return err
}
defer resp.Body.Close()

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
    return fmt.Errorf("API returned non-success status code: %d", resp.StatusCode)
}

return hcp.readResponseBody(resp, result)
Suggested change
func (hcp *HTTPClientService) MakeAPICall(body interface{}, result interface{}) error {
req, err := hcp.prepareRequest(body)
if err != nil {
return err
}
client := &http.Client{
Timeout: config.AppConfig.TIMEOUT,
}
resp, err := client.Do(req)
if err != nil {
logrus.Errorf("Failed to make request: %v", err)
return err
}
defer resp.Body.Close()
return hcp.readResponseBody(resp, result)
}
func (hcp *HTTPClientService) MakeAPICall(body interface{}, result interface{}) error {
req, err := hcp.prepareRequest(body)
if err != nil {
return err
}
client := &http.Client{
Timeout: config.AppConfig.TIMEOUT,
}
resp, err := client.Do(req)
if err != nil {
logrus.Errorf("Failed to make request: %v", err)
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("API returned non-success status code: %d", resp.StatusCode)
}
return hcp.readResponseBody(resp, result)
}

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

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.

6 participants